4.4BSD/usr/src/old/efl/gram.exec

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
}