|
{
|
|
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
|
|
}
|