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"
module AST where
import Text.Read
module AST where
import Text.Read
-import Text.ParserCombinators.ReadP hiding ((+++))
+import Text.ParserCombinators.ReadP hiding ((+++), choice)
+ | 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
+ parseBinOp s prc op = prec prc $ do
a <- step readPrec
lift $ do
skipSpaces
a <- step readPrec
lift $ do
skipSpaces
+ return (BinOp op a b)
+