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