📄 cgram.y
字号:
swend(); deflab(brklab); if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; resetbc(FCONT); } | BREAK SM ={ if( brklab == NOLAB ) uerror( "illegal break"); else if(reached) branch( brklab ); flostat |= FBRK; if( brkflag ) goto rch; reached = 0; } | CONTINUE SM ={ if( contlab == NOLAB ) uerror( "illegal continue"); else branch( contlab ); flostat |= FCONT; goto rch; } | RETURN SM ={ retstat |= NRETVAL; branch( retlab ); rch: if( !reached ) werror( "statement not reached"); reached = 0; } | RETURN e SM ={ register NODE *temp; idname = curftn; temp = buildtree( NAME, NIL, NIL ); temp->type = DECREF( temp->type ); temp = buildtree( RETURN, temp, $2 ); /* now, we have the type of the RHS correct */ temp->left->op = FREE; temp->op = FREE; ecomp( buildtree( FORCE, temp->right, NIL ) ); retstat |= RETVAL; branch( retlab ); reached = 0; } | GOTO NAME SM ={ register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); q->rval = idname = $2; defid( q, ULABEL ); stab[idname].suse = -lineno; branch( stab[idname].offset ); goto rch; } | SM | error SM | error RC | label statement ;label: NAME COLON ={ register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); q->rval = $1; defid( q, LABEL ); reached = 1; } | CASE e COLON ={ addcase($2); reached = 1; } | DEFAULT COLON ={ reached = 1; adddef(); flostat |= FDEF; } ;doprefix: DO ={ savebc(); if( !reached ) werror( "loop not entered at top"); brklab = getlab(); contlab = getlab(); deflab( $$ = getlab() ); reached = 1; } ;ifprefix: IF LP e RP ={ ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ; reached = 1; } ;ifelprefix: ifprefix statement ELSE ={ if( reached ) branch( $$ = getlab() ); else $$ = NOLAB; deflab( $1 ); reached = 1; } ;whprefix: WHILE LP e RP ={ savebc(); if( !reached ) werror( "loop not entered at top"); if( $3->op == ICON && $3->lval != 0 ) flostat = FLOOP; deflab( contlab = getlab() ); reached = 1; brklab = getlab(); if( flostat == FLOOP ) tfree( $3 ); else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) ); } ;forprefix: FOR LP .e SM .e SM ={ if( $3 ) ecomp( $3 ); else if( !reached ) werror( "loop not entered at top"); savebc(); contlab = getlab(); brklab = getlab(); deflab( $$ = getlab() ); reached = 1; if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) ); else flostat |= FLOOP; } ;switchpart: SWITCH LP e RP ={ savebc(); brklab = getlab(); ecomp( buildtree( FORCE, $3, NIL ) ); branch( $$ = getlab() ); swstart(); reached = 0; } ;/* EXPRESSIONS */con_e: { $<intval>$=instruct; stwart=instruct=0; } e %prec CM ={ $$ = icons( $2 ); instruct=$<intval>1; } ;.e: e | ={ $$=0; } ;elist: e %prec CM | elist CM e ={ goto bop; } ;e: e RELOP e ={ preconf: if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){ precplaint: if( hflag ) werror( "precedence confusion possible: parenthesize!" ); } bop: $$ = buildtree( $2, $1, $3 ); } | e CM e ={ $2 = COMOP; goto bop; } | e DIVOP e ={ goto bop; } | e PLUS e ={ if(yychar==SHIFTOP) goto precplaint; else goto bop; } | e MINUS e ={ if(yychar==SHIFTOP ) goto precplaint; else goto bop; } | e SHIFTOP e ={ if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } | e MUL e ={ goto bop; } | e EQUOP e ={ goto preconf; } | e AND e ={ if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } | e OR e ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } | e ER e ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } | e ANDAND e ={ goto bop; } | e OROR e ={ goto bop; } | e MUL ASSIGN e ={ abop: $$ = buildtree( ASG $2, $1, $4 ); } | e DIVOP ASSIGN e ={ goto abop; } | e PLUS ASSIGN e ={ goto abop; } | e MINUS ASSIGN e ={ goto abop; } | e SHIFTOP ASSIGN e ={ goto abop; } | e AND ASSIGN e ={ goto abop; } | e OR ASSIGN e ={ goto abop; } | e ER ASSIGN e ={ goto abop; } | e QUEST e COLON e ={ $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) ); } | e ASOP e ={ werror( "old-fashioned assignment operator" ); goto bop; } | e ASSIGN e ={ goto bop; } | term ;term: term INCOP ={ $$ = buildtree( $2, $1, bcon(1) ); } | MUL term ={ ubop: $$ = buildtree( UNARY $1, $2, NIL ); } | AND term ={ if( ISFTN($2->type) || ISARY($2->type) ){ werror( "& before array or function: ignored" ); $$ = $2; } else goto ubop; } | MINUS term ={ goto ubop; } | UNOP term ={ $$ = buildtree( $1, $2, NIL ); } | INCOP term ={ $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS, $2, bcon(1) ); } | SIZEOF term ={ $$ = doszof( $2 ); } | LP cast_type RP term %prec INCOP ={ $$ = buildtree( CAST, $2, $4 ); $$->left->op = FREE; $$->op = FREE; $$ = $$->right; } | SIZEOF LP cast_type RP %prec SIZEOF ={ $$ = doszof( $3 ); } | term LB e RB ={ $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); } | funct_idn RP ={ $$=buildtree(UNARY CALL,$1,NIL); } | funct_idn elist RP ={ $$=buildtree(CALL,$1,$2); } | term STROP NAME ={ if( $2 == DOT ){ $1 = buildtree( UNARY AND, $1, NIL ); } idname = $3; $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) ); } | NAME ={ idname = $1; /* recognize identifiers in initializations */ if( blevel==0 && stab[idname].stype == UNDEF ) { register NODE *q; werror( "undeclared initializer name %.8s", stab[idname].sname ); q = block( FREE, NIL, NIL, INT, 0, INT ); q->rval = idname; defid( q, EXTERN ); } $$=buildtree(NAME,NIL,NIL); stab[$1].suse = -lineno; } | ICON ={ $$=bcon(0); $$->lval = lastcon; $$->rval = NONAME; if( $1 ) $$->csiz = $$->type = ctype(LONG); } | FCON ={ $$=buildtree(FCON,NIL,NIL); $$->dval = dcon; } | STRING ={ $$ = getstr(); /* get string contents */ } | LP e RP ={ $$=$2; } ;cast_type: type null_decl ={ $$ = tymerge( $1, $2 ); $$->op = NAME; $1->op = FREE; } ;null_decl: /* empty */ ={ $$ = bdty( NAME, NIL, -1 ); } | LP RP ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } | LP null_decl RP LP RP ={ $$ = bdty( UNARY CALL, $2, 0 ); } | MUL null_decl ={ goto umul; } | null_decl LB RB ={ goto uary; } | null_decl LB con_e RB ={ goto bary; } | LP null_decl RP ={ $$ = $2; } ;funct_idn: NAME LP ={ if( stab[$1].stype == UNDEF ){ register NODE *q; q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); q->rval = $1; defid( q, EXTERN ); } idname = $1; $$=buildtree(NAME,NIL,NIL); stab[idname].suse = -lineno; } | term LP ;%%NODE *mkty( t, d, s ) unsigned t; { return( block( TYPE, NIL, NIL, t, d, s ) ); }NODE *bdty( op, p, v ) NODE *p; { register NODE *q; q = block( op, p, NIL, INT, 0, INT ); switch( op ){ case UNARY MUL: case UNARY CALL: break; case LB: q->right = bcon(v); break; case NAME: q->rval = v; break; default: cerror( "bad bdty" ); } return( q ); }dstash( n ){ /* put n into the dimension table */ if( curdim >= DIMTABSZ-1 ){ cerror( "dimension table overflow"); } dimtab[ curdim++ ] = n; }savebc() { if( psavbc > & asavbc[BCSZ-4 ] ){ cerror( "whiles, fors, etc. too deeply nested"); } *psavbc++ = brklab; *psavbc++ = contlab; *psavbc++ = flostat; *psavbc++ = swx; flostat = 0; }resetbc(mask){ swx = *--psavbc; flostat = *--psavbc | (flostat&mask); contlab = *--psavbc; brklab = *--psavbc; }addcase(p) NODE *p; { /* add case to switch */ p = optim( p ); /* change enum to ints */ if( p->op != ICON ){ uerror( "non-constant case expression"); return; } if( swp == swtab ){ uerror( "case not in switch"); return; } if( swp >= &swtab[SWITSZ] ){ cerror( "switch table overflow"); } swp->sval = p->lval; deflab( swp->slab = getlab() ); ++swp; tfree(p); }adddef(){ /* add default case to switch */ if( swtab[swx].slab >= 0 ){ uerror( "duplicate default in switch"); return; } if( swp == swtab ){ uerror( "default not inside switch"); return; } deflab( swtab[swx].slab = getlab() ); }swstart(){ /* begin a switch block */ if( swp >= &swtab[SWITSZ] ){ cerror( "switch table overflow"); } swx = swp - swtab; swp->slab = -1; ++swp; }swend(){ /* end a switch block */ register struct sw *swbeg, *p, *q, *r, *r1; CONSZ temp; int tempi; swbeg = &swtab[swx+1]; /* sort */ r1 = swbeg; r = swp-1; while( swbeg < r ){ /* bubble largest to end */ for( q=swbeg; q<r; ++q ){ if( q->sval > (q+1)->sval ){ /* swap */ r1 = q+1; temp = q->sval; q->sval = r1->sval; r1->sval = temp; tempi = q->slab; q->slab = r1->slab; r1->slab = tempi; } } r = r1; r1 = swbeg; } /* it is now sorted */ for( p = swbeg+1; p<swp; ++p ){ if( p->sval == (p-1)->sval ){ uerror( "duplicate case in switch, %d", tempi=p->sval ); return; } } genswitch( swbeg-1, swp-swbeg ); swp = swbeg-1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -