Compare commits

..

No commits in common. "42655b90f558fd82c4497325ae4bbb5b29e6f21a" and "be5e487e3154fdf2e8a083e3f33b007933752c3d" have entirely different histories.

3 changed files with 34 additions and 74 deletions

View File

@ -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).
"""

View File

@ -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)

View File

@ -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