parser.mly 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. %{
  2. (**
  3. * Parser for the CiviC language.
  4. *
  5. * Note that some shift/reduce conflicts exist, but these need not be solved
  6. * since menhir can automatically resolve them
  7. *)
  8. open Lexing
  9. open Ast
  10. let loc = Util.loc_from_lexpos
  11. let rec make_dims dimloc = function
  12. | [] -> []
  13. | dim :: tail -> Dim (dim, dimloc) :: (make_dims dimloc tail)
  14. let rec make_args = function
  15. | [] -> []
  16. | h::t -> Arg h :: (make_args t)
  17. %}
  18. (* Tokens *)
  19. %token LPAREN RPAREN LBRACK RBRACK LBRACE RBRACE SEMICOL COMMA
  20. %token NOT ADD SUB MUL DIV MOD
  21. %token EQ NE LT LE GT GE
  22. %token AND OR
  23. %token ASSIGN IF ELSE WHILE DO FOR RETURN EXTERN EXPORT
  24. %token INT BOOL FLOAT VOID
  25. %token EOF
  26. %token <bool> BOOL_CONST
  27. %token <float> FLOAT_CONST
  28. %token <int> INT_CONST
  29. %token <string> ID
  30. (* Precedence *)
  31. (*%right ASSIGN*)
  32. %left OR
  33. %left AND
  34. %left EQ NE
  35. %left LT LE GT GE
  36. %left ADD SUB
  37. %left MUL DIV MOD
  38. %right NOT NEG CAST
  39. %nonassoc IF
  40. %nonassoc ELSE
  41. (* Start symbol *)
  42. %type <Ast.node> program
  43. %start program
  44. %%
  45. basic_type:
  46. | FLOAT { Float }
  47. | INT { Int }
  48. | BOOL { Bool }
  49. program:
  50. decl*; EOF
  51. { Program ($1, loc $startpos $endpos) }
  52. decl:
  53. (* function: use location of function name *)
  54. | EXTERN; hdr=fun_header; SEMICOL
  55. { let (t, n, p, nameloc) = hdr in
  56. FunDec(t, n, p, nameloc) }
  57. | export=boption(EXPORT); hdr=fun_header; LBRACE; body=fun_body; RBRACE
  58. { let (t, n, p, nameloc) = hdr in
  59. FunDef (export, t, n, p, Block body, nameloc) }
  60. (* global variable declaration: use location of variable name *)
  61. | EXTERN; ctype=basic_type; name=ID; SEMICOL
  62. { GlobalDec (ctype, name, loc $startpos $endpos) }
  63. | EXTERN; ctype=basic_type;
  64. LBRACK; dims=separated_list(COMMA, ID); RBRACK;
  65. name=ID; SEMICOL
  66. { let dimloc = loc $startpos(dims) $endpos(dims) in
  67. let loc = loc $startpos(name) $endpos(name) in
  68. GlobalDec (ArrayDec (ctype, make_dims dimloc dims), name, loc) }
  69. | export=boption(EXPORT); ctype=basic_type; name=ID; SEMICOL
  70. { let loc = loc $startpos(name) $endpos(name) in
  71. GlobalDef (export, ctype, name, None, loc) }
  72. | export=boption(EXPORT); ctype=basic_type; name=ID; ASSIGN; init=expr; SEMICOL
  73. { let loc = loc $startpos(name) $endpos(name) in
  74. GlobalDef (export, ctype, name, Some init, loc) }
  75. | export=boption(EXPORT); ctype=basic_type;
  76. LBRACK; dims=separated_list(COMMA, expr); RBRACK;
  77. name=ID; SEMICOL
  78. { let loc = loc $startpos(name) $endpos(name) in
  79. GlobalDef (export, ArrayDef (ctype, dims), name, None, loc) }
  80. | export=boption(EXPORT); ctype=basic_type;
  81. LBRACK; dims=separated_list(COMMA, expr); RBRACK;
  82. name=ID; ASSIGN; init=expr; SEMICOL
  83. { let loc = loc $startpos(name) $endpos(name) in
  84. GlobalDef (export, ArrayDef (ctype, dims), name, Some init, loc) }
  85. fun_header:
  86. (* function header: use location of function name *)
  87. | ret=basic_type; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
  88. { (ret, name, params, loc $startpos(name) $endpos(name)) }
  89. | VOID; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
  90. { (Void, name, params, loc $startpos(name) $endpos(name)) }
  91. param:
  92. (* parameter: use location of parameter name *)
  93. | ctype=basic_type; name=ID
  94. { Param (ctype, name, loc $startpos(name) $endpos(name)) }
  95. | ctype=basic_type; LBRACK; dims=separated_list(COMMA, ID); RBRACK; name=ID
  96. { let dimloc = loc $startpos(dims) $endpos(dims) in
  97. let loc = loc $startpos(name) $endpos(name) in
  98. Param (ArrayDec (ctype, make_dims dimloc dims), name, loc) }
  99. fun_body:
  100. | var_dec* local_fun_dec* statement* loption(return_statement)
  101. { $1 @ $2 @ $3 @ $4 }
  102. return_statement:
  103. (* return statement: use location of return value *)
  104. | RETURN; value=expr; SEMICOL
  105. { [Return (value, loc $startpos(value) $endpos(value))] }
  106. (* function: use location of function name *)
  107. local_fun_dec:
  108. hdr=fun_header; LBRACE; body=fun_body; RBRACE
  109. { let (t, n, p, nameloc) = hdr in
  110. FunDef (false, t, n, p, Block body, nameloc) }
  111. var_dec:
  112. (* variable declaration: use location of variable name *)
  113. | ctype=basic_type; name=ID; SEMICOL
  114. { VarDec (ctype, name, None, loc $startpos(name) $endpos(name)) }
  115. | ctype=basic_type; name=ID; ASSIGN; init=expr; SEMICOL
  116. { VarDec (ctype, name, Some init, loc $startpos(name) $endpos(name)) }
  117. | ctype=basic_type; LBRACK; dims=separated_list(COMMA, expr); RBRACK;
  118. name=ID; SEMICOL
  119. { let loc = loc $startpos(name) $endpos(name) in
  120. VarDec (ArrayDef (ctype, dims), name, None, loc) }
  121. | ctype=basic_type; LBRACK; dims=separated_list(COMMA, expr); RBRACK;
  122. name=ID; ASSIGN; init=expr; SEMICOL
  123. { let loc = loc $startpos(name) $endpos(name) in
  124. VarDec (ArrayDef (ctype, dims), name, Some init, loc) }
  125. statement:
  126. (* assignment: use location of assigned variable name *)
  127. | name=ID; ASSIGN; value=expr; SEMICOL
  128. { Assign (name, None, value, loc $startpos(name) $endpos(name)) }
  129. | name=ID; LBRACK; dims=separated_list(COMMA, expr); brk=RBRACK;
  130. ASSIGN; value=expr; SEMICOL
  131. { Assign (name, Some dims, value, loc $startpos(name) $endpos(brk)) }
  132. | name=ID; LPAREN; args=separated_list(COMMA, expr); RPAREN; SEMICOL
  133. { Expr (FunCall (name, make_args args, loc $startpos(name) $endpos(name))) }
  134. (* if-statements and (do-)while-loops: use location of condition *)
  135. | IF; LPAREN; cond=expr; RPAREN; body=block
  136. { If (cond, Block body, loc $startpos $endpos) } %prec IF
  137. | IF; LPAREN; c=expr; RPAREN; t=block; ELSE; f=block
  138. { IfElse (c, Block t, Block f, loc $startpos(c) $endpos(c)) } %prec ELSE
  139. | WHILE; LPAREN; cond=expr; RPAREN; body=block
  140. { While (cond, Block body, loc $startpos(cond) $endpos(cond)) }
  141. | DO; body=block; WHILE; LPAREN; cond=expr; RPAREN; SEMICOL
  142. { DoWhile (cond, Block body, loc $startpos(cond) $endpos(cond)) }
  143. (* for-loop: use location of counter id *)
  144. | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN;
  145. body=block
  146. { let loc = loc $startpos(cnt) $endpos(cnt) in
  147. For (cnt, start, stop, IntConst (1, noloc), Block body, loc) }
  148. | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; COMMA;
  149. step=expr; RPAREN; body=block
  150. { let loc = loc $startpos(cnt) $endpos(cnt) in
  151. For (cnt, start, stop, step, Block body, loc) }
  152. block:
  153. | LBRACE; stats=statement*; RBRACE { stats }
  154. | stat=statement { [stat] }
  155. expr:
  156. | name=ID; LPAREN; args=separated_list(COMMA, expr); RPAREN
  157. { FunCall (name, make_args args, loc $startpos $endpos) }
  158. | LPAREN; expr; RPAREN { $2 }
  159. | ID { Var ($1, loc $startpos $endpos) }
  160. | l=expr; op=binop; r=expr { Binop (op, l, r, loc $startpos $endpos) }
  161. | SUB; expr { Monop (Neg, $2, loc $startpos $endpos) } %prec NEG
  162. | NOT; expr { Monop (Not, $2, loc $startpos $endpos) }
  163. | LPAREN; basic_type; RPAREN; expr { TypeCast ($2, $4, loc $startpos $endpos) } %prec CAST
  164. | FLOAT_CONST { FloatConst ($1, loc $startpos $endpos) }
  165. | INT_CONST { IntConst ($1, loc $startpos $endpos) }
  166. | BOOL_CONST { BoolConst ($1, loc $startpos $endpos) }
  167. | ID; array_const { Deref ($1, $2, loc $startpos $endpos) }
  168. | array_const { ArrayConst ($1, loc $startpos $endpos) }
  169. %inline binop:
  170. | ADD { Add }
  171. | SUB { Sub }
  172. | MUL { Mul }
  173. | DIV { Div }
  174. | MOD { Mod }
  175. | EQ { Eq }
  176. | NE { Ne }
  177. | LT { Lt }
  178. | LE { Le }
  179. | GT { Gt }
  180. | GE { Ge }
  181. | AND { And }
  182. | OR { Or }
  183. array_const:
  184. LBRACK; values=separated_list(COMMA, expr); RBRACK
  185. { values }
  186. %%