From d6cecbbf067560322e391363250fd3c5d45bfbec Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Sat, 18 May 2019 17:17:41 +0100 Subject: [PATCH] Parse more binary ops We can parameterise the precedence that we parse so that * is parsed before +/- etc. Try it out with `ghci AST.hs`, and see the difference between *AST> read "1 * 2 - 3" and *AST> read "1 + 2 - 3" --- AST.hs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/AST.hs b/AST.hs index 5628e7c..5b22ea6 100644 --- a/AST.hs +++ b/AST.hs @@ -1,23 +1,32 @@ module AST where import Text.Read -import Text.ParserCombinators.ReadP hiding ((+++)) +import Text.ParserCombinators.ReadP hiding ((+++), choice) data Expr = Num Float - | Add Expr Expr + | BinOp BinOp Expr Expr + deriving Show + +data BinOp = Add | Sub | Mul | Cmp Ordering deriving Show instance Read Expr where - readPrec = parseNum +++ parseAdd + readPrec = choice [ parseNum + , parseBinOp "<" 10 (Cmp LT) + , parseBinOp "+" 20 Add + , parseBinOp "-" 20 Sub + , parseBinOp "*" 40 Mul + ] where parseNum = Num <$> readPrec -- use 'prec 1' and 'step' so that parsing 'a' -- can only go one step deep, to prevent ininfite -- recursion - parseAdd = prec 1 $ do + parseBinOp s prc op = prec prc $ do a <- step readPrec lift $ do skipSpaces - char '+' + string s skipSpaces b <- readPrec - return (Add a b) + return (BinOp op a b) + -- 2.30.2