{ {-# OPTIONS_GHC -w #-} module Il.Parser where import Il.Lexer import Il.AST import Defs.Common import Prelude } %name parse funlist %tokentype { Token } %error { parseError } %token And { (_,TkAnd) } Assign { (_,TkAssign) } Comma { (_,TkComma) } Dec { (_,TkDec) } Div { (_,TkDiv) } Ds { (_,TkDs) } DsElem { (_,TkDsElem) } Else { (_,TkElse) } Equals { (_,TkEquals) } TFalse { (_,TkFalse) } For { (_,TkFor) } GEqual { (_,TkGEqual) } Greater { (_,TkGreater) } If { (_,TkIf) } Inc { (_,TkInc) } Int { (_,TkInt $$) } LCParen { (_,TkLCParen) } LSParen { (_,TkLSParen) } LEqual { (_,TkLEqual) } LParen { (_,TkLParen) } Less { (_,TkLess) } Minus { (_,TkMinus) } Mul { (_,TkMul) } Name { (_,TkName $$) } Newline { (_,TkNewline) } Not { (_,TkNot) } Null { (_,TkNull) } Or { (_,TkOr) } Plus { (_,TkPlus) } RCParen { (_,TkRCParen) } RSParen { (_,TkRSParen) } Return { (_,TkReturn) } RParen { (_,TkRParen) } Semicolon { (_,TkSemicolon)} Then { (_,TkThen) } TTrue { (_,TkTrue) } TInt { (_,TkTInt) } TBool { (_,TkTBool) } TVoid { (_,TkTVoid) } While { (_,TkWhile) } %left Else RParen %nonassoc Not %nonassoc Assign %left And Or %nonassoc Less Greater GEqual LEqual Equals %left Plus Minus %left Mul Div %nonassoc Inc Dec %nonassoc Newline %% funlist :: { [Function] } funlist: fundef funlist { $1:$2 } funlist: fundef Newline funlist { $1:$3 } | { [] } fundef :: { Function } fundef: type Name LParen argdef RParen block { Function (F $2) $1 $4 $6 } | type Name LParen argdef RParen Newline block { Function (F $2) $1 $4 $7 } argdef :: { [(VariableName, Type)] } argdef: nvtype Name Comma argdef { (V $2, $1):$4 } | nvtype Name { [(V $2, $1)] } | { [] } type :: { Type } type: TVoid { TVoid } | nvtype { $1 } nvtype :: { Type } nvtype: TInt { TInt } | TBool { TBool } | Ds { Ds } | DsElem { DsElem } | LSParen trecordintern RSParen { TRec $2 } trecordintern :: { [(Name, Type)] } trecordintern: trecordpair Comma trecordintern { $1 : $3 } | trecordpair { [$1] } trecordpair :: { (Name, Type) } trecordpair: nvtype Name { ($2, $1) } expr :: { Term } expr: Name Assign valexpr { Assign (V $1) $3 } | nvtype Name Assign valexpr { InitAssign (V $2) $4 $1 } | nvtype Name { VarInit (V $2) $1 } | block { $1 } | If valexpr Then expr Else expr { If $2 $4 $6 } | If valexpr Newline Then expr Newline Else expr { If $2 $5 $8 } | For LParen expr Semicolon valexpr Semicolon expr RParen expr { While $5 (Block [$3, $7, $9]) } | For LParen expr Semicolon valexpr Semicolon expr RParen Newline expr { While $5 (Block [$3, $7, $10]) } | While LParen valexpr RParen expr { While $3 $5 } | While LParen valexpr RParen Newline expr { While $3 $6 } | Return valexpr { Return $2 } | shexpr { $1 } shexpr :: { Term } shexpr: Inc Name { Inc (V $2) } | Name Inc { Inc (V $1) } | Dec Name { Dec (V $2) } | Name Dec { Dec (V $1) } | Name LParen commaseparatedlist RParen { Funcall (F $1) $3 } valexpr :: { Term } valexpr: Name { Var (V $1) } | Null { Int 0 } | Int { Int $1 } | TFalse { Int 0 } | TTrue { Int 1 } | Not valexpr { Not $2 } | valexpr And valexpr { And $1 $3 } | valexpr Or valexpr { Or $1 $3 } | valexpr Plus valexpr { Sum $1 $3 } | valexpr Minus valexpr { Sub $1 $3 } | valexpr Mul valexpr { Mul $1 $3 } | valexpr Div valexpr { Div $1 $3 } | valexpr Equals valexpr { Eq $1 $3 } | valexpr LEqual valexpr { Leq $1 $3 } | valexpr GEqual valexpr { Geq $1 $3 } | valexpr Greater valexpr { Gt $1 $3 } | valexpr Less valexpr { Lt $1 $3 } | LParen valexpr RParen { $2 } | record { $1 } | shexpr { $1 } record :: { Term } record: LSParen RSParen { Record [] } | LSParen recordintern RSParen { Record $2 } recordintern :: { [(Name, Term)] } recordintern: recordpair Comma recordintern { $1 : $3 } | recordpair { [$1] } recordpair :: { (Name, Term) } recordpair: Name Assign valexpr { ($1, $3) } block :: { Term } block: LCParen Newline exprlist RCParen { Block $3 } | LCParen exprlist RCParen { Block $2 } | LCParen RCParen { Block [] } | LCParen Newline RCParen { Block [] } exprlist :: { [Term] } exprlist: block exprlist { $1:$2 } | expr Newline exprlist { $1:$3 } | expr Newline { [$1] } | expr { [$1] } commaseparatedlist :: { [Term] } commaseparatedlist: valexpr Comma commaseparatedlist { $1:$3 } | valexpr { [$1] } | { [] } { parseError :: [Token] -> a parseError (((line,col),t):xs) = error $ "Parse error at line " ++ (show line) ++ ", column " ++ (show col) parseError [] = error "Parse error at the end" }