Compare commits
No commits in common. "42655b90f558fd82c4497325ae4bbb5b29e6f21a" and "be5e487e3154fdf2e8a083e3f33b007933752c3d" have entirely different histories.
42655b90f5
...
be5e487e31
@ -1,5 +1,3 @@
|
|||||||
{-# LANGUAGE MultilineStrings #-}
|
|
||||||
|
|
||||||
module Datalog.Parser
|
module Datalog.Parser
|
||||||
( parseTerm
|
( parseTerm
|
||||||
, parseAtom
|
, parseAtom
|
||||||
@ -16,7 +14,6 @@ import Data.Void (Void)
|
|||||||
import Text.Megaparsec
|
import Text.Megaparsec
|
||||||
import Text.Megaparsec.Char
|
import Text.Megaparsec.Char
|
||||||
import Text.Megaparsec.Char.Lexer qualified as L
|
import Text.Megaparsec.Char.Lexer qualified as L
|
||||||
import Text.Pretty.Simple
|
|
||||||
|
|
||||||
type Parser = Parsec Void Text
|
type Parser = Parsec Void Text
|
||||||
|
|
||||||
@ -39,63 +36,36 @@ comma, period :: (MonadParsec e Text m) => m ()
|
|||||||
comma = () <$ symbol ","
|
comma = () <$ symbol ","
|
||||||
period = () <$ symbol "."
|
period = () <$ symbol "."
|
||||||
|
|
||||||
parseCon :: (MonadParsec e Text m) => m (Term' SrcLoc)
|
parseCon :: (MonadParsec e Text m) => m Term
|
||||||
parseCon = Con dummy . ConId . T.pack <$> lexeme (liftA2 (:) (numberChar <|> lowerChar) (many alphaNumChar))
|
parseCon = Con . ConId . T.pack <$> lexeme (liftA2 (:) (numberChar <|> lowerChar) (many alphaNumChar))
|
||||||
|
|
||||||
parseVar :: (MonadParsec e Text m) => m (Term' SrcLoc)
|
parseVar :: (MonadParsec e Text m) => m Term
|
||||||
parseVar = Var dummy . VarId . T.pack <$> lexeme (liftA2 (:) upperChar (many alphaNumChar))
|
parseVar = Var . VarId . T.pack <$> lexeme (liftA2 (:) upperChar (many alphaNumChar))
|
||||||
|
|
||||||
parseTerm :: Parser (Term' SrcLoc)
|
parseTerm :: Parser Term
|
||||||
parseTerm = parseVar <|> parseCon
|
parseTerm = parseVar <|> parseCon
|
||||||
|
|
||||||
parseAtom :: Parser (Atom' SrcLoc)
|
parseAtom :: Parser Atom
|
||||||
parseAtom = do
|
parseAtom = do
|
||||||
p <- getSourcePos
|
|
||||||
rel <- RelId . T.pack <$> lexeme (liftA2 (:) lowerChar (many alphaNumChar))
|
rel <- RelId . T.pack <$> lexeme (liftA2 (:) lowerChar (many alphaNumChar))
|
||||||
args <- parens (parseTerm `sepBy` comma)
|
args <- parens (parseTerm `sepBy` comma)
|
||||||
return (Atom SrcLoc{start = p} rel args)
|
return (Atom rel args)
|
||||||
|
|
||||||
parseQuery :: Parser [Atom' SrcLoc]
|
parseQuery :: Parser [Atom]
|
||||||
parseQuery = parseAtom `sepBy` comma
|
parseQuery = parseAtom `sepBy` comma
|
||||||
|
|
||||||
parseFact :: Parser (Rule' SrcLoc)
|
parseFact :: Parser Rule
|
||||||
parseFact = do
|
parseFact = do
|
||||||
p <- getSourcePos
|
|
||||||
headAtom <- parseAtom
|
headAtom <- parseAtom
|
||||||
period
|
period
|
||||||
return (Rule SrcLoc{start = p} headAtom [])
|
return (headAtom :- [])
|
||||||
|
|
||||||
parseRule :: Parser (Rule' SrcLoc)
|
parseRule :: Parser Rule
|
||||||
parseRule = try parseFact <|> do
|
parseRule = try parseFact <|> do
|
||||||
p <- getSourcePos
|
|
||||||
headAtom <- parseAtom <* symbol ":-"
|
headAtom <- parseAtom <* symbol ":-"
|
||||||
bodyAtoms <- parseQuery
|
bodyAtoms <- parseQuery
|
||||||
period
|
period
|
||||||
return (Rule SrcLoc{start = p} headAtom bodyAtoms)
|
return (headAtom :- bodyAtoms)
|
||||||
|
|
||||||
parseProgram :: Parser (Program' SrcLoc)
|
parseProgram :: Parser Program
|
||||||
parseProgram = Program dummy <$> many parseRule
|
parseProgram = Program <$> many parseRule
|
||||||
|
|
||||||
data SrcLoc = SrcLoc
|
|
||||||
{ start :: SourcePos
|
|
||||||
-- , end :: (Word, Word)
|
|
||||||
} deriving Show
|
|
||||||
dummy = SrcLoc{start = initialPos "dummy-file"}
|
|
||||||
|
|
||||||
test = do
|
|
||||||
let r = runParser parseProgram "???" prog
|
|
||||||
pPrint @IO r
|
|
||||||
|
|
||||||
prog = """
|
|
||||||
odd(X,Y) :- r(X,Y).
|
|
||||||
odd(X,Y) :- even(X,Z), r(Z,Y).
|
|
||||||
even(X,Y) :- odd(X,Z), r(Z,Y).
|
|
||||||
|
|
||||||
r(0,1).
|
|
||||||
r(1,2).
|
|
||||||
r(2,3).
|
|
||||||
r(3,4).
|
|
||||||
r(4,5).
|
|
||||||
|
|
||||||
r(X,Y) :- r(Y,X).
|
|
||||||
"""
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
{-# LANGUAGE PatternSynonyms #-}
|
|
||||||
|
|
||||||
module Datalog.Syntax where
|
module Datalog.Syntax where
|
||||||
|
|
||||||
import Data.Char (isUpper)
|
import Data.Char (isUpper)
|
||||||
@ -17,56 +15,49 @@ newtype VarId = VarId Text
|
|||||||
newtype RelId = RelId Text
|
newtype RelId = RelId Text
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
type Term = Term' ()
|
data Term = Con ConId | Var VarId
|
||||||
data Term' a = Con a ConId | Var a VarId
|
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
con :: Text -> Term
|
con :: Text -> Term
|
||||||
con = Con () . ConId
|
con = Con . ConId
|
||||||
|
|
||||||
var :: Text -> Term
|
var :: Text -> Term
|
||||||
var = Var () . VarId
|
var = Var . VarId
|
||||||
|
|
||||||
term :: Text -> Term
|
term :: Text -> Term
|
||||||
term t = if not (T.null t) && isUpper (T.head t) then var t else con t
|
term t = if not (T.null t) && isUpper (T.head t) then var t else con t
|
||||||
|
|
||||||
type Atom = Atom' ()
|
data Atom = Atom RelId [Term]
|
||||||
data Atom' a = Atom a RelId [Term' a]
|
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
atom :: Text -> [Text] -> Atom
|
atom :: Text -> [Text] -> Atom
|
||||||
atom relName args = Atom () (RelId relName) (map term args)
|
atom relName args = Atom (RelId relName) (map term args)
|
||||||
|
|
||||||
type Rule = Rule' ()
|
data Rule = Atom :- [Atom]
|
||||||
data Rule' a = Rule a (Atom' a) [Atom' a]
|
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
{-# COMPLETE (:-) #-}
|
|
||||||
pattern (:-) :: Atom' a -> [Atom' a] -> Rule' a
|
|
||||||
pattern a :- b <- Rule _ a b
|
|
||||||
|
|
||||||
type Program = Program' ()
|
data Program = Program [Rule]
|
||||||
data Program' a = Program a [Rule' a]
|
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
class HasConstants a where
|
class HasConstants a where
|
||||||
constants :: a -> Set ConId
|
constants :: a -> Set ConId
|
||||||
|
|
||||||
instance HasConstants (Term' a) where
|
instance HasConstants Term where
|
||||||
constants t = case t of
|
constants t = case t of
|
||||||
Con _ x -> Set.singleton x
|
Con x -> Set.singleton x
|
||||||
Var _ _ -> Set.empty
|
Var _ -> Set.empty
|
||||||
|
|
||||||
instance HasConstants a => HasConstants [a] where
|
instance HasConstants a => HasConstants [a] where
|
||||||
constants xs = Set.unions (map constants xs)
|
constants xs = Set.unions (map constants xs)
|
||||||
|
|
||||||
instance HasConstants (Atom' a) where
|
instance HasConstants Atom where
|
||||||
constants (Atom _ _ ts) = constants ts
|
constants (Atom _ ts) = constants ts
|
||||||
|
|
||||||
instance HasConstants (Rule' a) where
|
instance HasConstants Rule where
|
||||||
constants (h :- b) = Set.union (constants h) (constants b)
|
constants (h :- b) = Set.union (constants h) (constants b)
|
||||||
|
|
||||||
instance HasConstants (Program' a) where
|
instance HasConstants Program where
|
||||||
constants (Program _ rs) = constants rs
|
constants (Program rs) = constants rs
|
||||||
|
|
||||||
class Pretty t where
|
class Pretty t where
|
||||||
pretty :: t -> Text
|
pretty :: t -> Text
|
||||||
@ -81,15 +72,15 @@ instance Pretty RelId where
|
|||||||
pretty (RelId t) = t
|
pretty (RelId t) = t
|
||||||
|
|
||||||
instance Pretty Term where
|
instance Pretty Term where
|
||||||
pretty (Con () conId) = pretty conId
|
pretty (Con conId) = pretty conId
|
||||||
pretty (Var () varId) = pretty varId
|
pretty (Var varId) = pretty varId
|
||||||
|
|
||||||
instance Pretty Atom where
|
instance Pretty Atom where
|
||||||
pretty (Atom () relId terms) = pretty relId <> "(" <> T.intercalate "," (map pretty terms) <> ")"
|
pretty (Atom relId terms) = pretty relId <> "(" <> T.intercalate "," (map pretty terms) <> ")"
|
||||||
|
|
||||||
instance Pretty Rule where
|
instance Pretty Rule where
|
||||||
pretty (h :- []) = pretty h <> "."
|
pretty (h :- []) = pretty h <> "."
|
||||||
pretty (h :- ts) = pretty h <> " :- " <> T.intercalate ", " (map pretty ts) <> "."
|
pretty (h :- ts) = pretty h <> " :- " <> T.intercalate ", " (map pretty ts) <> "."
|
||||||
|
|
||||||
instance Pretty Program where
|
instance Pretty Program where
|
||||||
pretty (Program () rs) = T.unlines (map pretty rs)
|
pretty (Program rs) = T.unlines (map pretty rs)
|
||||||
|
|||||||
@ -26,8 +26,7 @@ library datalog-parser
|
|||||||
base,
|
base,
|
||||||
text,
|
text,
|
||||||
containers,
|
containers,
|
||||||
megaparsec,
|
megaparsec
|
||||||
pretty-simple,
|
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
Datalog.Parser,
|
Datalog.Parser,
|
||||||
Datalog.Syntax
|
Datalog.Syntax
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user