Fix the remaining 12 shift/reduce conflicts
[tiger.ml.git] / tiger / src / lib / tiger / tiger_parser.mly
1 %{
2 open Printf
3 %}
4
5 /* Declarations */
6 %token AND
7 %token ARRAY
8 %token ASSIGN
9 %token BREAK
10 %token COLON
11 %token COMMA
12 %token DIVIDE
13 %token DO
14 %token DOT
15 %token ELSE
16 %token END
17 %token EOF
18 %token EQ
19 %token FOR
20 %token FUNCTION
21 %token GE
22 %token GT
23 %token <string> ID
24 %token IF
25 %token IN
26 %token <int> INT
27 %token LBRACE
28 %token LBRACK
29 %token LE
30 %token LET
31 %token LPAREN
32 %token LT
33 %token MINUS
34 %token NEQ
35 %token NIL
36 %token OF
37 %token OR
38 %token PLUS
39 %token RBRACE
40 %token RBRACK
41 %token RPAREN
42 %token SEMICOLON
43 %token <string> STRING
44 %token THEN
45 %token TIMES
46 %token TO
47 %token TYPE
48 %token VAR
49 %token WHILE
50
51 /* from lowest precedence */
52 %left THEN
53 %left ELSE
54 %nonassoc ASSIGN
55 %left OF DO
56 %left OR
57 %left AND
58 %nonassoc EQ NEQ GT LT GE LE
59 %left PLUS MINUS
60 %left TIMES DIVIDE
61 %nonassoc UMINUS
62 /* to highest precedence */
63
64 %type <string> program
65
66 %start program
67
68 %%
69
70 program:
71 | exp EOF
72 {
73 sprintf "program[%s]" $1
74 }
75 ;
76
77 exp:
78 | NIL
79 {
80 "nil[]"
81 }
82 | INT
83 {
84 sprintf "int[%d]" $1
85 }
86 | MINUS exp %prec UMINUS
87 {
88 sprintf "negation[%s]" $2
89 }
90 | ID LBRACK exp RBRACK OF exp
91 {
92 let type_id = $1 in
93 let number_of_elements = $3 in
94 let initial_value = $6 in
95 sprintf
96 "array[type[%s], size[%s], val[%s]]"
97 type_id number_of_elements initial_value
98 }
99 | ID LBRACE rec_field_assignments RBRACE
100 {
101 let type_id = $1 in
102 let rec_field_assignments = $3 in
103 sprintf
104 "record[type[%s], rec_field_assignments[%s]]"
105 type_id rec_field_assignments
106 }
107 | lvalue
108 {
109 $1
110 }
111 | lvalue ASSIGN exp
112 {
113 sprintf "assign[%s := %s]" $1 $3
114 }
115 | STRING
116 {
117 sprintf "string[%S]" $1
118 }
119 | ID LPAREN RPAREN
120 {
121 let id = $1 in
122 sprintf "fun_call[%s, []]" id
123 }
124 | ID LPAREN fun_args RPAREN
125 {
126 let id = $1 in
127 let fun_args = $3 in
128 sprintf "fun_call[%s, %s]" id fun_args
129 }
130 | exp PLUS exp
131 {
132 sprintf "op_plus[%s + %s]" $1 $3
133 }
134 | exp MINUS exp
135 {
136 sprintf "op_minus[%s - %s]" $1 $3
137 }
138 | exp TIMES exp
139 {
140 sprintf "op_times[%s * %s]" $1 $3
141 }
142 | exp DIVIDE exp
143 {
144 sprintf "op_divide[%s / %s]" $1 $3
145 }
146 | exp EQ exp
147 {
148 sprintf "op_eq[%s = %s]" $1 $3
149 }
150 | exp NEQ exp
151 {
152 sprintf "op_neq[%s <> %s]" $1 $3
153 }
154 | exp GT exp
155 {
156 sprintf "op_gt[%s > %s]" $1 $3
157 }
158 | exp LT exp
159 {
160 sprintf "op_lt[%s < %s]" $1 $3
161 }
162 | exp GE exp
163 {
164 sprintf "op_ge[%s >= %s]" $1 $3
165 }
166 | exp LE exp
167 {
168 sprintf "op_le[%s <= %s]" $1 $3
169 }
170 | exp AND exp
171 {
172 sprintf "op_and[%s & %s]" $1 $3
173 }
174 | exp OR exp
175 {
176 sprintf "op_or[%s | %s]" $1 $3
177 }
178 | IF exp THEN exp ELSE exp
179 {
180 let e1 = $2 in
181 let e2 = $4 in
182 let e3 = $6 in
183 sprintf "if_then_else[%s, then[%s], else[%s]]" e1 e2 e3
184 }
185 | IF exp THEN exp
186 {
187 sprintf "if_then[%s, then[%s]]" $2 $4
188 }
189 | WHILE exp DO exp
190 {
191 sprintf "while[%s, do[%s]]" $2 $4
192 }
193 | FOR ID ASSIGN exp TO exp DO exp
194 {
195 let id = $2 in
196 let e1 = $4 in
197 let e2 = $6 in
198 let e3 = $8 in
199 sprintf "for[%s := %s, to[%s], do[%s]]" id e1 e2 e3
200 }
201 | BREAK
202 {
203 "break[]"
204 }
205 | LPAREN exps RPAREN
206 {
207 sprintf "exps[%s]" $2
208 }
209 | LET decs IN exps END
210 {
211 let decs = $2 in
212 let exps = $4 in
213 sprintf "let[decs[%s], in[exps[%s]]]" decs exps
214 }
215 | LPAREN RPAREN
216 {
217 (* Perhaps "void"? *)
218 "unit[]"
219 }
220 ;
221
222 rec_field_assignments:
223 | ID EQ exp
224 {
225 let id = $1 in
226 let exp = $3 in
227 sprintf "%S = %s" id exp
228 }
229 | ID EQ exp COMMA rec_field_assignments
230 {
231 let id = $1 in
232 let exp = $3 in
233 let rec_field_assignments = $5 in
234 sprintf "%S = %s, %s" id exp rec_field_assignments
235 }
236 ;
237
238 exps:
239 | exp
240 {
241 let exp = $1 in
242 sprintf "%s" exp
243 }
244 | exp SEMICOLON exps
245 {
246 let exp = $1 in
247 let exps = $3 in
248 sprintf "%s; %s" exp exps
249 }
250 ;
251
252 decs:
253 | dec
254 {
255 sprintf "%s" $1
256 }
257 | dec decs
258 {
259 sprintf "%s %s" $1 $2
260 }
261 ;
262
263 dec:
264 /* Tydec */
265 | TYPE ID EQ ID
266 {
267 let type_id_new = $2 in
268 let type_id_orig = $4 in
269 sprintf "tydec_alias[from[%s], to[%s]]" type_id_new type_id_orig
270 }
271 | TYPE ID EQ LBRACE RBRACE
272 {
273 let type_id = $2 in
274 sprintf "tydec_empty_record[%s]" type_id
275 }
276 | TYPE ID EQ LBRACE tyfields RBRACE
277 {
278 let type_id = $2 in
279 let tyfields = $5 in
280 sprintf "tydec_record[%s, fields[%s]]" type_id tyfields
281 }
282 | TYPE ID EQ ARRAY OF ID
283 {
284 let type_id = $2 in
285 let element_type_id = $6 in
286 sprintf "tydec_array[%s, elements_of_type[%s]]" type_id element_type_id
287 }
288
289 /* Vardec */
290 | VAR ID ASSIGN exp
291 {
292 let id = $2 in
293 let exp = $4 in
294 sprintf "vardec[%s, exp[%s]]" id exp
295 }
296 | VAR ID COLON ID ASSIGN exp
297 {
298 let id = $2 in
299 let type_id = $4 in
300 let exp = $6 in
301 sprintf "vardec[%s, type_id[%s], exp[%s]]" id type_id exp
302 }
303
304 /* Fundec */
305 | FUNCTION ID LPAREN RPAREN EQ exp
306 {
307 let id = $2 in
308 let exp = $6 in
309 sprintf "fundec[%s, arguments[], exp[%s]]" id exp
310 }
311 | FUNCTION ID LPAREN tyfields RPAREN EQ exp
312 {
313 let id = $2 in
314 let tyfields = $4 in
315 let exp = $7 in
316 sprintf "fundec[%s, arguments[%s], exp[%s]]" id tyfields exp
317 }
318 | FUNCTION ID LPAREN tyfields RPAREN COLON ID EQ exp
319 {
320 let id = $2 in
321 let tyfields = $4 in
322 let type_id = $7 in
323 let exp = $9 in
324 sprintf
325 "fundec[%s, tyfields[%s], type_id[%s], exp[%s]]"
326 id tyfields type_id exp
327 }
328 ;
329
330 tyfields:
331 | ID COLON ID
332 {
333 let id_1 = $1 in
334 let id_2 = $3 in
335 sprintf "%s : %s" id_1 id_2
336 }
337 | ID COLON ID COMMA tyfields
338 {
339 let id_1 = $1 in
340 let id_2 = $3 in
341 let tyfield = sprintf "%s : %s" id_1 id_2 in
342 let tyfields = $5 in
343 sprintf "%s, %s" tyfield tyfields
344 }
345 ;
346
347 fun_args:
348 | exp
349 {
350 $1
351 }
352 | exp COMMA fun_args
353 {
354 sprintf "%s, %s" $1 $3
355 }
356 ;
357
358 lvalue:
359 | ID lvalue_part
360 {
361 let id = $1 in
362 let part = $2 in
363 sprintf "lvalue[%s, part[%s]]" id part
364 }
365 ;
366
367 lvalue_part:
368 | {"epsilon[]"}
369 | lvalue_subscript {$1}
370 | lvalue_field_access {$1}
371 ;
372
373 lvalue_subscript:
374 | LBRACK exp RBRACK
375 {
376 let exp = $2 in
377 sprintf "subscript[%s]" exp
378 }
379 ;
380
381 lvalue_field_access:
382 | DOT ID
383 {
384 let field = $2 in
385 sprintf "field_access[%s]" field
386 }
387 ;
388
389 %%
This page took 0.0603359999999999 seconds and 4 git commands to generate.