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
Prisms 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
> "2 + 3 * * 5" ^?? expr Left "Unexpected \"*\""
Still lacking in the library
- The errors from
syntax-opticsdo not currently report source-code locations of syntax errors.
AVerbosePrismtype synonym, similar in spirit to
APrism, is currently missing. With it the library would not need
Proxyparameters which it currently requires (
pin 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!
- Title image by Jean François WITZ.