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