Trying to create Syntax Optics 2020.11.19

The journey to create combinators for parsing and pretty-pretting continues!

This post (along with the new syntax-optics repo) combines two previous efforts:

The resulting combinators let us nicely declare syntax:

data Expr
    = Lit Int
    | Add Expr Expr
    | Mul Expr Expr
    deriving (Show, Eq)
makePrisms ''Expr

expr :: VerbosePrism' String String Expr
expr = tokens . takeExpr . endOfTokens

takeExpr :: VerbosePrism' String [String] (Expr, [String])
takeExpr =
    infixOpLeftRecursion p "+" _Add $           -- Additions of
    infixOpLeftRecursion p "*" _Mul $           -- multiplications of
    tryMatchAtom p (prismFallback _Lit) _Show $ -- literals or
    parens takeExpr                             -- expressions in parens
    where
        p = Proxy @String

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

I've tried to define AVerbosePrism but haven't succeeded so far. Help and advice from lens wizards would be very appreciated!

Notes