Parse terms and definitions
This commit is contained in:
parent
18e5acd693
commit
60c2c2fe6d
3 changed files with 85 additions and 0 deletions
|
|
@ -14,6 +14,7 @@ extra-doc-files:
|
||||||
dependencies:
|
dependencies:
|
||||||
- base >= 4.7 && < 5
|
- base >= 4.7 && < 5
|
||||||
- containers
|
- containers
|
||||||
|
- megaparsec
|
||||||
- text
|
- text
|
||||||
- transformers
|
- transformers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ library
|
||||||
Propa.Lambda.Term
|
Propa.Lambda.Term
|
||||||
Propa.Prolog.Display
|
Propa.Prolog.Display
|
||||||
Propa.Prolog.Example
|
Propa.Prolog.Example
|
||||||
|
Propa.Prolog.Parse
|
||||||
Propa.Prolog.Types
|
Propa.Prolog.Types
|
||||||
Propa.Prolog.Unify
|
Propa.Prolog.Unify
|
||||||
other-modules:
|
other-modules:
|
||||||
|
|
@ -33,6 +34,7 @@ library
|
||||||
build-depends:
|
build-depends:
|
||||||
base >=4.7 && <5
|
base >=4.7 && <5
|
||||||
, containers
|
, containers
|
||||||
|
, megaparsec
|
||||||
, text
|
, text
|
||||||
, transformers
|
, transformers
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
@ -47,6 +49,7 @@ executable propa-tools-exe
|
||||||
build-depends:
|
build-depends:
|
||||||
base >=4.7 && <5
|
base >=4.7 && <5
|
||||||
, containers
|
, containers
|
||||||
|
, megaparsec
|
||||||
, propa-tools
|
, propa-tools
|
||||||
, text
|
, text
|
||||||
, transformers
|
, transformers
|
||||||
|
|
|
||||||
81
src/Propa/Prolog/Parse.hs
Normal file
81
src/Propa/Prolog/Parse.hs
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module Propa.Prolog.Parse
|
||||||
|
( parseTerms
|
||||||
|
, parseDb
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import Data.Bifunctor
|
||||||
|
import Data.Char
|
||||||
|
import Data.Void
|
||||||
|
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Text.Megaparsec
|
||||||
|
import qualified Text.Megaparsec.Char as C
|
||||||
|
import qualified Text.Megaparsec.Char.Lexer as L
|
||||||
|
|
||||||
|
import Propa.Prolog.Types
|
||||||
|
|
||||||
|
type Parser = Parsec Void T.Text
|
||||||
|
|
||||||
|
-- Lexeme stuff
|
||||||
|
|
||||||
|
space :: Parser ()
|
||||||
|
space = L.space C.space1 (L.skipLineComment "%") (L.skipBlockComment "/*" "*/")
|
||||||
|
|
||||||
|
lexeme :: Parser a -> Parser a
|
||||||
|
lexeme = L.lexeme space
|
||||||
|
|
||||||
|
symbol :: T.Text -> Parser T.Text
|
||||||
|
symbol = L.symbol space
|
||||||
|
|
||||||
|
parens :: Parser a -> Parser a
|
||||||
|
parens = between (symbol "(") (symbol ")")
|
||||||
|
|
||||||
|
-- Building blocks
|
||||||
|
|
||||||
|
pName :: Parser T.Text
|
||||||
|
pName = lexeme $ unquotedName <|> quotedName
|
||||||
|
where
|
||||||
|
unquotedName = takeWhile1P (Just "lowercase character") isLower
|
||||||
|
quotedName = fmap T.pack $ C.char '"' *> manyTill L.charLiteral (C.char '"')
|
||||||
|
|
||||||
|
pVarName :: Parser T.Text
|
||||||
|
pVarName = lexeme $ takeWhile1P (Just "uppercase character") isUpper
|
||||||
|
|
||||||
|
pStat :: Parser (T.Text, [Term T.Text])
|
||||||
|
pStat = do
|
||||||
|
name <- pName
|
||||||
|
terms <- parens (pTerm `sepBy1` symbol ",") <|> pure []
|
||||||
|
pure (name, terms)
|
||||||
|
|
||||||
|
pTerm :: Parser (Term T.Text)
|
||||||
|
pTerm = (Var <$> pVarName) <|> (uncurry Stat <$> pStat)
|
||||||
|
|
||||||
|
pTerms :: Parser [Term T.Text]
|
||||||
|
pTerms = (pTerm `sepBy1` symbol ",") <* symbol "."
|
||||||
|
|
||||||
|
pDef :: Parser (Def T.Text)
|
||||||
|
pDef = do
|
||||||
|
name <- pName
|
||||||
|
args <- parens (pTerm `sepBy1` symbol ",") <|> pure []
|
||||||
|
terms <- (symbol ":-" *> (pTerm `sepBy1` symbol ",")) <|> pure []
|
||||||
|
void $ symbol "."
|
||||||
|
pure $ Def name args terms
|
||||||
|
|
||||||
|
pDefs :: Parser [Def T.Text]
|
||||||
|
pDefs = many pDef
|
||||||
|
|
||||||
|
-- And finally, our nice parsers
|
||||||
|
|
||||||
|
parseHelper :: Parser a -> FilePath -> T.Text -> Either T.Text a
|
||||||
|
parseHelper p path input
|
||||||
|
= first (T.pack . errorBundlePretty)
|
||||||
|
$ parse (space *> p) path input
|
||||||
|
|
||||||
|
parseTerms :: FilePath -> T.Text -> Either T.Text [Term T.Text]
|
||||||
|
parseTerms = parseHelper pTerms
|
||||||
|
|
||||||
|
parseDb :: FilePath -> T.Text -> Either T.Text (Db T.Text)
|
||||||
|
parseDb = parseHelper pDefs
|
||||||
Loading…
Add table
Add a link
Reference in a new issue