Complete 1.04.p: add semantic actions to parser
[tiger.ml.git] / tiger / src / lib / tiger / tiger_parser.mly
CommitLineData
543d3420 1%{
28875fec
SK
2 module Ast = Tiger_absyn
3 module Sym = Tiger_symbol
4
5 let pos () =
6 Tiger_position.of_lexing_positions
7 ~pos_start:(Parsing.symbol_start_pos ())
8 ~pos_end:(Parsing.symbol_end_pos ())
543d3420
SK
9%}
10
11/* Declarations */
12%token AND
13%token ARRAY
14%token ASSIGN
15%token BREAK
16%token COLON
17%token COMMA
18%token DIVIDE
19%token DO
20%token DOT
21%token ELSE
22%token END
23%token EOF
24%token EQ
25%token FOR
26%token FUNCTION
27%token GE
28%token GT
29%token <string> ID
30%token IF
31%token IN
32%token <int> INT
33%token LBRACE
34%token LBRACK
35%token LE
36%token LET
37%token LPAREN
38%token LT
39%token MINUS
40%token NEQ
41%token NIL
42%token OF
43%token OR
44%token PLUS
45%token RBRACE
46%token RBRACK
47%token RPAREN
48%token SEMICOLON
49%token <string> STRING
50%token THEN
51%token TIMES
52%token TO
53%token TYPE
54%token VAR
55%token WHILE
56
57/* from lowest precedence */
28875fec
SK
58%nonassoc LOWEST
59%nonassoc THEN
60%nonassoc ELSE
c7598faf 61%nonassoc ASSIGN
28875fec 62%nonassoc OF DO
543d3420
SK
63%left OR
64%left AND
65%nonassoc EQ NEQ GT LT GE LE
66%left PLUS MINUS
67%left TIMES DIVIDE
28875fec 68%nonassoc HIGHEST
543d3420
SK
69/* to highest precedence */
70
28875fec 71%type <Tiger_absyn.t> program
543d3420
SK
72
73%start program
74
75%%
76
28875fec 77program: exp EOF { $1 };
543d3420
SK
78
79exp:
80 | NIL
28875fec 81 { Ast.NilExp }
543d3420 82 | INT
28875fec
SK
83 { Ast.IntExp $1 }
84 | MINUS exp %prec HIGHEST
85 {
86 Ast.OpExp
87 { left = Ast.IntExp 0
88 ; oper = Ast.MinusOp
89 ; right = $2
90 ; pos = pos ()
91 }
92 }
93 | lvalue LBRACK exp RBRACK OF exp
94 {
95 match $1 with
96 | Ast.SimpleVar {symbol=typ; _} ->
97 Ast.ArrayExp
98 { typ
99 ; size = $3
100 ; init = $6
101 ; pos = pos ()
102 }
103 | Ast.SubscriptVar _ | Ast.FieldVar _ ->
104 raise Parse_error
105 }
106 | ID LBRACE rec_fields_bind RBRACE
543d3420 107 {
ef945634 108 let type_id = $1 in
28875fec
SK
109 let fields = $3 in
110 let typ = Sym.of_string type_id in
111 let pos = pos () in
112 Ast.RecordExp {fields; typ; pos}
543d3420
SK
113 }
114 | lvalue
28875fec 115 { Ast.VarExp $1 }
543d3420
SK
116 | lvalue ASSIGN exp
117 {
28875fec
SK
118 let var = $1 in
119 let exp = $3 in
120 let pos = pos () in
121 Ast.AssignExp {var; exp; pos}
543d3420
SK
122 }
123 | STRING
28875fec 124 { Ast.StringExp {string = $1; pos = pos ()} }
29de275c
SK
125 | ID LPAREN fun_args RPAREN
126 {
28875fec
SK
127 Ast.CallExp
128 { func = Sym.of_string $1
129 ; args = $3
130 ; pos = pos ()
131 }
543d3420 132 }
6a74bf44 133 | exp PLUS exp
543d3420 134 {
28875fec
SK
135 Ast.OpExp
136 { left = $1
137 ; oper = Ast.PlusOp
138 ; right = $3
139 ; pos = pos ()
140 }
6a74bf44
SK
141 }
142 | exp MINUS exp
143 {
28875fec
SK
144 Ast.OpExp
145 { left = $1
146 ; oper = Ast.MinusOp
147 ; right = $3
148 ; pos = pos ()
149 }
6a74bf44
SK
150 }
151 | exp TIMES exp
152 {
28875fec
SK
153 Ast.OpExp
154 { left = $1
155 ; oper = Ast.TimesOp
156 ; right = $3
157 ; pos = pos ()
158 }
6a74bf44
SK
159 }
160 | exp DIVIDE exp
161 {
28875fec
SK
162 Ast.OpExp
163 { left = $1
164 ; oper = Ast.DivideOp
165 ; right = $3
166 ; pos = pos ()
167 }
6a74bf44
SK
168 }
169 | exp EQ exp
170 {
28875fec
SK
171 Ast.OpExp
172 { left = $1
173 ; oper = Ast.EqOp
174 ; right = $3
175 ; pos = pos ()
176 }
6a74bf44
SK
177 }
178 | exp NEQ exp
179 {
28875fec
SK
180 Ast.OpExp
181 { left = $1
182 ; oper = Ast.NeqOp
183 ; right = $3
184 ; pos = pos ()
185 }
6a74bf44
SK
186 }
187 | exp GT exp
188 {
28875fec
SK
189 Ast.OpExp
190 { left = $1
191 ; oper = Ast.GtOp
192 ; right = $3
193 ; pos = pos ()
194 }
6a74bf44
SK
195 }
196 | exp LT exp
197 {
28875fec
SK
198 Ast.OpExp
199 { left = $1
200 ; oper = Ast.LtOp
201 ; right = $3
202 ; pos = pos ()
203 }
6a74bf44
SK
204 }
205 | exp GE exp
206 {
28875fec
SK
207 Ast.OpExp
208 { left = $1
209 ; oper = Ast.GeOp
210 ; right = $3
211 ; pos = pos ()
212 }
6a74bf44
SK
213 }
214 | exp LE exp
215 {
28875fec
SK
216 Ast.OpExp
217 { left = $1
218 ; oper = Ast.LeOp
219 ; right = $3
220 ; pos = pos ()
221 }
6a74bf44
SK
222 }
223 | exp AND exp
224 {
28875fec
SK
225 let e1 = $1 in
226 let e2 = $3 in
227 Ast.IfExp
228 { test = e1
229 ; then' = e2
230 ; else' = Some (Ast.IntExp 0)
231 ; pos = pos ()
232 }
6a74bf44
SK
233 }
234 | exp OR exp
235 {
28875fec
SK
236 let e1 = $1 in
237 let e2 = $3 in
238 Ast.IfExp
239 { test = e1
240 ; then' = Ast.IntExp 1
241 ; else' = Some e2
242 ; pos = pos ()
243 }
543d3420
SK
244 }
245 | IF exp THEN exp ELSE exp
246 {
247 let e1 = $2 in
248 let e2 = $4 in
249 let e3 = $6 in
28875fec
SK
250 Ast.IfExp
251 { test = e1
252 ; then' = e2
253 ; else' = Some e3
254 ; pos = pos ()
255 }
543d3420
SK
256 }
257 | IF exp THEN exp
258 {
28875fec
SK
259 let e1 = $2 in
260 let e2 = $4 in
261 Ast.IfExp
262 { test = e1
263 ; then' = e2
264 ; else' = None
265 ; pos = pos ()
266 }
543d3420
SK
267 }
268 | WHILE exp DO exp
269 {
28875fec
SK
270 let e1 = $2 in
271 let e2 = $4 in
272 Ast.WhileExp
273 { test = e1
274 ; body = e2
275 ; pos = pos ()
276 }
543d3420 277 }
ffff6f35 278 | FOR ID ASSIGN exp TO exp DO exp
543d3420 279 {
28875fec
SK
280 let var = $2 in
281 let e1 = $4 in
282 let e2 = $6 in
283 let e3 = $8 in
284 Ast.ForExp
285 { var = Sym.of_string var
286 ; escape = ref true
287 ; lo = e1
288 ; hi = e2
289 ; body = e3
290 ; pos = pos ()
291 }
543d3420
SK
292 }
293 | BREAK
28875fec 294 { Ast.BreakExp (pos ()) }
e7dfac93 295 | LPAREN exps RPAREN
28875fec 296 { Ast.SeqExp $2 }
e7dfac93 297 | LET decs IN exps END
543d3420
SK
298 {
299 let decs = $2 in
e7dfac93 300 let exps = $4 in
28875fec 301 Ast.LetExp {decs; body = Ast.SeqExp exps; pos = pos ()}
543d3420 302 }
a0db5523 303 ;
543d3420 304
28875fec
SK
305exps:
306 | { [] }
307 | exp { ($1, pos ()) :: [] }
308 | exp SEMICOLON exps { ($1, pos ()) :: $3 }
a0db5523 309 ;
b3c9d54d 310
28875fec
SK
311rec_fields_bind:
312 | ID EQ exp { (Sym.of_string $1, $3, pos ()) :: [] }
313 | ID EQ exp COMMA rec_fields_bind { (Sym.of_string $1, $3, pos ()) :: $5 }
a0db5523 314 ;
543d3420
SK
315
316decs:
28875fec
SK
317 | dec { $1 :: [] }
318 | dec decs { $1 :: $2 }
a0db5523 319 ;
543d3420
SK
320
321dec:
28875fec
SK
322 | var_dec { $1 }
323 | typ_decs %prec LOWEST { Ast.TypeDecs $1 }
324 | fun_decs %prec LOWEST { Ast.FunDecs $1 }
325 ;
326
327typ_decs:
328 | typ_dec { $1 :: [] }
329 | typ_dec typ_decs %prec LOWEST { $1 :: $2 }
330 ;
331
332typ_dec:
3fbeb7c1 333 | TYPE ID EQ ID
ef945634 334 {
28875fec
SK
335 let type_id_left = $2 in
336 let type_id_right = $4 in
337 let pos = pos () in (* FIXME: rhs id should have its own pos, no? *)
338 Ast.TypeDec
339 { name = Sym.of_string type_id_left
340 ; ty = Ast.NameTy {symbol = Sym.of_string type_id_right; pos}
341 ; pos
342 }
ef945634 343 }
28875fec 344 | TYPE ID EQ LBRACE type_fields RBRACE
543d3420 345 {
3fbeb7c1 346 let type_id = $2 in
28875fec
SK
347 let type_fields = $5 in
348 Ast.TypeDec
349 { name = Sym.of_string type_id
350 ; ty = Ast.RecordTy type_fields
351 ; pos = pos ()
352 }
3fbeb7c1
SK
353 }
354 | TYPE ID EQ ARRAY OF ID
355 {
28875fec
SK
356 let type_id = Sym.of_string $2 in
357 let element_type_id = Sym.of_string $6 in
358 let pos = pos () in
359 Ast.TypeDec
360 { name = type_id
361 ; ty = Ast.ArrayTy {symbol = element_type_id; pos}
362 ; pos
363 }
543d3420 364 }
28875fec 365 ;
543d3420 366
28875fec
SK
367var_dec:
368 | VAR ID maybe_type_sig ASSIGN exp
369 {
370 let var_id = Sym.of_string $2 in
371 let maybe_type_sig = $3 in
372 let exp = $5 in
373 let pos = pos () in
374 Ast.VarDec
375 { name = var_id
376 ; escape = ref true
377 ; typ = maybe_type_sig
378 ; init = exp
379 ; pos
380 }
543d3420 381 }
28875fec 382 ;
543d3420 383
28875fec
SK
384fun_decs:
385 | fun_dec { $1 :: [] }
386 | fun_dec fun_decs %prec LOWEST { $1 :: $2 }
387 ;
388
389fun_dec:
390 | FUNCTION ID LPAREN type_fields RPAREN maybe_type_sig EQ exp
543d3420 391 {
28875fec
SK
392 let name = Sym.of_string $2 in
393 let params = $4 in
394 let result = $6 in
395 let body = $8 in
396 let pos = pos () in
397 Ast.FunDec {name; params; result; body; pos}
543d3420 398 }
a0db5523 399 ;
543d3420 400
28875fec
SK
401maybe_type_sig:
402 | { None }
403 | COLON ID { Some (Sym.of_string $2, pos ()) }
404 ;
405
406type_fields:
407 |
408 { [] }
a87678f0 409 | ID COLON ID
543d3420 410 {
28875fec
SK
411 let field =
412 Ast.Field
413 { name = Sym.of_string $1
414 ; escape = ref true
415 ; typ = Sym.of_string $3
416 ; pos = pos ()
417 }
418 in
419 field :: []
420 }
421 | ID COLON ID COMMA type_fields
422 {
423 let field =
424 Ast.Field
425 { name = Sym.of_string $1
426 ; escape = ref true
427 ; typ = Sym.of_string $3
428 ; pos = pos ()
429 }
430 in
431 field :: $5
543d3420 432 }
a0db5523 433 ;
543d3420 434
543d3420 435fun_args:
28875fec
SK
436 | { [] }
437 | exp { $1 :: [] }
438 | exp COMMA fun_args { $1 :: $3 }
a0db5523 439 ;
543d3420 440
543d3420 441lvalue:
28875fec 442 | ID
543d3420 443 {
28875fec
SK
444 Ast.SimpleVar
445 { symbol = Sym.of_string $1
446 ; pos = pos ()
447 }
543d3420 448 }
28875fec 449 | lvalue LBRACK exp RBRACK
543d3420 450 {
28875fec
SK
451 Ast.SubscriptVar
452 { var = $1
453 ; exp = $3
454 ; pos = pos ()
455 }
543d3420 456 }
28875fec 457 | lvalue DOT ID
543d3420 458 {
28875fec
SK
459 Ast.FieldVar
460 { var = $1
461 ; symbol = Sym.of_string $3
462 ; pos = pos ()
463 }
543d3420 464 }
a0db5523 465 ;
543d3420
SK
466
467%%
This page took 0.065094 seconds and 4 git commands to generate.