-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcool.cup
380 lines (326 loc) · 11.5 KB
/
cool.cup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/*
* cool.cup
* Parser definition for the COOL language.
*
*/
import java_cup.runtime.*;
/* Stuff enclosed in {: :} is copied verbatim to the class containing
all parser actions. All the extra variables/functions you want to use
in the semantic actions should go here. Don't remove or modify anything
that was there initially. */
action code {:
int curr_lineno() {
return ((CoolTokenLexer)parser.getScanner()).curr_lineno();
}
AbstractSymbol curr_filename() {
return ((CoolTokenLexer)parser.getScanner()).curr_filename();
}
:}
/************************************************************************/
/* DONT CHANGE ANYTHING IN THIS SECTION */
parser code {:
int omerrs = 0;
public void syntax_error(Symbol cur_token) {
int lineno = action_obj.curr_lineno();
String filename = action_obj.curr_filename().getString();
System.err.print("\"" + filename + "\", line " + lineno +
": parse error at or near ");
Utilities.printToken(cur_token);
omerrs++;
if (omerrs>50) {
System.err.println("More than 50 errors");
System.exit(1);
}
}
public void unrecovered_syntax_error(Symbol cur_token) {
}
:}
/* Declare the terminals; a few have types for associated lexemes. The
token ERROR is never used in the parser; thus, it is a parse error when
the lexer returns it. */
terminal CLASS, ELSE, FI, IF, IN, INHERITS, LET, LET_STMT, LOOP, POOL, THEN, WHILE;
terminal CASE, ESAC, OF, DARROW, NEW, ISVOID;
terminal ASSIGN, NOT, LE, ERROR;
terminal PLUS, DIV, MINUS, MULT, EQ, LT, DOT, NEG, COMMA, SEMI, COLON;
terminal LPAREN, RPAREN, AT, LBRACE, RBRACE;
terminal AbstractSymbol STR_CONST, INT_CONST;
terminal Boolean BOOL_CONST;
terminal AbstractSymbol TYPEID, OBJECTID;
/* DON'T CHANGE ANYTHING ABOVE THIS LINE, OR YOUR PARSER WONT WORK */
/**************************************************************************/
/* Complete the nonterminal list below, giving a type for the semantic
value of each non terminal. (See the CUP documentation for details. */
nonterminal programc program;
nonterminal Classes class_list;
nonterminal class_c class_decl;
nonterminal Features feature_list;
nonterminal Feature feature;
nonterminal Formals formal_list;
nonterminal Formals non_empty_formal_list;
nonterminal Formal formal;
nonterminal Expression expression;
nonterminal Expression atomic_expression;
nonterminal Expression arith_expression;
nonterminal Expression case_expression;
nonterminal Case case;
nonterminal Cases cases;
nonterminal Expression let_sequence;
nonterminal Expression maybe_expr_in_let;
nonterminal Expression block;
nonterminal Expressions non_empty_expr_list;
nonterminal Expression dispatch;
nonterminal Expression static_dispatch;
nonterminal Expression dynamic_dispatch;
nonterminal Expressions method_args;
nonterminal Expressions non_empty_method_args;
nonterminal Expression assignment;
/* Precedence declarations go here. */
precedence left PLUS, MINUS;
precedence left MULT, DIV;
precedence left ISVOID, NEG;
precedence nonassoc LE, EQ;
precedence left DOT;
program ::=
class_list:cl
{: RESULT = new programc(curr_lineno(), cl); :}
;
class_list ::=
/* single class */
CLASS class_decl:c SEMI
{: RESULT = (new Classes(curr_lineno())).appendElement(c); :}
|
/* several classes */
class_list:cl CLASS class_decl:c SEMI
{: RESULT = cl.appendElement(c); :}
|
/* several classes with error */
class_list:cl CLASS error SEMI
{: RESULT = cl; :}
|
/* error */
CLASS error SEMI
{: RESULT = new Classes(curr_lineno()); :}
;
/* If no parent is specified, the class inherits from the Object class */
class_decl ::=
TYPEID:n LBRACE feature_list:f RBRACE
{: RESULT = new class_c(curr_lineno(), n,
AbstractTable.idtable.addString("Object"),
f, curr_filename()); :}
|
TYPEID:n INHERITS TYPEID:p LBRACE feature_list:f RBRACE
{: RESULT = new class_c(curr_lineno(), n, p, f, curr_filename()); :}
;
/* Feature list may be empty, but no empty features in list. */
feature_list ::=
/* empty */
{: RESULT = new Features(curr_lineno()); :}
|
/* several features */
feature_list:fl feature:f SEMI
{: RESULT = fl.appendElement(f); :}
|
/* several features with an error*/
feature_list:fl error SEMI
{: RESULT = fl; :}
;
feature ::=
/* an attribute withinit expression*/
OBJECTID:n COLON TYPEID:t ASSIGN expression:e
{: RESULT = new attr(curr_lineno(), n, t, e); :}
|
/* an attribute without init expression*/
OBJECTID:n COLON TYPEID:t
{: RESULT = new attr(curr_lineno(), n, t,
new no_expr(curr_lineno())); :}
|
/* a method with a body */
OBJECTID:n LPAREN formal_list:fs RPAREN COLON TYPEID:t LBRACE expression:e RBRACE
{: RESULT = new method(curr_lineno(), n, fs, t, e); :}
;
/* Formal list */
formal_list ::=
/* empty */
{: RESULT = new Formals(curr_lineno()); :}
|
/* several formals */
non_empty_formal_list:fl
{: RESULT = fl; :}
;
non_empty_formal_list ::=
formal: f
{: RESULT = (new Formals(curr_lineno())).appendElement(f); :}
|
/* several formals */
non_empty_formal_list:fl COMMA formal:f
{: RESULT = fl.appendElement(f); :}
;
formal ::=
OBJECTID:n COLON TYPEID:t
{: RESULT = new formalc(curr_lineno(), n, t); :}
;
expression ::=
assignment:e
{: RESULT = e; :}
|
dispatch:e
{: RESULT = e; :}
|
IF expression:e1 THEN expression:e2 ELSE expression:e3 FI
{: RESULT = new cond(curr_lineno(), e1, e2, e3); :}
|
WHILE expression:e1 LOOP expression:e2 POOL
{: RESULT = new loop(curr_lineno(), e1, e2); :}
|
block:e
{: RESULT = e; :}
|
LET let_sequence:e
{: RESULT = e; :}
|
case_expression:e
{: RESULT = e; :}
|
NEW TYPEID:t
{: RESULT = new new_(curr_lineno(), t); :}
|
ISVOID expression:e
{: RESULT = new isvoid(curr_lineno(), e); :}
|
arith_expression:e
{: RESULT = e; :}
|
LPAREN expression:e RPAREN
{: RESULT = e; :}
|
atomic_expression:e
{: RESULT = e; :}
;
assignment ::=
OBJECTID:n ASSIGN expression:e
{: RESULT = new assign(curr_lineno(), n, e); :}
;
dispatch ::=
static_dispatch:e
{: RESULT = e; :}
|
dynamic_dispatch:e
{: RESULT = e; :}
;
static_dispatch ::=
expression:e DOT OBJECTID:method LPAREN method_args:args RPAREN
{: RESULT = new dispatch(curr_lineno(), e, method, args); :}
|
/* default to "self" */
OBJECTID:method LPAREN method_args:args RPAREN
{: AbstractSymbol selfSymbol = AbstractTable.inttable.addString("self");
Expression self = new object(curr_lineno(), selfSymbol);
RESULT = new dispatch(curr_lineno(), self, method, args); :}
;
dynamic_dispatch ::=
expression:e AT TYPEID:type DOT OBJECTID:method LPAREN method_args:args RPAREN
{: RESULT = new static_dispatch(curr_lineno(), e, type, method, args); :}
;
method_args ::=
/* empty list */
{: RESULT = new Expressions(curr_lineno()); :}
|
non_empty_method_args:es
{: RESULT = es; :}
;
non_empty_method_args ::=
expression:e
{: RESULT = (new Expressions(curr_lineno())).appendElement(e); :}
|
non_empty_method_args:es COMMA expression:e
{: RESULT = es.appendElement(e); :}
;
block ::=
LBRACE non_empty_expr_list:el RBRACE
{: RESULT = new block(curr_lineno(), el); :}
;
non_empty_expr_list ::=
expression:e SEMI
{: RESULT = (new Expressions(curr_lineno())).appendElement(e); :}
|
non_empty_expr_list:el expression:e SEMI
{: RESULT = el.appendElement(e); :}
|
error SEMI
{: RESULT = new Expressions(curr_lineno()); :}
;
let_sequence ::=
OBJECTID:n COLON TYPEID:t maybe_expr_in_let:e1 IN expression:e2
{: RESULT = new let(curr_lineno(), n, t, e1, e2); :}
|
OBJECTID:n COLON TYPEID:t maybe_expr_in_let:e1 COMMA let_sequence:e2
{: RESULT = new let(curr_lineno(), n, t, e1, e2); :}
|
error COMMA let_sequence:e2
{: RESULT = e2; :}
;
maybe_expr_in_let ::=
ASSIGN expression:e
{: RESULT = e; :}
|
/* empty expression */
{: RESULT = new no_expr(curr_lineno()); :}
;
case_expression ::=
CASE expression:e OF cases:cs ESAC
{: RESULT = new typcase(curr_lineno(), e, cs); :}
;
cases ::=
/* single case */
case:c SEMI
{: RESULT = (new Cases(curr_lineno())).appendElement(c); :}
|
/* several cases */
cases:cl case:c SEMI
{: RESULT = cl.appendElement(c); :}
;
case ::=
OBJECTID:n COLON TYPEID:t DARROW expression:e
{: RESULT = new branch(curr_lineno(), n, t, e); :}
;
atomic_expression ::=
OBJECTID:n
{: RESULT = new object(curr_lineno(), n); :}
|
INT_CONST:i
{: RESULT = new int_const(curr_lineno(), i); :}
|
STR_CONST:s
{: RESULT = new string_const(curr_lineno(), s); :}
|
BOOL_CONST:b
{: RESULT = new bool_const(curr_lineno(), b); :}
;
arith_expression ::=
expression:e1 PLUS expression:e2
{: RESULT = new plus(curr_lineno(), e1, e2); :}
|
expression:e1 MINUS expression:e2
{: RESULT = new sub(curr_lineno(), e1, e2); :}
|
expression:e1 MULT expression:e2
{: RESULT = new mul(curr_lineno(), e1, e2); :}
|
expression:e1 DIV expression:e2
{: RESULT = new divide(curr_lineno(), e1, e2); :}
|
NEG expression:e
{: RESULT = new neg(curr_lineno(), e); :}
|
expression:e1 LT expression:e2
{: RESULT = new lt(curr_lineno(), e1, e2); :}
|
expression:e1 LE expression:e2
{: RESULT = new leq(curr_lineno(), e1, e2); :}
|
expression:e1 EQ expression:e2
{: RESULT = new eq(curr_lineno(), e1, e2); :}
|
NOT expression:e
{: RESULT = new comp(curr_lineno(), e); :}
;