parser.mly 7.6 KB

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