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
|
{-
The standard example: arithmetic expressions (see dragon book p222).
frown --debug Test.g
Try
expr (lexer "a+b*c+d") :: [Expr]
Tracing the parse:
frown --debug --trace Expr.g
Try
expr (lexer "a+b*c+d")
-}
module Test
where
import Char
data AddOp = Plus | Minus
deriving (Show)
data MulOp = Times | Divide
deriving (Show)
data Expr = Add Expr AddOp Expr
| Mul Expr MulOp Expr
| Id String
deriving (Show)
type Result = []
%{
Terminal = IDENT {String}
| ADDOP {AddOp}
| MULOP {MulOp}
| LPAR
| RPAR
| *EOF;
Nonterminal = *expr {Expr}
| term {Expr}
| factor {Expr};
expr {Add e1 op e2} : expr {e1}, ADDOP {op}, term {e2};
{e} | term {e};
term {Mul e1 op e2} : term {e1}, MULOP {op}, factor {e2};
{e} | factor {e};
factor {e} : LPAR, expr {e}, RPAR;
{Id s} | IDENT {s};
}%
frown ts = fail "syntax error"
data Terminal = IDENT String | ADDOP AddOp | MULOP MulOp | LPAR | RPAR | EOF
deriving (Show)
lexer :: String -> [Terminal]
lexer [] = [EOF]
lexer ('+' : cs) = ADDOP Plus : lexer cs
lexer ('-' : cs) = ADDOP Minus : lexer cs
lexer ('*' : cs) = MULOP Times : lexer cs
lexer ('/' : cs) = MULOP Divide : lexer cs
lexer ('(' : cs) = LPAR : lexer cs
lexer (')' : cs) = RPAR : lexer cs
lexer (c : cs)
| isAlpha c = let (n, cs') = span isAlphaNum cs
in IDENT (c : n) : lexer cs'
| otherwise = lexer cs
|