Parse more binary ops
authorLuke Lau <luke_lau@icloud.com>
Sat, 18 May 2019 16:17:41 +0000 (17:17 +0100)
committerLuke Lau <luke_lau@icloud.com>
Sat, 18 May 2019 22:35:42 +0000 (23:35 +0100)
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

diff --git a/AST.hs b/AST.hs
index 5628e7c7cd74c8d0f04d5b4e9c908e245e5696f6..5b22ea6c662714d483f1dd1ec51755e5f4b7dc7a 100644 (file)
--- a/AST.hs
+++ b/AST.hs
@@ -1,23 +1,32 @@
 module AST where
 
 import Text.Read 
 module AST where
 
 import Text.Read 
-import Text.ParserCombinators.ReadP hiding ((+++))
+import Text.ParserCombinators.ReadP hiding ((+++), choice)
 
 data Expr = Num Float
 
 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
   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
     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
             a <- step readPrec
             lift $ do
               skipSpaces
-              char '+'
+              string s
               skipSpaces
             b <- readPrec
               skipSpaces
             b <- readPrec
-            return (Add a b)
+            return (BinOp op a b)
+