%{ (* Parser for a small object-oriented language (uJava). sestoft@dina.kvl.dk * 2001-02-17, 2001-04-10 *) open Absyn; %} %token CSTINT %token CSTSTRING NAME %token CSTBOOL %token BOOLEAN CLASS EXTENDS ELSE FOR IF INT NEW NULL RETURN %token THIS VOID WHILE %token PLUS MINUS TIMES EQ DIV MOD %token EQ NE GT LT GE LE %token NOT SEQOR SEQAND %token LPAR RPAR LBRACE RBRACE SEMI COMMA DOT ASSIGN %token EOF %right ASSIGN /* lowest precedence */ %left SEQOR %left SEQAND %left EQ NE %nonassoc GT LT GE LE %left PLUS MINUS %left TIMES DIV MOD %nonassoc NOT %left DOT /* highest precedence */ %start Main %type Main Classdecs %type Classdec %type Memberdecs %type Memberdec Fielddec Methoddec %type Paramdecs Paramdecs1 %type Paramdec %type Stmt StmtM StmtU Block %type StmtOrDecSeq %type Expr %type Exprs Exprs1 %type Const %type Type %% Main: Classdecs EOF { $1 } ; Classdecs: /* empty */ { [] } | Classdec Classdecs { $1 :: $2 } ; Classdec: CLASS NAME EXTENDS NAME LBRACE Memberdecs RBRACE { Classdec($2, $4, $6) } ; Memberdecs: /* empty */ { [] } | Memberdec Memberdecs { $1 :: $2 } ; Memberdec: Methoddec { $1 } | Fielddec { $1 } ; Fielddec: Type NAME SEMI { Fielddec($1, $2) } ; Methoddec: VOID NAME LPAR Paramdecs RPAR Stmt { Methoddec(NONE, $2, $4, $6) } | Type NAME LPAR Paramdecs RPAR Stmt { Methoddec(SOME($1), $2, $4, $6) } ; Paramdecs: /* empty */ { [] } | Paramdecs1 { $1 } ; Paramdecs1: Paramdec { [$1] } | Paramdec COMMA Paramdecs1 { $1 :: $3 } ; Paramdec: Type NAME { ($1, $2) } ; Block: LBRACE StmtOrDecSeq RBRACE { Block $2 } ; StmtOrDecSeq: /* empty */ { [] } | Stmt StmtOrDecSeq { Stmt $1 :: $2 } | Type NAME SEMI StmtOrDecSeq { Dec ($1, $2) :: $4 } ; Stmt: StmtM { $1 } | StmtU { $1 } ; StmtM: /* No unbalanced if-else */ NAME ASSIGN Expr SEMI { SetLocal($1, $3) } | Expr DOT NAME ASSIGN Expr SEMI { SetField($1, $3, $5) } | Expr SEMI { Expr($1) } | RETURN SEMI { Return NONE } | RETURN Expr SEMI { Return(SOME($2)) } | Block { $1 } | IF LPAR Expr RPAR StmtM ELSE StmtM { If($3, $5, $7) } | WHILE LPAR Expr RPAR StmtM { While($3, $5) } ; StmtU: IF LPAR Expr RPAR StmtM ELSE StmtU { If($3, $5, $7) } | IF LPAR Expr RPAR Stmt { If($3, $5, Block []) } | WHILE LPAR Expr RPAR StmtU { While($3, $5) } ; Expr: THIS { GetLocal("this") } | NAME { GetLocal($1) } | Expr DOT NAME { GetField($1, $3) } | Const { Cst($1) } | NEW NAME LPAR RPAR { New($2) } | Expr DOT NAME LPAR Exprs RPAR { Call($1, $3, $5) } | NAME LPAR Exprs RPAR { PrimC($1, $3) } | LPAR Expr RPAR { $2 } | NOT Expr { Prim1("!", $2) } | Expr PLUS Expr { Prim2("+", $1, $3) } | Expr MINUS Expr { Prim2("-", $1, $3) } | Expr TIMES Expr { Prim2("*", $1, $3) } | Expr DIV Expr { Prim2("/", $1, $3) } | Expr MOD Expr { Prim2("%", $1, $3) } | Expr EQ Expr { Prim2("==", $1, $3) } | Expr NE Expr { Prim2("!=", $1, $3) } | Expr GT Expr { Prim2(">", $1, $3) } | Expr LT Expr { Prim2("<", $1, $3) } | Expr GE Expr { Prim2(">=", $1, $3) } | Expr LE Expr { Prim2("<=", $1, $3) } | Expr SEQAND Expr { Andalso($1, $3) } | Expr SEQOR Expr { Orelse($1, $3) } ; Exprs: /* empty */ { [] } | Exprs1 { $1 } ; Exprs1: Expr { [$1] } | Expr COMMA Exprs1 { $1 :: $3 } ; Const: CSTINT { CstI($1) } | MINUS CSTINT { CstI(~ $2) } | CSTBOOL { CstI(if $1 then 1 else 0) } | CSTSTRING { CstS($1) } | NULL { CstN } ; Type: INT { TypI } | NAME { TypO($1) } ;