exec: beginexec exec1 { TEST fprintf(diagfile, "exec done\n"); } ; beginexec: { $$ = bgnexec(); if(ncases > 0) ncases = 0; } ; exec1: lhs ASGNOP expr { if($1->tag==TCALL) { dclerr("no statement functions in EFL", $1->sthead->namep); frexpr($1); frexpr($3); } else exasgn($1,$2,$3); } | DOUBLEADDOP lhs { exasgn($2, $1, mkint(1) ); } | lhs1 { excall($1); } | CALL lhs1 { excall($2); } | debug exec enddebug | LBRACK beginblock stats endblock RBRACK { TEST fprintf(diagfile, "exec: { stats }\n"); addexec(); } | labels exec1 { thisexec->labeled = 1; } | control { thisexec->uniffable = 1; popctl(); } | branch { thisexec->brnchend = 1; } | iostat { exio($1, 0); } | null { exnull(); } | ESCAPE { exnull(); putsii(ICCOMMENT, $1); cfree($1); exnull(); } ; null: { TEST fprintf(diagfile, "exec:empty\n"); } | CONTINUE { TEST fprintf(diagfile, "exec: continue\n"); } ; beginblock: { thisexec->copylab = 1; ++blklevel; dclsect = 1; ndecl[blklevel] = 0; nhid [blklevel] = 0; } ; endblock: { if(ndecl[blklevel]) unhide(); --blklevel; dclsect = 0; } ; labels: NAME COLON contnu { mklabel($1,YES); } | CONST contnu { mklabel(mkilab($1),YES); } | CONST contnu COLON contnu { mklabel(mkilab($1),YES); } | DEFAULT COLON contnu { brkcase(); mkcase(PNULL,1); } | CASE { brkcase(); } caselist COLON contnu ; caselist: expr { mkcase($1,1); } | caselist COMMA expr { mkcase($3,1); } ; control: ifclause contnu exec EOS ELSE elsecode contnu exec { TEST fprintf(diagfile, "if-then-else\n"); i = $3->brnchend & $8->brnchend; addexec(); $$ = addexec(); thisexec->brnchend = i; TEST fprintf(diagfile, "exec: if(expr) exec else exec\n"); } | ifclause contnu exec EOS { TEST fprintf(diagfile, "if-then\n"); pushlex = 1; yyclearin; $$ = ifthen(); TEST fprintf(diagfile, "exec: if(expr) exec\n"); } | repeat contnu exec until { TEST fprintf(diagfile, "repeat done\n"); } | leftcont contnu exec { TEST fprintf(diagfile, "exec: control exec\n"); $$ = addexec(); } ; ifclause: IF LPAR expr RPAR { pushctl(STIF,$3); } ; elsecode: { if(thisctl->breaklab == 0) thisctl->breaklab = nextlab(); /* if(thisexec->prevexec->brnchend == 0) */ exgoto(thisctl->breaklab); exlab( indifs[thisctl->indifn] = nextlab() ); } ; repeat: REPEAT { pushctl(STREPEAT, PNULL); } ; until: EOS { pushlex = 1; yyclearin; $$ = addexec(); exgoto(thisctl->xlab); TEST fprintf(diagfile, " no until\n"); } | EOS UNTIL LPAR expr RPAR { $$ = addexec(); exnull(); exlab( indifs[thisctl->indifn] = nextlab() ); exifgo(mknode(TNOTOP,OPNOT,$4,PNULL), thisctl->xlab); TEST fprintf(diagfile, "until\n"); } ; branch: RETURN { exretn(PNULL); } | RETURN expr { exretn($2); } | break | GOTO label { exgoto($2); } | GO NAME label { if( !equals($2->namep, "to") ) execerr("go %s ??\n", $2->namep); else exgoto($3); } | GOTO parlablist compgotoindex { excompgoto($2, $3); } | GO NAME parlablist compgotoindex { if(!equals($2->namep, "to") ) execerr("go %s ??\n", $2->namep); else excompgoto($3, $4); } ; parlablist: LPAR lablist RPAR { $$ = $2; } ; lablist: label { $$ = mkchain($1,CHNULL); } | lablist COMMA label { $$ = hookup($1, mkchain($3,CHNULL) ); } ; compgotoindex: expr | COMMA expr { $$ = $2; } ; label: NAME { $$ = mklabel($1,NO); } | CONST { $$ = mklabel(mkilab($1),NO); } | CASE expr { $$ = mkcase($2,0); } | DEFAULT { $$ = mkcase(PNULL,0); } ; break: brk { exbrk($1, PNULL, 0); } | brk CONST { exbrk($1, $2, 0); } | brk blocktype { exbrk($1, PNULL, $2); } | brk CONST blocktype { exbrk($1,$2,$3); } | brk blocktype CONST { exbrk($1,$3,$2); } ; brk: NEXT { $$ = 1; } | BREAK { $$ = 0; } | EXIT { $$ = 0; } ; blocktype: WHILE { $$ = STWHILE; } | FOR { $$ = STFOR; } | DO { $$ = STDO; } | REPEAT { $$ = STREPEAT; } | SWITCH { $$ = STSWITCH; } | PROCEDURE { $$ = STPROC; } ; leftcont: WHILE LPAR exprnull RPAR { pushctl(STWHILE, $3); TEST fprintf(diagfile, "while(expr)\n"); } | for forinit fortest forincr { exlab(thisctl->xlab); if($3) exifgo(mknode(TNOTOP,OPNOT,$3,PNULL), thisctl->breaklab = nextlab() ); else exnull(); TEST fprintf(diagfile, "for (forlist)\n"); } | SWITCH LPAR expr RPAR { pushctl(STSWITCH, simple(LVAL,$3)); TEST fprintf(diagfile, "switch (expr)\n"); } | do { pushctl(STDO, $1); TEST fprintf(diagfile, "do loop\n"); } ; do: DO expr EOS contnu { $$ = doloop($2, PNULL, PNULL); } | DO expr contnu { $$ = doloop($2, PNULL, PNULL); } | DO expr COMMA expr EOS contnu { $$ = doloop($2, $4, PNULL); } | DO expr COMMA expr contnu { $$ = doloop($2, $4, PNULL); } | DO expr COMMA expr COMMA expr EOS contnu { $$ = doloop($2,$4,$6); } | DO expr COMMA expr COMMA expr contnu { $$ = doloop($2,$4,$6); } ; for: FOR LPAR { pushctl(STFOR, PNULL); } ; forinit: exec COMMA { exgoto(thisctl->xlab); exlab(thisctl->nextlab); addexec(); } | exec EOS contnu COMMA { exgoto(thisctl->xlab); exlab(thisctl->nextlab); addexec(); } ; fortest: exprnull COMMA ; forincr: exec RPAR { addexec(); } | exec EOS contnu RPAR { addexec(); } ; exprnull: { $$ = 0; } | expr ; debug: DEBUG contnu { if(dbgopt) ++dbglevel; } ; enddebug: { if(dbgopt) --dbglevel; } ; iostat: iokwd LPAR iounit COMMA iolist RPAR { $$ = mkiost($1, $3, $5); } ; iokwd: READBIN { $$ = 0; } | WRITEBIN { $$ = 1; } | READ { $$ = 2; } | WRITE { $$ = 3; } ; iounit: expr | { $$ = NULL; } ; iolist: ioitem { $$ = mkchain($1,CHNULL); } | iolist COMMA ioitem { hookup($1, mkchain($3,CHNULL)); } ; ioitem: expr { $$ = mkioitem($1,CNULL); } | expr COLON format { $$ = mkioitem($1,$3); } | COLON format { $$ = mkioitem(PNULL,$2); } | iobrace { $$ = mkiogroup($1, CNULL, PNULL); } | do iobrace { $$ = mkiogroup($2, CNULL, $1); } | do iobrace COLON format { $$ = mkiogroup($2,$4,$1); } | iobrace COLON format { $$ = mkiogroup($1,$3,PNULL); } ; iobrace: LBRACK { ++iobrlevel; } iolist RBRACK { --iobrlevel; $$ = $3; } ; format: letter { $$ = mkformat($1, PNULL, PNULL); } | letter LPAR expr RPAR { $$ = mkformat($1, $3, PNULL); } | letter LPAR expr COMMA expr RPAR { $$ = mkformat($1,$3,$5); } | letton CONST lettoff { $$ = $2->leftp; frexpblock($2); } ; letter: letton LETTER lettoff { $$ = $2; } ; letton: { lettneed = YES;} ; lettoff: { lettneed = NO; } ; %% setyydeb() { #ifdef YYDEBUG extern int yydebug; yydebug = 1; #endif }