ptera-th 0.1.0.0 → 0.2.0.0
raw patch · 4 files changed
+121/−50 lines, 4 filesdep ~pteraPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: ptera
API changes (from Hackage documentation)
- Language.Parser.Ptera.TH: epsM :: (HTExpList '[] -> Q (TExp (ActionTask ctx a))) -> AltM ctx rules tokens elem a
- Language.Parser.Ptera.TH.Syntax: epsM :: (HTExpList '[] -> Q (TExp (ActionTask ctx a))) -> AltM ctx rules tokens elem a
- Language.Parser.Ptera.TH: eps :: (HTExpList '[] -> Q (TExp a)) -> AltM ctx rules tokens elem a
+ Language.Parser.Ptera.TH: eps :: Expr rules tokens elem ('[] :: [Type])
- Language.Parser.Ptera.TH.Syntax: eps :: (HTExpList '[] -> Q (TExp a)) -> AltM ctx rules tokens elem a
+ Language.Parser.Ptera.TH.Syntax: eps :: Expr rules tokens elem ('[] :: [Type])
Files
- README.md +112/−34
- ptera-th.cabal +2/−2
- src/Language/Parser/Ptera/TH.hs +5/−3
- src/Language/Parser/Ptera/TH/Syntax.hs +2/−11
README.md view
@@ -1,6 +1,6 @@-# Ptera: A Generator for Parsers+# Ptera: A Parser Generator for PEGs -[](https://hackage.haskell.org/package/ptera)+[](https://hackage.haskell.org/package/ptera-th) ## Installation @@ -9,10 +9,8 @@ ``` build-depends: base,- bytestring, ptera, -- main ptera-th, -- for outputing parser with Template Haskell- charset, template-haskell, ``` @@ -21,47 +19,127 @@ Write parser rules: ```haskell-data Terminal- = Digit- | SymPlus- | SymMulti- deriving (Eq, Show, Enum)+module Parser.Rules where -data NonTerminal- | Expr- | Sum- | Product- | Value+import Language.Haskell.TH+import Language.Parser.Ptera.TH++data Token+ = TokDigit+ | TokSymPlus+ | TokSymMulti+ | TokEndOfInput deriving (Eq, Show, Enum) -type ParseRule = Rule Terminal NonTerminal+data Ast+ = Value+ | Sum Ast Ast+ | Product Ast Ast +$(genGrammarToken (mkName "Tokens") [t|Token|]+ [ ("+", [p|TokSymPlus|])+ , ("*", [p|TokSymMulti|])+ , ("n", [p|TokDigit|])+ , ("^Z", [p|TokEndOfInput{}|])+ ]) -data Ast- = GenValue- | GenSum (NonEmpty Ast)- | GenProduct Ast Ast+$(Ptera.genRules+ do TH.mkName "RuleDefs"+ do GenRulesTypes+ { genRulesCtxTy = [t|()|]+ , genRulesTokensTy = [t|Tokens|]+ , genRulesTokenTy = [t|Token|]+ }+ [ (TH.mkName "ruleExprEos", "expr ^Z", [t|Ast|])+ , (TH.mkName "ruleExpr", "expr", [t|Ast|])+ , (TH.mkName "ruleSum", "sum", [t|Ast|])+ , (TH.mkName "ruleProduct", "product", [t|Ast|])+ , (TH.mkName "ruleValue", "value", [t|Ast|])+ ]+ ) -rExpr :: ParseRule Ast-rExpr = rule Expr rSum+$(Ptera.genParsePoints+ do TH.mkName "ParsePoints"+ do TH.mkName "RuleDefs"+ [ "expr ^Z"+ ]+ ) -rSum :: ParseRule Ast-rSum = rule Sum do- (rProduct <,> manyP do token SymPlus *> rProduct) <&> \(e, es) -> GenSum do e :| es+grammar :: Grammar RuleDefs Tokens Token ParsePoints+grammar = fixGrammar $ RuleDefs+ { ruleExprEos = rExprEos+ , ruleExpr = rExpr+ , ruleSum = rSum+ , ruleProduct = rProduct+ , ruleValue = rValue+ } -rProduct :: ParseRule Ast-rProduct = rule Product do- orP- [- (rValue <* token SymMulti <,> rProduct) <&> \(e1, e2) -> GenProduct e1 e2,- rValue- ]+type Rule = RuleExpr RuleDefs Tokens Token -rValue :: ParseRule Ast-rValue = rule Value do token Digit *> pure GenValue++rExprEos :: Rule Ast+rExprEos = ruleExpr+ [ varA @"expr" <^> tokA @"^Z"+ <:> \(e :* _ :* HNil) -> e+ ]++rExpr :: Rule Ast+rExpr = ruleExpr+ [ varA @"sum"+ <:> \(e :* HNil) -> e+ ]++rSum :: Rule Ast+rSum = ruleExpr+ [ varA @"product" <^> tokA @"+" <^> varA @"sum"+ <:> \(e1 :* _ :* e2 :* HNil) -> [|| Sum $$(e1) $$(e2) ||]+ , varA @"product"+ <:> \(e :* HNil) -> e+ ]++rProduct :: Rule Ast+rProduct = ruleExpr+ [ varA @"value" <^> tokA @"*" <^> varA @"product"+ <:> \(e1 :* _ :* e2 :* HNil) -> [|| Product $$(e1) $$(e2) ||]+ , varA @"value"+ <:> \(e :* HNil) -> e+ ]++rValue :: Rule Ast+rValue = ruleExpr+ [ tokA @"n" <:> \(n :* HNil) ->+ [|| case $$(n) of+ TokDigit -> Value+ _ -> error "unreachable: expected digit token"+ ||]+ ] ``` +And, generate parser:++```haskell+module Parser where++import Parser.Rules+import Language.Parser.Ptera.TH+import Data.Proxy++$(genRunner+ (GenParam+ { startsTy = [t|ParsePoints|]+ , rulesTy = [t|RuleDefs|]+ , tokensTy = [t|Tokens|]+ , tokenTy = [t|Token|]+ , customCtxTy = defaultCustomCtxTy+ })+ grammar+ )++exprParser :: Scanner posMark Token m => m (Result posMark Ast)+exprParser = runParser (Proxy :: Proxy "expr EOS") pteraTHRunner+```+ ## Examples -* Small language: https://github.com/mizunashi-mana/ptera/tree/master/example/small-lang+* Small language: https://github.com/mizunashi-mana/ptera/tree/master/example/small-lang-th * Haskell2010: https://github.com/mizunashi-mana/ptera/tree/master/example/haskell2010
ptera-th.cabal view
@@ -2,7 +2,7 @@ build-type: Custom name: ptera-th-version: 0.1.0.0+version: 0.2.0.0 license: Apache-2.0 OR MPL-2.0 license-file: LICENSE copyright: (c) 2021 Mizunashi Mana@@ -93,7 +93,7 @@ -- project depends ptera-core >= 0.1.0 && < 0.2,- ptera >= 0.1.0 && < 0.2,+ ptera >= 0.2.0 && < 0.3, ghc-prim >= 0.6.1 && < 0.7, containers >= 0.6.0 && < 0.7, unordered-containers >= 0.2.0 && < 0.3,
src/Language/Parser/Ptera/TH.hs view
@@ -23,11 +23,13 @@ import qualified Language.Parser.Ptera.TH.Pipeline.Grammar2ParserDec as Grammar2ParserDec import Language.Parser.Ptera.TH.Syntax hiding (T, UnsafeSemActM,- unsafeSemanticAction, semAct, semActM)+ semAct,+ semActM,+ unsafeSemanticAction) import Language.Parser.Ptera.TH.Util (GenRulesTypes (..), genGrammarToken,- genRules,- genParsePoints)+ genParsePoints,+ genRules) import qualified Type.Membership as Membership genRunner :: forall initials rules tokens ctx elem
src/Language/Parser/Ptera/TH/Syntax.hs view
@@ -39,10 +39,9 @@ SafeGrammar.fixGrammar, SafeGrammar.ruleExpr, (SafeGrammar.<^>),+ SafeGrammar.eps, (<:>),- eps, (<::>),- epsM, SafeGrammar.var, SafeGrammar.varA, SafeGrammar.tok,@@ -54,10 +53,10 @@ import qualified Language.Haskell.TH as TH import qualified Language.Haskell.TH.Syntax as TH+import qualified Language.Parser.Ptera.Data.HFList as HFList import qualified Language.Parser.Ptera.Syntax as Syntax import qualified Language.Parser.Ptera.Syntax.SafeGrammar as SafeGrammar import Language.Parser.Ptera.TH.ParserLib-import qualified Language.Parser.Ptera.Data.HFList as HFList type T ctx = GrammarM ctx@@ -78,9 +77,6 @@ infixl 4 <:> -eps :: (HTExpList '[] -> TH.Q (TH.TExp a)) -> AltM ctx rules tokens elem a-eps act = SafeGrammar.eps do semAct act HFList.HFNil- (<::>) :: SafeGrammar.Expr rules tokens elem us -> (HTExpList us -> TH.Q (TH.TExp (ActionTask ctx a)))@@ -88,11 +84,6 @@ e@(SafeGrammar.UnsafeExpr ue) <::> act = e SafeGrammar.<:> semActM act ue infixl 4 <::>--epsM- :: (HTExpList '[] -> TH.Q (TH.TExp (ActionTask ctx a)))- -> AltM ctx rules tokens elem a-epsM act = SafeGrammar.eps do semActM act HFList.HFNil type HTExpList = HFList.T TExpQ