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