-- vim: set syntax=happy autoindent ts=4 sts=4 sw=4 : { module Imp_Parse (imp_parse) where import Imp_Lex import Imp_AbsSyntax } %name imp_parse Prog %tokentype { Token } %error { parseError } -- tokens %token '(' { LPAREN _ } ')' { RPAREN _ } ';' { DELIM _ } assign { ASSIGN _ } '+' { BINOP _ "+" } '-' { BINOP _ "-" } '*' { BINOP _ "*" } '<' { BINOP _ "<" } '~' { BINOP _ "==" } if { KEYWORD _ "if" } then { KEYWORD _ "then" } else { KEYWORD _ "else" } while { KEYWORD _ "while" } do { KEYWORD _ "do" } skip { KEYWORD _ "skip" } num { NUM _ $$ } bool { BOOL _ $$ } loc { LOC _ $$ } -- precedence and associativity declarations, lowest precedence first -- these are needed to break shift/reduce conflict in while/if statements %nonassoc do then else %right ';' %nonassoc assign %nonassoc '~' '<' %left '+' '-' %left '*' %% Prog : {- empty -} { Skip } | Command { $1 } Command : skip { Skip } | loc assign AExpr { Assign ($1, $3) } | if BExpr then Command else Command { Cond ($2, $4, $6) } | while BExpr do Command { While ($2, $4) } | Command ';' Command { Seq ($1, $3) } | '(' Command ')' { $2 } AExpr : loc { Loc $1 } | num { Num $1 } | AExpr '+' AExpr { AOp ("+", $1, $3) } | AExpr '-' AExpr { AOp ("-", $1, $3) } | AExpr '*' AExpr { AOp ("*", $1, $3) } BExpr : bool { Boolean $1 } | AExpr '<' AExpr { BOp ("<", $1, $3) } | AExpr '~' AExpr { BOp ("==", $1, $3) } { parseError :: [Token] -> a parseError ts = error ("Parse error at " ++ location ++ "\n") where location = case ts of [] -> "end of file" (t:_) -> "line " ++ show l ++ ", column " ++ show c where AlexPn _ l c = pos t }