-- Parsers for arithmetic expressions import Parser data Expr = Var String | Num Integer | Neg Expr | Add Expr Expr deriving Show -- With parentheses around additions expr0 :: Parser Expr expr0 = token ident >>> Var ||| token uint >>> Num ||| symb '-' *** expr0 >>> Neg . snd ||| symb '(' *** expr0 *** symb '+' *** expr0 *** symb ')' >>> \(_,(e1,(_,(e2,_)))) -> Add e1 e2 -- Let us get rid of unnecessary parentheses expr1 :: Parser Expr expr1 = token ident >>> Var ||| token uint >>> Num ||| symb '-' *** expr1 >>> Neg . snd ||| symb '(' *** expr1 *** symb ')' >>> fst . snd ||| expr1 *** symb '+' *** expr1 >>> \(e1,(_,e2)) -> Add e1 e2 {- Does not work/terminate because of left-recursion: expr1 "" = [] ++ [] ++ [] ++ [] ++ [(Add e1 e2,zs) | (e1,ys) <- expr1 "", (e2,zs) <- (symb '+' *** expr1) ys] = [(Add e1 e2,zs) | (e1,ys) <- expr1 "", (e2,zs) <- (symb '+' *** expr1) ys] = ... -} -- Separate parser/grammar into two levels: term :: Parser Expr term = token ident >>> Var ||| token uint >>> Num ||| symb '-' *** term >>> Neg . snd ||| symb '(' *** expr2 *** symb ')' >>> fst . snd expr2 :: Parser Expr expr2 = term ||| term *** symb '+' *** expr2 >>> \(e1,(_,e2)) -> Add e1 e2 -- An optimimization: expr3 :: Parser Expr expr3 = term *** optional (symb '+' *** expr3) >>> add where add (e1,Nothing) = e1 add (e1,(Just(_,e2))) = Add e1 e2