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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
This is a simple test for happy using operator precedence.
First thing to declare is the name of your parser,
and the type of the tokens the parser reads.
> {
> import Data.Char
> }
> %name calc
> %tokentype { Token }
The parser will be of type [Token] -> ?, where ? is determined by the
production rules. Now we declare all the possible tokens:
> %token
> let { TokenLet }
> in { TokenIn }
> int { TokenInt $$ }
> var { TokenVar $$ }
> '=' { TokenEq }
> '>' { TokenGreater }
> '<' { TokenLess }
> '+' { TokenPlus }
> '-' { TokenMinus }
> '*' { TokenTimes }
> '/' { TokenDiv }
> '(' { TokenOB }
> ')' { TokenCB }
> UMINUS { TokenFoo }
> %nonassoc '>' '<'
> %left '+' '-'
> %left '*' '/'
> %left UMINUS
> %%
> Exp :: { Exp }
> Exp : let var '=' Exp in Exp { Let $2 $4 $6 }
> | Exp '>' Exp { Greater $1 $3 }
> | Exp '<' Exp { Less $1 $3 }
> | Exp '+' Exp { Plus $1 $3 }
> | Exp '-' Exp { Minus $1 $3 }
> | Exp '*' Exp { Times $1 $3 }
> | Exp '/' Exp { Div $1 $3 }
> | '-' Exp %prec UMINUS { Uminus $2 }
> | '(' Exp ')' { Brack $2 }
> | int { Int $1 }
> | var { Var $1 }
We are simply returning the parsed data structure !
Now we need some extra code, to support this parser,
and make in complete:
> {
All parsers must declair this function,
which is called when an error is detected.
Note that currently we do no error recovery.
> happyError tks = error "Parse error"
Now we declare the datastructure that we are parsing.
> data Exp
> = Let String Exp Exp
> | Greater Exp Exp
> | Less Exp Exp
> | Plus Exp Exp
> | Minus Exp Exp
> | Times Exp Exp
> | Div Exp Exp
> | Uminus Exp
> | Brack Exp
> | Int Int
> | Var String
> deriving Show
The datastructure for the tokens...
> data Token
> = TokenLet
> | TokenIn
> | TokenInt Int
> | TokenVar String
> | TokenEq
> | TokenGreater
> | TokenLess
> | TokenPlus
> | TokenMinus
> | TokenTimes
> | TokenDiv
> | TokenOB
> | TokenCB
> | TokenFoo
.. and a simple lexer that returns this datastructure.
> lexer :: String -> [Token]
> lexer [] = []
> lexer (c:cs)
> | isSpace c = lexer cs
> | isAlpha c = lexVar (c:cs)
> | isDigit c = lexNum (c:cs)
> lexer ('=':cs) = TokenEq : lexer cs
> lexer ('>':cs) = TokenGreater : lexer cs
> lexer ('<':cs) = TokenLess : lexer cs
> lexer ('+':cs) = TokenPlus : lexer cs
> lexer ('-':cs) = TokenMinus : lexer cs
> lexer ('*':cs) = TokenTimes : lexer cs
> lexer ('/':cs) = TokenDiv : lexer cs
> lexer ('(':cs) = TokenOB : lexer cs
> lexer (')':cs) = TokenCB : lexer cs
> lexNum cs = TokenInt (read num) : lexer rest
> where (num,rest) = span isDigit cs
> lexVar cs =
> case span isAlpha cs of
> ("let",rest) -> TokenLet : lexer rest
> ("in",rest) -> TokenIn : lexer rest
> (var,rest) -> TokenVar var : lexer rest
To run the program, call this in gofer, or use some code
to print it.
> runCalc :: String -> Exp
> runCalc = calc . lexer
Here we test our parser.
> main = case runCalc "let x = 1 in let y = 2 in x * y + x / y" of {
> (Let "x" (Int 1) (Let "y" (Int 2) (Plus (Times (Var "x") (Var "y")) (Div (Var "x") (Var "y"))))) ->
> case runCalc "- 1 * - 2 + 3" of {
> (Plus (Times (Uminus (Int 1)) (Uminus (Int 2))) (Int 3)) ->
> case runCalc "- - - 1 + 2 * 3 - 4" of {
> (Minus (Plus (Uminus (Uminus (Uminus (Int 1)))) (Times (Int 2) (Int 3))) (Int 4)) ->
> print "Test works\n";
> _ -> quit } ; _ -> quit } ; _ -> quit }
>
> quit = print "Test failed\n";
>
> }
|