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