parser.mly 7.0 KB

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