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