The journey to create combinators for parsing and pretty-pretting continues!
This post (along with the new syntax-optics
repo) combines two previous efforts:
- "Elegant AST Parsing and
Building with Prisms" declared
Prism
s to parse and print ASTs, but lacking descriptive errors when the parsing fails - "Basic error reporting
for optics" declared new
lens
-compatible optics that add error reporting to parse errors
The resulting combinators let us nicely declare syntax:
data Expr
= Lit Int
| Add Expr Expr
| Mul Expr Expr
deriving (Show, Eq)
'Expr
makePrisms '
expr :: VerbosePrism' String String Expr
= tokens . takeExpr . endOfTokens
expr
takeExpr :: VerbosePrism' String [String] (Expr, [String])
=
takeExpr "+" _Add $ -- Additions of
infixOpLeftRecursion p "*" _Mul $ -- multiplications of
infixOpLeftRecursion p $ -- literals or
tryMatchAtom p (prismFallback _Lit) _Show -- expressions in parens
parens takeExpr where
= Proxy @String p
expr
can be used to both pretty-print and to parse:
> expr # (Lit 1 `Mul` (Lit 2 `Add` Lit 3)) `Add` Lit 4
"1 * (2 + 3) + 4"
> "1 * (2 + 3) + 4" ^? expr
Just (Add (Mul (Lit 1) (Add (Lit 2) (Lit 3))) (Lit 4))
Now, to also get the syntax errors when parsing, we can use the new
^??
operator rather than lens
's
^?
:
> "2 + 3 * * 5" ^?? expr
Left "Unexpected \"*\""
Still lacking in the library
- The errors from
syntax-optics
do not currently report source-code locations of syntax errors. - An
AVerbosePrism
type synonym, similar in spirit toALens
andAPrism
, is currently missing. With it the library would not needRankNTypes
norProxy
parameters which it currently requires (p
in the example in this post).
I've tried to define AVerbosePrism
but haven't succeeded
so far. Help and advice from lens
wizards would be very
appreciated!
Notes
- Title image by Jean François WITZ.