Skip to content

Commit

Permalink
add support for inline terms (DefAlias rules) and source references
Browse files Browse the repository at this point in the history
  • Loading branch information
mengwong committed Oct 20, 2021
1 parent cfde6dc commit df58c28
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 18 deletions.
25 changes: 16 additions & 9 deletions mengwong/mp/src/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import Control.Monad.Reader (ReaderT(runReaderT), asks, MonadReader (local))
someFunc :: IO ()
someFunc = do
mpd <- lookupEnv "MP_DEBUG"
let runConfig = RC (maybe False (read :: String -> Bool) mpd) 0 []
let runConfig = RC (maybe False (read :: String -> Bool) mpd) 0 [] "STDIN"
myinput <- BS.getContents
runExample runConfig myinput

Expand Down Expand Up @@ -324,7 +324,7 @@ pConstitutiveRule = debugName "pConstitutiveRule" $ do
myTraceM $ "pConstitutiveRule: matched defWord " ++ show defWord
myTraceM $ "pConstitutiveRule: \"" ++ Text.unpack term ++ "\" " ++ show defWord ++ "..."
(ands,rs) <- withDepth leftX dBoolRules -- (foo AND (bar OR baz), [constitutive and regulative sub-rules])
return $ Constitutive term ands Nothing Nothing : rs
return $ Constitutive term ands Nothing Nothing Nothing : rs

pRegRule :: Parser [Rule]
pRegRule = debugName "pRegRule" $ try pRegRuleSugary <|> pRegRuleNormal
Expand Down Expand Up @@ -354,7 +354,7 @@ pRegRuleSugary = debugName "pRegRuleSugary" $ do
(rbdeon rulebody)
(rbaction rulebody)
(rbtemporal rulebody)
Nothing Nothing Nothing Nothing
Nothing Nothing Nothing Nothing Nothing
myTraceM $ "pRegRuleSugary: the specifier is " ++ show who
myTraceM $ "pRegRuleSugary: returning " ++ show toreturn
myTraceM $ "pRegRuleSugary: with appendix brs = " ++ show brs
Expand All @@ -371,8 +371,9 @@ pRegRuleSugary = debugName "pRegRuleSugary" $ do
pRegRuleNormal :: Parser [Rule]
pRegRuleNormal = debugName "pRegRuleNormal" $ do
leftX <- lookAhead pXLocation -- this is the column where we expect IF/AND/OR etc.
leftY <- lookAhead pYLocation
checkDepth
(_party_every, entitytype) <- pActor Party <|> pActor Every
(_party_every, entitytype, entityalias) <- pActor Party <|> pActor Every
-- (Who, (BoolStruct,[Rule]))
whoBool <- optional (withDepth leftX (preambleBoolRules [Who]))
-- the below are going to be permutables
Expand All @@ -383,6 +384,9 @@ pRegRuleNormal = debugName "pRegRuleNormal" $ do
myTraceM $ "pRegRuleNormal: permutations returned rulebody " ++ show rulebody
let (who, (cbs, brs)) = mergePBRS (if null (rbpbrs rulebody) then [(Always, (Nothing, []))] else rbpbrs rulebody)
let (ewho, (ebs, ebrs)) = fromMaybe (Always, (Nothing, [])) whoBool
srcurl <- asks sourceURL
let srcref = SrcRef srcurl srcurl leftX leftY Nothing
let defalias = maybe [] (\t -> pure (DefTermAlias t entitytype Nothing (Just srcref))) entityalias
let toreturn = Regulative
entitytype
(newPre (Text.pack $ show ewho) <$> ebs)
Expand All @@ -394,10 +398,11 @@ pRegRuleNormal = debugName "pRegRuleNormal" $ do
lestLimb
Nothing -- rule label
Nothing -- legal source
Nothing -- internal SrcRef
myTraceM $ "pRegRuleNormal: the specifier is " ++ show who
myTraceM $ "pRegRuleNormal: returning " ++ show toreturn
myTraceM $ "pRegRuleNormal: with appendix brs = " ++ show brs
return ( toreturn : brs ++ ebrs )
return ( toreturn : brs ++ ebrs ++ defalias )

pHenceLest :: MyToken -> Parser [Rule]
pHenceLest henceLest = debugName ("pHenceLest-" ++ show henceLest) $ do
Expand Down Expand Up @@ -425,12 +430,14 @@ pTemporal = ( do
t2 <- pOtherVal
return $ mkTC t1 t2

-- "PARTY Seller"
-- "PARTY Bob (the "Seller")
-- "EVERY Seller"
pActor :: MyToken -> Parser (MyToken, Text.Text)
pActor :: MyToken -> Parser (MyToken, Text.Text, Maybe Text.Text)
pActor party = do
entitytype <- pToken party *> pOtherVal <* dnl
return (party, entitytype)
entitytype <- pToken party *> pOtherVal
entityalias <- optional pOtherVal
_ <- dnl
return (party, entitytype, entityalias)

pDoAction :: Parser ActionType
pDoAction = pToken Do >> pAction
Expand Down
19 changes: 18 additions & 1 deletion mengwong/mp/src/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ data Rule = Regulative
, lest :: Maybe [Rule]
, rlabel :: Maybe Text.Text
, lsource :: Maybe Text.Text
, srcref :: Maybe SrcRef
}
| Constitutive
{ term :: ConstitutiveTerm
, cond :: Maybe BoolStruct
, rlabel :: Maybe Text.Text
, lsource :: Maybe Text.Text
, srcref :: Maybe SrcRef
}
| DefTermAlias -- inline alias, like some thing ("Thing")
{ term :: ConstitutiveTerm -- "Thing"
, detail :: Text.Text -- "some thing"
, nlhint :: Maybe Text.Text -- "lang=en number=singular"
, srcref :: Maybe SrcRef
}
| RegAlias Text.Text -- internal softlink to a regulative rule label
| ConAlias Text.Text -- internal softlink to a constitutive rule label
Expand All @@ -60,6 +63,14 @@ type BoolStruct = AA.Item Text.Text
data Deontic = DMust | DMay | DShant
deriving (Eq, Show)

