{ module Parser where import Control.Monad.Error import Lexer.Support import Syntax import Lexer (scan) } %name parseExpr Expr %name parseDecl Decl %tokentype { Token } %monad { Lexer } %lexer { lexer } { TkEOF } %errorhandlertype explist %error { parseError } %token VAR { TkIdent $$ } 'let' { TkLet } 'in' { TkIn } 'where' { TkWhere } '=' { TkEqual } '{' { TkOpen } ';' { TkSemi } '}' { TkClose } '\\' { TkBackslash } '->' { TkArrow } '(' { TkLParen } ')' { TkRParen } OPEN { TkVOpen } SEMI { TkVSemi } CLOSE { TkVClose } %% Atom :: { Expr } : VAR { Var $1 } | '(' Expr ')' { $2 } Expr :: { Expr } : '\\' VAR '->' Expr { Lam $2 $4 } | 'let' DeclBlock 'in' Expr { Let $2 $4 } | FuncExpr { $1 } FuncExpr :: { Expr } : FuncExpr Atom { App $1 $2 } | Atom { $1 } DeclBlock :: { [Decl] } : '{' DeclListSemi '}' { $2 } | OPEN DeclListSEMI Close { $2 } DeclListSemi :: { [Decl] } : Decl ';' DeclListSemi { $1:$3 } | Decl { [$1] } | {- empty -} { [] } DeclListSEMI :: { [Decl] } : Decl SEMI DeclListSemi { $1:$3 } | Decl { [$1] } | {- empty -} { [] } Close : CLOSE { () } | error {% popLayout } Decl : VAR '=' Expr { Decl $1 $3 Nothing } | VAR '=' Expr 'where' DeclBlock { Decl $1 $3 (Just $5) } { lexer cont = scan >>= cont parseError = throwError . show }