1 %{
2 /*****
3 * camp.y
4 * Andy Hammerlindl 08/12/2002
5 *
6 * The grammar of the camp language.
7 *****/
8
9 #include "errormsg.h"
10 #include "exp.h"
11 #include "newexp.h"
12 #include "dec.h"
13 #include "fundec.h"
14 #include "stm.h"
15 #include "modifier.h"
16 #include "opsymbols.h"
17
18 // Avoid error messages with unpatched bison-1.875:
19 #ifndef __attribute__
20 #define __attribute__(x)
21 #endif
22
23 // Used when a position needs to be determined and no token is
24 // available. Defined in camp.l.
25 position lexerPos();
26
27 bool lexerEOF();
28
29 int yylex(void); /* function prototype */
30
yyerror(const char * s)31 void yyerror(const char *s)
32 {
33 if (!lexerEOF()) {
34 em.error(lexerPos());
35 em << s;
36 em.cont();
37 }
38 }
39
40 // Check if the symbol given is "keyword". Returns true in this case and
41 // returns false and reports an error otherwise.
checkKeyword(position pos,symbol sym)42 bool checkKeyword(position pos, symbol sym)
43 {
44 if (sym != symbol::trans("keyword")) {
45 em.error(pos);
46 em << "expected 'keyword' here";
47
48 return false;
49 }
50 return true;
51 }
52
53 namespace absyntax { file *root; }
54
55 using namespace absyntax;
56 using sym::symbol;
57 using mem::string;
58 %}
59
60 %union {
61 position pos;
62 bool boo;
63 struct {
64 position pos;
65 sym::symbol sym;
66 } ps;
67 absyntax::name *n;
68 absyntax::varinit *vi;
69 absyntax::arrayinit *ai;
70 absyntax::exp *e;
71 absyntax::stringExp *stre;
72 absyntax::specExp *se;
73 absyntax::joinExp *j;
74 absyntax::explist *elist;
75 absyntax::argument arg;
76 absyntax::arglist *alist;
77 absyntax::slice *slice;
78 absyntax::dimensions *dim;
79 absyntax::ty *t;
80 absyntax::decid *di;
81 absyntax::decidlist *dil;
82 absyntax::decidstart *dis;
83 absyntax::runnable *run;
84 struct {
85 position pos;
86 trans::permission val;
87 } perm;
88 struct {
89 position pos;
90 trans::modifier val;
91 } mod;
92 absyntax::modifierList *ml;
93 //absyntax::program *prog;
94 absyntax::vardec *vd;
95 //absyntax::vardecs *vds;
96 absyntax::dec *d;
97 absyntax::idpair *ip;
98 absyntax::idpairlist *ipl;
99 absyntax::stm *s;
100 absyntax::block *b;
101 absyntax::stmExpList *sel;
102 //absyntax::funheader *fh;
103 absyntax::formal *fl;
104 absyntax::formals *fls;
105 }
106
107 %token <ps> ID SELFOP
108 DOTS COLONS DASHES INCR LONGDASH
109 CONTROLS TENSION ATLEAST CURL
110 COR CAND BAR AMPERSAND EQ NEQ LT LE GT GE CARETS
111 '+' '-' '*' '/' '%' '^' OPERATOR
112 %token <pos> LOOSE ASSIGN '?' ':'
113 DIRTAG JOIN_PREC AND
114 '{' '}' '(' ')' '.' ',' '[' ']' ';' ELLIPSIS
115 ACCESS UNRAVEL IMPORT INCLUDE FROM QUOTE STRUCT TYPEDEF NEW
116 IF ELSE WHILE DO FOR BREAK CONTINUE RETURN_
117 THIS EXPLICIT
118 GARBAGE
119 %token <e> LIT
120 %token <stre> STRING
121 %token <perm> PERM
122 %token <mod> MODIFIER
123
124 %right ASSIGN SELFOP
125 %right '?' ':'
126 %left COR
127 %left CAND
128 %left BAR
129 %left AMPERSAND
130 %left EQ NEQ
131 %left LT LE GT GE
132 %left OPERATOR
133
134 %left CARETS
135 %left JOIN_PREC DOTS COLONS DASHES INCR LONGDASH
136 %left DIRTAG CONTROLS TENSION ATLEAST AND
137 %left CURL '{' '}'
138
139 %left '+' '-'
140 %left '*' '/' '%' LIT
141 %left UNARY
142 %right '^'
143 %left EXP_IN_PARENS_RULE
144 %left '(' ')'
145
146 %type <b> fileblock bareblock block
147 %type <n> name
148 %type <run> runnable
149 %type <ml> modifiers
150 %type <d> dec fundec typedec
151 %type <ps> strid
152 %type <ip> idpair stridpair
153 %type <ipl> idpairlist stridpairlist
154 %type <vd> vardec barevardec
155 %type <t> type celltype
156 %type <dim> dims
157 %type <dil> decidlist
158 %type <di> decid
159 %type <dis> decidstart
160 %type <vi> varinit
161 %type <ai> arrayinit basearrayinit varinits
162 %type <fl> formal
163 %type <fls> formals
164 %type <e> value exp fortest
165 %type <arg> argument
166 %type <slice> slice
167 %type <j> join basicjoin
168 %type <e> tension controls
169 %type <se> dir
170 %type <elist> dimexps
171 %type <alist> arglist tuple
172 %type <s> stm stmexp blockstm
173 %type <run> forinit
174 %type <sel> forupdate stmexplist
175 %type <boo> explicitornot
176
177 /* There are four shift/reduce conflicts:
178 * the dangling ELSE in IF (exp) IF (exp) stm ELSE stm
179 * new ID
180 * the argument id=exp is taken as an argument instead of an assignExp
181 * explicit cast
182 */
183 %expect 4
184
185 /* Enable grammar debugging. */
186 /*%debug*/
187
188 %%
189
190 file:
191 fileblock { absyntax::root = $1; }
192 ;
193
194 fileblock:
195 /* empty */ { $$ = new file(lexerPos(), false); }
196 | fileblock runnable
197 { $$ = $1; $$->add($2); }
198 ;
199
200 bareblock:
201 /* empty */ { $$ = new block(lexerPos(), true); }
202 | bareblock runnable
203 { $$ = $1; $$->add($2); }
204 ;
205
206 name:
207 ID { $$ = new simpleName($1.pos, $1.sym); }
208 | name '.' ID { $$ = new qualifiedName($2, $1, $3.sym); }
209 | '%' { $$ = new simpleName($1.pos,
210 symbol::trans("operator answer")); }
211 ;
212
213 runnable:
214 dec { $$ = $1; }
215 | stm { $$ = $1; }
216 | modifiers dec
217 { $$ = new modifiedRunnable($1->getPos(), $1, $2); }
218 | modifiers stm
219 { $$ = new modifiedRunnable($1->getPos(), $1, $2); }
220 ;
221
222 modifiers:
223 MODIFIER { $$ = new modifierList($1.pos); $$->add($1.val); }
224 | PERM { $$ = new modifierList($1.pos); $$->add($1.val); }
225 | modifiers MODIFIER
226 { $$ = $1; $$->add($2.val); }
227 | modifiers PERM
228 { $$ = $1; $$->add($2.val); }
229 ;
230
231 dec:
232 vardec { $$ = $1; }
233 | fundec { $$ = $1; }
234 | typedec { $$ = $1; }
235 | ACCESS stridpairlist ';'
236 { $$ = new accessdec($1, $2); }
237 | FROM name UNRAVEL idpairlist ';'
238 { $$ = new unraveldec($1, $2, $4); }
239 | FROM name UNRAVEL '*' ';'
240 { $$ = new unraveldec($1, $2, WILDCARD); }
241 | UNRAVEL name ';' { $$ = new unraveldec($1, $2, WILDCARD); }
242 | FROM strid ACCESS idpairlist ';'
243 { $$ = new fromaccessdec($1, $2.sym, $4); }
244 | FROM strid ACCESS '*' ';'
245 { $$ = new fromaccessdec($1, $2.sym, WILDCARD); }
246 | IMPORT stridpair ';'
247 { $$ = new importdec($1, $2); }
248 | INCLUDE ID ';' { $$ = new includedec($1, $2.sym); }
249 | INCLUDE STRING ';'
250 { $$ = new includedec($1, $2->getString()); }
251 ;
252
253 idpair:
254 ID { $$ = new idpair($1.pos, $1.sym); }
255 /* ID 'as' ID */
256 | ID ID ID { $$ = new idpair($1.pos, $1.sym, $2.sym , $3.sym); }
257 ;
258
259 idpairlist:
260 idpair { $$ = new idpairlist(); $$->add($1); }
261 | idpairlist ',' idpair
262 { $$ = $1; $$->add($3); }
263 ;
264
265 strid:
266 ID { $$ = $1; }
267 | STRING { $$.pos = $1->getPos();
268 $$.sym = symbol::literalTrans($1->getString()); }
269 ;
270
271 stridpair:
272 ID { $$ = new idpair($1.pos, $1.sym); }
273 /* strid 'as' ID */
274 | strid ID ID { $$ = new idpair($1.pos, $1.sym, $2.sym , $3.sym); }
275 ;
276
277 stridpairlist:
278 stridpair { $$ = new idpairlist(); $$->add($1); }
279 | stridpairlist ',' stridpair
280 { $$ = $1; $$->add($3); }
281 ;
282
283 vardec:
284 barevardec ';' { $$ = $1; }
285 ;
286
287 barevardec:
288 type decidlist { $$ = new vardec($1->getPos(), $1, $2); }
289 ;
290
291 type:
292 celltype { $$ = $1; }
293 | name dims { $$ = new arrayTy($1, $2); }
294 ;
295
296 celltype:
297 name { $$ = new nameTy($1); }
298 ;
299
300 dims:
301 '[' ']' { $$ = new dimensions($1); }
302 | dims '[' ']' { $$ = $1; $$->increase(); }
303 ;
304
305 dimexps:
306 '[' exp ']' { $$ = new explist($1); $$->add($2); }
307 | dimexps '[' exp ']'
308 { $$ = $1; $$->add($3); }
309 ;
310
311 decidlist:
312 decid { $$ = new decidlist($1->getPos()); $$->add($1); }
313 | decidlist ',' decid
314 { $$ = $1; $$->add($3); }
315 ;
316
317 decid:
318 decidstart { $$ = new decid($1->getPos(), $1); }
319 | decidstart ASSIGN varinit
320 { $$ = new decid($1->getPos(), $1, $3); }
321 ;
322
323 decidstart:
324 ID { $$ = new decidstart($1.pos, $1.sym); }
325 | ID dims { $$ = new decidstart($1.pos, $1.sym, $2); }
326 | ID '(' ')' { $$ = new fundecidstart($1.pos, $1.sym, 0,
327 new formals($2)); }
328 | ID '(' formals ')'
329 { $$ = new fundecidstart($1.pos, $1.sym, 0, $3); }
330 ;
331
332 varinit:
333 exp { $$ = $1; }
334 | arrayinit { $$ = $1; }
335 ;
336
337 block:
338 '{' bareblock '}'
339 { $$ = $2; }
340 ;
341
342 arrayinit:
343 '{' '}' { $$ = new arrayinit($1); }
344 | '{' ELLIPSIS varinit '}'
345 { $$ = new arrayinit($1); $$->addRest($3); }
346 | '{' basearrayinit '}'
347 { $$ = $2; }
348 | '{' basearrayinit ELLIPSIS varinit '}'
349 { $$ = $2; $$->addRest($4); }
350 ;
351
352 basearrayinit:
353 ',' { $$ = new arrayinit($1); }
354 | varinits { $$ = $1; }
355 | varinits ',' { $$ = $1; }
356 ;
357
358 varinits:
359 varinit { $$ = new arrayinit($1->getPos());
360 $$->add($1);}
361 | varinits ',' varinit
362 { $$ = $1; $$->add($3); }
363 ;
364
365 formals:
366 formal { $$ = new formals($1->getPos()); $$->add($1); }
367 | ELLIPSIS formal { $$ = new formals($1); $$->addRest($2); }
368 | formals ',' formal
369 { $$ = $1; $$->add($3); }
370 | formals ELLIPSIS formal
371 { $$ = $1; $$->addRest($3); }
372 ;
373
374 explicitornot:
375 EXPLICIT { $$ = true; }
376 | { $$ = false; }
377 ;
378
379 formal:
380 explicitornot type
381 { $$ = new formal($2->getPos(), $2, 0, 0, $1, 0); }
382 | explicitornot type decidstart
383 { $$ = new formal($2->getPos(), $2, $3, 0, $1, 0); }
384 | explicitornot type decidstart ASSIGN varinit
385 { $$ = new formal($2->getPos(), $2, $3, $5, $1, 0); }
386 /* The uses of ID below are 'keyword' qualifiers before the parameter name. */
387 | explicitornot type ID decidstart
388 { bool k = checkKeyword($3.pos, $3.sym);
389 $$ = new formal($2->getPos(), $2, $4, 0, $1, k); }
390 | explicitornot type ID decidstart ASSIGN varinit
391 { bool k = checkKeyword($3.pos, $3.sym);
392 $$ = new formal($2->getPos(), $2, $4, $6, $1, k); }
393 ;
394
395 fundec:
396 type ID '(' ')' blockstm
397 { $$ = new fundec($3, $1, $2.sym, new formals($3), $5); }
398 | type ID '(' formals ')' blockstm
399 { $$ = new fundec($3, $1, $2.sym, $4, $6); }
400 ;
401
402 typedec:
403 STRUCT ID block { $$ = new recorddec($1, $2.sym, $3); }
404 | TYPEDEF vardec { $$ = new typedec($1, $2); }
405 ;
406
407 slice:
408 ':' { $$ = new slice($1, 0, 0); }
409 | exp ':' { $$ = new slice($2, $1, 0); }
410 | ':' exp { $$ = new slice($1, 0, $2); }
411 | exp ':' exp { $$ = new slice($2, $1, $3); }
412 ;
413
414 value:
415 value '.' ID { $$ = new fieldExp($2, $1, $3.sym); }
416 | name '[' exp ']' { $$ = new subscriptExp($2,
417 new nameExp($1->getPos(), $1), $3); }
418 | value '[' exp ']'{ $$ = new subscriptExp($2, $1, $3); }
419 | name '[' slice ']' { $$ = new sliceExp($2,
420 new nameExp($1->getPos(), $1), $3); }
421 | value '[' slice ']'{ $$ = new sliceExp($2, $1, $3); }
422 | name '(' ')' { $$ = new callExp($2,
423 new nameExp($1->getPos(), $1),
424 new arglist()); }
425 | name '(' arglist ')'
426 { $$ = new callExp($2,
427 new nameExp($1->getPos(), $1),
428 $3); }
429 | value '(' ')' { $$ = new callExp($2, $1, new arglist()); }
430 | value '(' arglist ')'
431 { $$ = new callExp($2, $1, $3); }
432 | '(' exp ')' %prec EXP_IN_PARENS_RULE
433 { $$ = $2; }
434 | '(' name ')' %prec EXP_IN_PARENS_RULE
435 { $$ = new nameExp($2->getPos(), $2); }
436 | THIS { $$ = new thisExp($1); }
437 ;
438
439 argument:
440 exp { $$.name = symbol::nullsym; $$.val=$1; }
441 | ID ASSIGN exp { $$.name = $1.sym; $$.val=$3; }
442 ;
443
444 arglist:
445 argument { $$ = new arglist(); $$->add($1); }
446 | ELLIPSIS argument
447 { $$ = new arglist(); $$->addRest($2); }
448 | arglist ',' argument
449 { $$ = $1; $$->add($3); }
450 | arglist ELLIPSIS argument
451 { $$ = $1; $$->addRest($3); }
452 ;
453
454 /* A list of two or more expressions, separated by commas. */
455 tuple:
456 exp ',' exp { $$ = new arglist(); $$->add($1); $$->add($3); }
457 | tuple ',' exp { $$ = $1; $$->add($3); }
458 ;
459
460 exp:
461 name { $$ = new nameExp($1->getPos(), $1); }
462 | value { $$ = $1; }
463 | LIT { $$ = $1; }
464 | STRING { $$ = $1; }
465 /* This is for scaling expressions such as 105cm */
466 | LIT exp { $$ = new scaleExp($1->getPos(), $1, $2); }
467 | '(' name ')' exp
468 { $$ = new castExp($2->getPos(), new nameTy($2), $4); }
469 | '(' name dims ')' exp
470 { $$ = new castExp($2->getPos(), new arrayTy($2, $3), $5); }
471 | '+' exp %prec UNARY
472 { $$ = new unaryExp($1.pos, $2, $1.sym); }
473 | '-' exp %prec UNARY
474 { $$ = new unaryExp($1.pos, $2, $1.sym); }
475 | OPERATOR exp { $$ = new unaryExp($1.pos, $2, $1.sym); }
476 | exp '+' exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
477 | exp '-' exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
478 | exp '*' exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
479 | exp '/' exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
480 | exp '%' exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
481 | exp '^' exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
482 | exp LT exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
483 | exp LE exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
484 | exp GT exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
485 | exp GE exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
486 | exp EQ exp { $$ = new equalityExp($2.pos, $1, $2.sym, $3); }
487 | exp NEQ exp { $$ = new equalityExp($2.pos, $1, $2.sym, $3); }
488 | exp CAND exp { $$ = new andExp($2.pos, $1, $2.sym, $3); }
489 | exp COR exp { $$ = new orExp($2.pos, $1, $2.sym, $3); }
490 | exp CARETS exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
491 | exp AMPERSAND exp{ $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
492 | exp BAR exp{ $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
493 | exp OPERATOR exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
494 | exp INCR exp { $$ = new binaryExp($2.pos, $1, $2.sym, $3); }
495 | NEW celltype
496 { $$ = new newRecordExp($1, $2); }
497 | NEW celltype dimexps
498 { $$ = new newArrayExp($1, $2, $3, 0, 0); }
499 | NEW celltype dimexps dims
500 { $$ = new newArrayExp($1, $2, $3, $4, 0); }
501 | NEW celltype dims
502 { $$ = new newArrayExp($1, $2, 0, $3, 0); }
503 | NEW celltype dims arrayinit
504 { $$ = new newArrayExp($1, $2, 0, $3, $4); }
505 | NEW celltype '(' ')' blockstm
506 { $$ = new newFunctionExp($1, $2, new formals($3), $5); }
507 | NEW celltype dims '(' ')' blockstm
508 { $$ = new newFunctionExp($1,
509 new arrayTy($2->getPos(), $2, $3),
510 new formals($4),
511 $6); }
512 | NEW celltype '(' formals ')' blockstm
513 { $$ = new newFunctionExp($1, $2, $4, $6); }
514 | NEW celltype dims '(' formals ')' blockstm
515 { $$ = new newFunctionExp($1,
516 new arrayTy($2->getPos(), $2, $3),
517 $5,
518 $7); }
519 | exp '?' exp ':' exp
520 { $$ = new conditionalExp($2, $1, $3, $5); }
521 | exp ASSIGN exp { $$ = new assignExp($2, $1, $3); }
522 | '(' tuple ')' { $$ = new callExp($1, new nameExp($1, SYM_TUPLE), $2); }
523 | exp join exp %prec JOIN_PREC
524 { $2->pushFront($1); $2->pushBack($3); $$ = $2; }
525 | exp dir %prec DIRTAG
526 { $2->setSide(camp::OUT);
527 joinExp *jexp =
528 new joinExp($2->getPos(), SYM_DOTS);
529 $$=jexp;
530 jexp->pushBack($1); jexp->pushBack($2); }
531 | INCR exp %prec UNARY
532 { $$ = new prefixExp($1.pos, $2, SYM_PLUS); }
533 | DASHES exp %prec UNARY
534 { $$ = new prefixExp($1.pos, $2, SYM_MINUS); }
535 /* Illegal - will be caught during translation. */
536 | exp INCR %prec UNARY
537 { $$ = new postfixExp($2.pos, $1, SYM_PLUS); }
538 | exp SELFOP exp { $$ = new selfExp($2.pos, $1, $2.sym, $3); }
539 | QUOTE '{' fileblock '}'
540 { $$ = new quoteExp($1, $3); }
541 ;
542
543 // This verbose definition is because leaving empty as an expansion for dir
544 // made a whack of reduce/reduce errors.
545 join:
546 DASHES { $$ = new joinExp($1.pos,$1.sym); }
547 | basicjoin %prec JOIN_PREC
548 { $$ = $1; }
549 | dir basicjoin %prec JOIN_PREC
550 { $1->setSide(camp::OUT);
551 $$ = $2; $$->pushFront($1); }
552 | basicjoin dir %prec JOIN_PREC
553 { $2->setSide(camp::IN);
554 $$ = $1; $$->pushBack($2); }
555 | dir basicjoin dir %prec JOIN_PREC
556 { $1->setSide(camp::OUT); $3->setSide(camp::IN);
557 $$ = $2; $$->pushFront($1); $$->pushBack($3); }
558 ;
559
560 dir:
561 '{' CURL exp '}' { $$ = new specExp($2.pos, $2.sym, $3); }
562 | '{' exp '}' { $$ = new specExp($1, symbol::opTrans("spec"), $2); }
563 | '{' exp ',' exp '}'
564 { $$ = new specExp($1, symbol::opTrans("spec"),
565 new pairExp($3, $2, $4)); }
566 | '{' exp ',' exp ',' exp '}'
567 { $$ = new specExp($1, symbol::opTrans("spec"),
568 new tripleExp($3, $2, $4, $6)); }
569 ;
570
571 basicjoin:
572 DOTS { $$ = new joinExp($1.pos, $1.sym); }
573 | DOTS tension DOTS
574 { $$ = new joinExp($1.pos, $1.sym); $$->pushBack($2); }
575 | DOTS controls DOTS
576 { $$ = new joinExp($1.pos, $1.sym); $$->pushBack($2); }
577 | COLONS { $$ = new joinExp($1.pos, $1.sym); }
578 | LONGDASH { $$ = new joinExp($1.pos, $1.sym); }
579 ;
580
581 tension:
582 TENSION exp { $$ = new binaryExp($1.pos, $2, $1.sym,
583 new booleanExp($1.pos, false)); }
584 | TENSION exp AND exp
585 { $$ = new ternaryExp($1.pos, $2, $1.sym, $4,
586 new booleanExp($1.pos, false)); }
587 | TENSION ATLEAST exp
588 { $$ = new binaryExp($1.pos, $3, $1.sym,
589 new booleanExp($2.pos, true)); }
590 | TENSION ATLEAST exp AND exp
591 { $$ = new ternaryExp($1.pos, $3, $1.sym, $5,
592 new booleanExp($2.pos, true)); }
593 ;
594
595 controls:
596 CONTROLS exp { $$ = new unaryExp($1.pos, $2, $1.sym); }
597 | CONTROLS exp AND exp
598 { $$ = new binaryExp($1.pos, $2, $1.sym, $4); }
599 ;
600
601 stm:
602 ';' { $$ = new emptyStm($1); }
603 | blockstm { $$ = $1; }
604 | stmexp ';' { $$ = $1; }
605 | IF '(' exp ')' stm
606 { $$ = new ifStm($1, $3, $5); }
607 | IF '(' exp ')' stm ELSE stm
608 { $$ = new ifStm($1, $3, $5, $7); }
609 | WHILE '(' exp ')' stm
610 { $$ = new whileStm($1, $3, $5); }
611 | DO stm WHILE '(' exp ')' ';'
612 { $$ = new doStm($1, $2, $5); }
613 | FOR '(' forinit ';' fortest ';' forupdate ')' stm
614 { $$ = new forStm($1, $3, $5, $7, $9); }
615 | FOR '(' type ID ':' exp ')' stm
616 { $$ = new extendedForStm($1, $3, $4.sym, $6, $8); }
617 | BREAK ';' { $$ = new breakStm($1); }
618 | CONTINUE ';' { $$ = new continueStm($1); }
619 | RETURN_ ';' { $$ = new returnStm($1); }
620 | RETURN_ exp ';' { $$ = new returnStm($1, $2); }
621 ;
622
623 stmexp:
624 exp { $$ = new expStm($1->getPos(), $1); }
625 ;
626
627 blockstm:
628 block { $$ = new blockStm($1->getPos(), $1); }
629 ;
630
631 forinit:
632 /* empty */ { $$ = 0; }
633 | stmexplist { $$ = $1; }
634 | barevardec { $$ = $1; }
635 ;
636
637 fortest:
638 /* empty */ { $$ = 0; }
639 | exp { $$ = $1; }
640 ;
641
642 forupdate:
643 /* empty */ { $$ = 0; }
644 | stmexplist { $$ = $1; }
645 ;
646
647 stmexplist:
648 stmexp { $$ = new stmExpList($1->getPos()); $$->add($1); }
649 | stmexplist ',' stmexp
650 { $$ = $1; $$->add($3); }
651 ;
652