data SrcRef = SrcRef { url :: Text.Text
, short :: Text.Text
, srcrow :: Int
, srccol :: Int
, version :: Maybe Text.Text
}
deriving (Eq, Show)

mkTC :: MyToken -> Text.Text -> Maybe (TemporalConstraint Text.Text)
mkTC Before tt = Just $ TBefore tt
mkTC After tt = Just $ TAfter tt
Expand All @@ -71,6 +82,7 @@ mkTC x y = error $ "mkTC: can't create temporal constraint from " ++ show
data RunConfig = RC { debug :: Bool
, callDepth :: Int
, parseCallStack :: [String]
, sourceURL :: Text.Text
}

nestLevel :: RunConfig -> Int
Expand Down Expand Up @@ -147,10 +159,15 @@ dToken c = do
pTokenMatch (== c) c

pXLocation :: Parser Depth
pXLocation = token test Set.empty <?> "nested Boolstruct"
pXLocation = token test Set.empty <?> "x location"
where
test (WithPos (SourcePos _ _y x) _ _ _) = Just (unPos x)

pYLocation :: Parser Depth
pYLocation = token test Set.empty <?> "y location"
where
test (WithPos (SourcePos _ y _x) _ _ _) = Just (unPos y)


pTokenMatch :: (MyToken -> Bool) -> MyToken -> Parser MyToken
pTokenMatch f c = token test (Set.singleton . Tokens . nes . liftMyToken $ c)
Expand Down
29 changes: 21 additions & 8 deletions mengwong/mp/test/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ r `shouldParse` v = case r of
++ errorBundlePrettyCustom e
Right x -> x `shouldBe` v

defaultReg :: Rule
defaultReg, defaultCon :: Rule
defaultReg = Regulative
{ every = "person"
, who = Nothing
Expand All @@ -49,12 +49,21 @@ defaultReg = Regulative
, lest = Nothing
, rlabel = Nothing
, lsource = Nothing
, srcref = Nothing
}

defaultCon = Constitutive
{ term = ""
, cond = Nothing
, rlabel = Nothing
, lsource = Nothing
, srcref = Nothing
}

main :: IO ()
main = do
mpd <- lookupEnv "MP_DEBUG"
let runConfig = RC (maybe False (read :: String -> Bool) mpd) 0 []
let runConfig = RC (maybe False (read :: String -> Bool) mpd) 0 [] "test/Spec"
let parseR p = parse (runReaderT p runConfig)

hspec $ do
Expand Down Expand Up @@ -118,11 +127,9 @@ main = do
mycsv <- BS.readFile "test/indented-1-checkboxes.csv"
parseR (pRule <* eof) "" (exampleStream mycsv) `shouldParse` imbibeRule

let degustates = Constitutive
let degustates = defaultCon
{ term = "degustates"
, cond = Just $ Any ( Pre "any of:" ) [ Leaf "eats", Leaf "drinks" ]
, rlabel = Nothing
, lsource = Nothing
}

it "should parse a simple constitutive rule" $ do
Expand All @@ -141,11 +148,9 @@ main = do
]
, action = ("sing", [])
}
, Constitutive
, defaultCon
{ term = "degustates"
, cond = Just $ Any ( Pre "any of:" ) [ Leaf "eats", Leaf "drinks" ]
, rlabel = Nothing
, lsource = Nothing
}
]

Expand Down Expand Up @@ -226,6 +231,14 @@ main = do
mycsv <- BS.readFile "test/chained-regulatives-part1-alternative-3.csv"
parseR (pRule <* eof) "" (exampleStream mycsv) `shouldParse` king_pays_singer

let if_king_wishes_singer = if_king_wishes ++
[ DefTermAlias "(\"singer\")" "person" Nothing
(Just (SrcRef {url = "test/Spec", short = "test/Spec", srcrow = 1, srccol = 1, version = Nothing})) ]

it "should parse natural language aliases (\"NL Aliases\") aka inline defined terms" $ do
mycsv <- BS.readFile "test/nl-aliases.csv"
parseR (pRule <* eof) "" (exampleStream mycsv) `shouldParse` if_king_wishes_singer

-- upgrade single OR group to bypass the top level AND group


6 changes: 6 additions & 0 deletions mengwong/mp/test/nl-aliases.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
EVERY,person,"(""singer"")",
WHO,walks,,
AND,eats,,
MUST,,,
IF,the King wishes,,
->,sing,,

0 comments on commit df58c28

Please sign in to comment.