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