|
@@ -59,156 +59,155 @@ rlist(x):
|
|
|
| { [] }
|
|
| { [] }
|
|
|
| rlist(x) x { $1 @ [$2] }
|
|
| rlist(x) x { $1 @ [$2] }
|
|
|
|
|
|
|
|
|
|
+(* Shorthand for comma-separated list *)
|
|
|
|
|
+%inline clist(x):
|
|
|
|
|
+ lst=separated_list(COMMA, x)
|
|
|
|
|
+ { lst }
|
|
|
|
|
+
|
|
|
basic_type:
|
|
basic_type:
|
|
|
| FLOAT { Float }
|
|
| FLOAT { Float }
|
|
|
| INT { Int }
|
|
| INT { Int }
|
|
|
| BOOL { Bool }
|
|
| BOOL { Bool }
|
|
|
|
|
|
|
|
program:
|
|
program:
|
|
|
- decl*; EOF
|
|
|
|
|
|
|
+ decl* EOF
|
|
|
{ Program ($1, loc $startpos $endpos) }
|
|
{ Program ($1, loc $startpos $endpos) }
|
|
|
|
|
|
|
|
decl:
|
|
decl:
|
|
|
(* function: use location of function name *)
|
|
(* function: use location of function name *)
|
|
|
- | EXTERN; hdr=fun_header; SEMICOL
|
|
|
|
|
|
|
+ | EXTERN hdr=fun_header SEMICOL
|
|
|
{ let (t, n, p, nameloc) = hdr in
|
|
{ let (t, n, p, nameloc) = hdr in
|
|
|
FunDec(t, n, p, nameloc) }
|
|
FunDec(t, n, p, nameloc) }
|
|
|
|
|
|
|
|
- | export=boption(EXPORT); hdr=fun_header; LBRACE; body=fun_body; RBRACE
|
|
|
|
|
|
|
+ | export=boption(EXPORT) hdr=fun_header LBRACE body=fun_body RBRACE
|
|
|
{ let (t, n, p, nameloc) = hdr in
|
|
{ let (t, n, p, nameloc) = hdr in
|
|
|
FunDef (export, t, n, p, Block body, nameloc) }
|
|
FunDef (export, t, n, p, Block body, nameloc) }
|
|
|
|
|
|
|
|
(* global variable declaration: use location of variable name *)
|
|
(* global variable declaration: use location of variable name *)
|
|
|
- | EXTERN; ctype=basic_type; name=ID; SEMICOL
|
|
|
|
|
|
|
+ | EXTERN ctype=basic_type name=ID SEMICOL
|
|
|
{ GlobalDec (ctype, name, loc $startpos $endpos) }
|
|
{ GlobalDec (ctype, name, loc $startpos $endpos) }
|
|
|
|
|
|
|
|
- | EXTERN; ctype=basic_type;
|
|
|
|
|
- LBRACK; dims=separated_list(COMMA, ID); RBRACK;
|
|
|
|
|
- name=ID; SEMICOL
|
|
|
|
|
|
|
+ | EXTERN ctype=basic_type LBRACK dims=clist(ID) RBRACK name=ID SEMICOL
|
|
|
{ let dimloc = loc $startpos(dims) $endpos(dims) in
|
|
{ let dimloc = loc $startpos(dims) $endpos(dims) in
|
|
|
let loc = loc $startpos(name) $endpos(name) in
|
|
let loc = loc $startpos(name) $endpos(name) in
|
|
|
GlobalDec (ArrayDims (ctype, make_dims dimloc dims), name, loc) }
|
|
GlobalDec (ArrayDims (ctype, make_dims dimloc dims), name, loc) }
|
|
|
|
|
|
|
|
- | export=boption(EXPORT); ctype=basic_type; name=ID; SEMICOL
|
|
|
|
|
|
|
+ | export=boption(EXPORT) ctype=basic_type name=ID SEMICOL
|
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
|
GlobalDef (export, ctype, name, None, loc) }
|
|
GlobalDef (export, ctype, name, None, loc) }
|
|
|
|
|
|
|
|
- | export=boption(EXPORT); ctype=basic_type; name=ID; ASSIGN; init=expr; SEMICOL
|
|
|
|
|
|
|
+ | export=boption(EXPORT) ctype=basic_type name=ID ASSIGN init=expr SEMICOL
|
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
|
GlobalDef (export, ctype, name, Some init, loc) }
|
|
GlobalDef (export, ctype, name, Some init, loc) }
|
|
|
|
|
|
|
|
- | export=boption(EXPORT); ctype=basic_type;
|
|
|
|
|
- LBRACK; dims=separated_list(COMMA, expr); RBRACK;
|
|
|
|
|
- name=ID; SEMICOL
|
|
|
|
|
|
|
+ | export=boption(EXPORT) ctype=basic_type LBRACK dims=clist(expr) RBRACK
|
|
|
|
|
+ name=ID SEMICOL
|
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
|
GlobalDef (export, ArrayDims (ctype, dims), name, None, loc) }
|
|
GlobalDef (export, ArrayDims (ctype, dims), name, None, loc) }
|
|
|
|
|
|
|
|
fun_header:
|
|
fun_header:
|
|
|
(* function header: use location of function name *)
|
|
(* function header: use location of function name *)
|
|
|
- | ret=basic_type; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
|
|
|
|
|
|
|
+ | ret=basic_type name=ID LPAREN params=clist(param) RPAREN
|
|
|
{ (ret, name, params, loc $startpos(name) $endpos(name)) }
|
|
{ (ret, name, params, loc $startpos(name) $endpos(name)) }
|
|
|
|
|
|
|
|
- | VOID; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
|
|
|
|
|
|
|
+ | VOID name=ID LPAREN params=clist(param) RPAREN
|
|
|
{ (Void, name, params, loc $startpos(name) $endpos(name)) }
|
|
{ (Void, name, params, loc $startpos(name) $endpos(name)) }
|
|
|
|
|
|
|
|
param:
|
|
param:
|
|
|
(* parameter: use location of parameter name *)
|
|
(* parameter: use location of parameter name *)
|
|
|
- | ctype=basic_type; name=ID
|
|
|
|
|
|
|
+ | ctype=basic_type name=ID
|
|
|
{ Param (ctype, name, loc $startpos(name) $endpos(name)) }
|
|
{ Param (ctype, name, loc $startpos(name) $endpos(name)) }
|
|
|
|
|
|
|
|
- | ctype=basic_type; LBRACK; dims=separated_list(COMMA, ID); RBRACK; name=ID
|
|
|
|
|
|
|
+ | ctype=basic_type LBRACK dims=clist(ID) RBRACK name=ID
|
|
|
{ let dimloc = loc $startpos(dims) $endpos(dims) in
|
|
{ let dimloc = loc $startpos(dims) $endpos(dims) in
|
|
|
let loc = loc $startpos(name) $endpos(name) in
|
|
let loc = loc $startpos(name) $endpos(name) in
|
|
|
Param (ArrayDims (ctype, make_dims dimloc dims), name, loc) }
|
|
Param (ArrayDims (ctype, make_dims dimloc dims), name, loc) }
|
|
|
|
|
|
|
|
fun_body:
|
|
fun_body:
|
|
|
- | rlist(var_dec); local_fun_dec*; statement*; loption(return_statement)
|
|
|
|
|
|
|
+ | rlist(var_dec) local_fun_dec* statement* loption(return_statement)
|
|
|
{ VarDecs $1 :: (LocalFuns $2) :: $3 @ $4 }
|
|
{ VarDecs $1 :: (LocalFuns $2) :: $3 @ $4 }
|
|
|
|
|
|
|
|
return_statement:
|
|
return_statement:
|
|
|
(* return statement: use location of return value *)
|
|
(* return statement: use location of return value *)
|
|
|
- | RETURN; value=expr; SEMICOL
|
|
|
|
|
|
|
+ | RETURN value=expr SEMICOL
|
|
|
{ [Return (value, loc $startpos(value) $endpos(value))] }
|
|
{ [Return (value, loc $startpos(value) $endpos(value))] }
|
|
|
|
|
|
|
|
(* function: use location of function name *)
|
|
(* function: use location of function name *)
|
|
|
local_fun_dec:
|
|
local_fun_dec:
|
|
|
- | hdr=fun_header; LBRACE; body=fun_body; RBRACE
|
|
|
|
|
|
|
+ | hdr=fun_header LBRACE body=fun_body RBRACE
|
|
|
{ let (t, n, p, nameloc) = hdr in
|
|
{ let (t, n, p, nameloc) = hdr in
|
|
|
FunDef (false, t, n, p, Block body, nameloc) }
|
|
FunDef (false, t, n, p, Block body, nameloc) }
|
|
|
|
|
|
|
|
var_dec:
|
|
var_dec:
|
|
|
(* variable declaration: use location of variable name *)
|
|
(* variable declaration: use location of variable name *)
|
|
|
- | ctype=basic_type; name=ID; SEMICOL
|
|
|
|
|
|
|
+ | ctype=basic_type name=ID SEMICOL
|
|
|
{ VarDec (ctype, name, None, loc $startpos(name) $endpos(name)) }
|
|
{ VarDec (ctype, name, None, loc $startpos(name) $endpos(name)) }
|
|
|
|
|
|
|
|
- | ctype=basic_type; name=ID; ASSIGN; init=expr; SEMICOL
|
|
|
|
|
|
|
+ | ctype=basic_type name=ID ASSIGN init=expr SEMICOL
|
|
|
{ VarDec (ctype, name, Some init, loc $startpos(name) $endpos(name)) }
|
|
{ VarDec (ctype, name, Some init, loc $startpos(name) $endpos(name)) }
|
|
|
|
|
|
|
|
- | ctype=basic_type; LBRACK; dims=separated_list(COMMA, expr); RBRACK;
|
|
|
|
|
- name=ID; SEMICOL
|
|
|
|
|
|
|
+ | ctype=basic_type LBRACK dims=clist(expr) RBRACK name=ID SEMICOL
|
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
|
VarDec (ArrayDims (ctype, dims), name, None, loc) }
|
|
VarDec (ArrayDims (ctype, dims), name, None, loc) }
|
|
|
|
|
|
|
|
- | ctype=basic_type; LBRACK; dims=separated_list(COMMA, expr); RBRACK;
|
|
|
|
|
- name=ID; ASSIGN; init=expr; SEMICOL
|
|
|
|
|
|
|
+ | ctype=basic_type LBRACK dims=clist(expr) RBRACK name=ID ASSIGN
|
|
|
|
|
+ init=expr SEMICOL
|
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
{ let loc = loc $startpos(name) $endpos(name) in
|
|
|
VarDec (ArrayDims (ctype, dims), name, Some init, loc) }
|
|
VarDec (ArrayDims (ctype, dims), name, Some init, loc) }
|
|
|
|
|
|
|
|
statement:
|
|
statement:
|
|
|
(* assignment: use location of assigned variable name *)
|
|
(* assignment: use location of assigned variable name *)
|
|
|
- | name=ID; ASSIGN; value=expr; SEMICOL
|
|
|
|
|
|
|
+ | name=ID ASSIGN value=expr SEMICOL
|
|
|
{ Assign (name, None, value, loc $startpos(name) $endpos(name)) }
|
|
{ Assign (name, None, value, loc $startpos(name) $endpos(name)) }
|
|
|
|
|
|
|
|
- | name=ID; LBRACK; dims=separated_list(COMMA, expr); brk=RBRACK;
|
|
|
|
|
- ASSIGN; value=expr; SEMICOL
|
|
|
|
|
|
|
+ | name=ID LBRACK dims=clist(expr) brk=RBRACK ASSIGN value=expr SEMICOL
|
|
|
{ Assign (name, Some dims, value, loc $startpos(name) $endpos(brk)) }
|
|
{ Assign (name, Some dims, value, loc $startpos(name) $endpos(brk)) }
|
|
|
|
|
|
|
|
- | name=ID; LPAREN; args=separated_list(COMMA, expr); RPAREN; SEMICOL
|
|
|
|
|
|
|
+ | name=ID LPAREN args=clist(expr) RPAREN SEMICOL
|
|
|
{ Expr (FunCall (name, make_args args, loc $startpos(name) $endpos(name))) }
|
|
{ Expr (FunCall (name, make_args args, loc $startpos(name) $endpos(name))) }
|
|
|
|
|
|
|
|
(* if-statements and (do-)while-loops: use location of condition *)
|
|
(* if-statements and (do-)while-loops: use location of condition *)
|
|
|
- | IF; LPAREN; cond=expr; RPAREN; body=block
|
|
|
|
|
|
|
+ | IF LPAREN cond=expr RPAREN body=block
|
|
|
{ If (cond, Block body, loc $startpos $endpos) } %prec IF
|
|
{ If (cond, Block body, loc $startpos $endpos) } %prec IF
|
|
|
|
|
|
|
|
- | IF; LPAREN; c=expr; RPAREN; t=block; ELSE; f=block
|
|
|
|
|
|
|
+ | IF LPAREN c=expr RPAREN t=block ELSE f=block
|
|
|
{ IfElse (c, Block t, Block f, loc $startpos(c) $endpos(c)) } %prec ELSE
|
|
{ IfElse (c, Block t, Block f, loc $startpos(c) $endpos(c)) } %prec ELSE
|
|
|
|
|
|
|
|
- | WHILE; LPAREN; cond=expr; RPAREN; body=block
|
|
|
|
|
|
|
+ | WHILE LPAREN cond=expr RPAREN body=block
|
|
|
{ While (cond, Block body, loc $startpos(cond) $endpos(cond)) }
|
|
{ While (cond, Block body, loc $startpos(cond) $endpos(cond)) }
|
|
|
|
|
|
|
|
- | DO; body=block; WHILE; LPAREN; cond=expr; RPAREN; SEMICOL
|
|
|
|
|
|
|
+ | DO body=block WHILE LPAREN cond=expr RPAREN SEMICOL
|
|
|
{ DoWhile (cond, Block body, loc $startpos(cond) $endpos(cond)) }
|
|
{ DoWhile (cond, Block body, loc $startpos(cond) $endpos(cond)) }
|
|
|
|
|
|
|
|
(* for-loop: use location of counter id *)
|
|
(* for-loop: use location of counter id *)
|
|
|
- | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN;
|
|
|
|
|
- body=block
|
|
|
|
|
|
|
+ | FOR LPAREN INT cnt=ID ASSIGN start=expr COMMA stop=expr RPAREN body=block
|
|
|
{ let loc = loc $startpos(cnt) $endpos(cnt) in
|
|
{ let loc = loc $startpos(cnt) $endpos(cnt) in
|
|
|
For (cnt, start, stop, Const (IntVal 1, []), Block body, loc) }
|
|
For (cnt, start, stop, Const (IntVal 1, []), Block body, loc) }
|
|
|
|
|
|
|
|
- | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; COMMA;
|
|
|
|
|
- step=expr; RPAREN; body=block
|
|
|
|
|
|
|
+ | FOR LPAREN INT cnt=ID ASSIGN start=expr COMMA stop=expr COMMA step=expr
|
|
|
|
|
+ RPAREN body=block
|
|
|
{ let loc = loc $startpos(cnt) $endpos(cnt) in
|
|
{ let loc = loc $startpos(cnt) $endpos(cnt) in
|
|
|
For (cnt, start, stop, step, Block body, loc) }
|
|
For (cnt, start, stop, step, Block body, loc) }
|
|
|
|
|
|
|
|
block:
|
|
block:
|
|
|
- | LBRACE; stats=statement*; RBRACE { stats }
|
|
|
|
|
- | stat=statement { [stat] }
|
|
|
|
|
|
|
+ | LBRACE stats=statement* RBRACE { stats }
|
|
|
|
|
+ | stat=statement { [stat] }
|
|
|
|
|
|
|
|
expr:
|
|
expr:
|
|
|
- | name=ID; LPAREN; args=separated_list(COMMA, expr); RPAREN
|
|
|
|
|
|
|
+ | name=ID LPAREN args=clist(expr) RPAREN
|
|
|
{ FunCall (name, make_args args, loc $startpos $endpos) }
|
|
{ FunCall (name, make_args args, loc $startpos $endpos) }
|
|
|
|
|
|
|
|
- | LPAREN; expr; RPAREN { $2 }
|
|
|
|
|
- | ID { Var ($1, None, loc $startpos $endpos) }
|
|
|
|
|
- | l=expr; op=binop; r=expr { Binop (op, l, r, loc $startpos $endpos) }
|
|
|
|
|
- | SUB; expr { Monop (Neg, $2, loc $startpos $endpos) } %prec NEG
|
|
|
|
|
- | NOT; expr { Monop (Not, $2, loc $startpos $endpos) }
|
|
|
|
|
- | LPAREN; basic_type; RPAREN; expr { TypeCast ($2, $4, loc $startpos $endpos) } %prec CAST
|
|
|
|
|
- | FLOAT_CONST { Const (FloatVal $1, loc $startpos $endpos) }
|
|
|
|
|
- | INT_CONST { Const (IntVal $1, loc $startpos $endpos) }
|
|
|
|
|
- | BOOL_CONST { Const (BoolVal $1, loc $startpos $endpos) }
|
|
|
|
|
- | ID; array_const { Var ($1, Some $2, loc $startpos $endpos) }
|
|
|
|
|
- | array_const { ArrayConst ($1, loc $startpos $endpos) }
|
|
|
|
|
|
|
+ | LPAREN expr RPAREN { $2 }
|
|
|
|
|
+ | ID { Var ($1, None, loc $startpos $endpos) }
|
|
|
|
|
+ | l=expr op=binop r=expr { Binop (op, l, r, loc $startpos $endpos) }
|
|
|
|
|
+ | SUB expr { Monop (Neg, $2, loc $startpos $endpos) } %prec NEG
|
|
|
|
|
+ | NOT expr { Monop (Not, $2, loc $startpos $endpos) }
|
|
|
|
|
+ | LPAREN basic_type RPAREN expr { TypeCast ($2, $4, loc $startpos $endpos) } %prec CAST
|
|
|
|
|
+ | FLOAT_CONST { Const (FloatVal $1, loc $startpos $endpos) }
|
|
|
|
|
+ | INT_CONST { Const (IntVal $1, loc $startpos $endpos) }
|
|
|
|
|
+ | BOOL_CONST { Const (BoolVal $1, loc $startpos $endpos) }
|
|
|
|
|
+ | ID array_const { Var ($1, Some $2, loc $startpos $endpos) }
|
|
|
|
|
+ | array_const { ArrayConst ($1, loc $startpos $endpos) }
|
|
|
|
|
|
|
|
%inline binop:
|
|
%inline binop:
|
|
|
| ADD { Add }
|
|
| ADD { Add }
|
|
@@ -226,7 +225,7 @@ expr:
|
|
|
| OR { Or }
|
|
| OR { Or }
|
|
|
|
|
|
|
|
array_const:
|
|
array_const:
|
|
|
- LBRACK; values=separated_list(COMMA, expr); RBRACK
|
|
|
|
|
|
|
+ LBRACK values=clist(expr) RBRACK
|
|
|
{ values }
|
|
{ values }
|
|
|
|
|
|
|
|
%%
|
|
%%
|