@hackage ptera-th0.7.0.0
A parser generator
Installation
CustomDependencies (10)
- array >=0.5.4 && <0.6
- base >=4.14.0 && <5
- containers >=0.6.0 && <0.7
- enummapset >=0.7.1 && <1
- ghc-prim >=0.8.0 && <1
- membership >=0.0.1 && <0.1 Show all…
Dependents (0)
Package Flags
develop
(off by default)
Turn on some options for development
Ptera: A Parser Generator for PEGs
Installation
Add dependencies on package.cabal:
build-depends:
base,
ptera, -- main
ptera-th, -- for outputing parser with Template Haskell
template-haskell,
Usage
Write parser rules:
module Parser.Rules where
import Language.Haskell.TH
import Language.Parser.Ptera.TH
data Token
= TokDigit
| TokSymPlus
| TokSymMulti
| TokEndOfInput
deriving (Eq, Show, Enum)
data Ast
= Value
| Sum Ast Ast
| Product Ast Ast
$(genGrammarToken (mkName "Tokens") [t|Token|]
[ ("+", [p|TokSymPlus|])
, ("*", [p|TokSymMulti|])
, ("n", [p|TokDigit|])
, ("^Z", [p|TokEndOfInput{}|])
])
$(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|])
]
)
$(Ptera.genParsePoints
do TH.mkName "ParsePoints"
do TH.mkName "RuleDefs"
[ "expr ^Z"
]
)
grammar :: Grammar RuleDefs Tokens Token ParsePoints
grammar = fixGrammar $ RuleDefs
{ ruleExprEos = rExprEos
, ruleExpr = rExpr
, ruleSum = rSum
, ruleProduct = rProduct
, ruleValue = rValue
}
type Rule = RuleExpr RuleDefs Tokens Token
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:
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