1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
>{-# OPTIONS -farrows #-}
> module ExprParser where
> import Data.Char
> import Control.Arrow
> import Control.Arrow.Transformer.Error
> import Parser
Expressions
> data ESym = LPar | RPar | Plus | Minus | Mult | Div | Number | Unknown | EOF
> deriving (Show, Eq, Ord)
> instance Symbol ESym where
> eof = EOF
> type ExprParser = Parser ESym String (->)
> type ExprSym = Sym ESym String
The grammar
> expr :: ExprParser () Int
> expr = proc () -> do
> x <- term -< ()
> expr' -< x
> expr' :: ExprParser Int Int
> expr' = proc x -> do
> returnA -< x
> <+> do
> symbol Plus -< ()
> y <- term -< ()
> expr' -< x + y
> <+> do
> symbol Minus -< ()
> y <- term -< ()
> expr' -< x - y
> term :: ExprParser () Int
> term = proc () -> do
> x <- factor -< ()
> term' -< x
> term' :: ExprParser Int Int
> term' = proc x -> do
> returnA -< x
> <+> do
> symbol Mult -< ()
> y <- factor -< ()
> term' -< x * y
> <+> do
> symbol Div -< ()
> y <- factor -< ()
> term' -< x `div` y
> factor :: ExprParser () Int
> factor = proc () -> do
> v <- symbol Number -< ()
> returnA -< read v::Int
> <+> do
> symbol Minus -< ()
> v <- factor -< ()
> returnA -< -v
> <+> do
> symbol LPar -< ()
> v <- expr -< ()
> symbol RPar -< ()
> returnA -< v
Lexical analysis
> lexer :: String -> [ExprSym]
> lexer [] = []
> lexer ('(':cs) = Sym LPar "(":lexer cs
> lexer (')':cs) = Sym RPar ")":lexer cs
> lexer ('+':cs) = Sym Plus "+":lexer cs
> lexer ('-':cs) = Sym Minus "-":lexer cs
> lexer ('*':cs) = Sym Mult "*":lexer cs
> lexer ('/':cs) = Sym Div "/":lexer cs
> lexer (c:cs)
> | isSpace c = lexer cs
> | isDigit c = Sym Number (c:w):lexer cs'
> | otherwise = Sym Unknown [c]:lexer cs
> where (w,cs') = span isDigit cs
> run parser = runError (runParser parser)
> (\(_, err) -> error ("parse error: " ++ err)) . lexer
> t = run expr
|