📄 cgram.y
字号:
| ifprefix statement ={ deflab($1); reached = 1; } | ifelprefix statement ={ if( $1 != NOLAB ){ deflab( $1 ); reached = 1; } } | whprefix statement ={ branch( contlab ); deflab( brklab ); if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1; else reached = 0; resetbc(0); } | doprefix statement WHILE LP e RP SM ={ deflab( contlab ); if( flostat & FCONT ) reached = 1; ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) ); deflab( brklab ); reached = 1; resetbc(0); } | forprefix .e RP statement ={ deflab( contlab ); if( flostat&FCONT ) reached = 1; if( $2 ) ecomp( $2 ); branch( $1 ); deflab( brklab ); if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; else reached = 0; resetbc(0); } | switchpart statement ={ if( reached ) branch( brklab ); deflab( $1 ); 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 ); if(temp->in.type == TVOID) uerror("void function %s cannot return value", stab[idname].sname); temp->in.type = DECREF( temp->in.type ); temp = buildtree( RETURN, temp, $2 ); /* now, we have the type of the RHS correct */ temp->in.left->in.op = FREE; temp->in.op = FREE; ecomp( buildtree( FORCE, temp->in.right, NIL ) ); retstat |= RETVAL; branch( retlab ); reached = 0; } | GOTO NAME SM ={ register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); q->tn.rval = idname = $2; defid( q, ULABEL ); stab[idname].suse = -lineno; branch( stab[idname].offset ); goto rch; } | SM | error SM | error RC | label statement ;asmpartnow: ASM ={ procasm(); /* Read in the asm info */ outasm(asmptr); /* Put it out now */ } /* RAP001 */ ;asmpart: ASM ={ $$ = $1; procasm(); /* Read in the asm info */ /* (put out in match.c) */ } /* RAP001 */ ;label: NAME COLON ={ register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); q->tn.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->in.op == ICON && $3->tn.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 ={ /* resolve qar 2001: */ /* Detect cases of shifts larger than the object; eg: * y = x << 2 + 40; * * yypvt[-2].nodep (aka 'l' in buldtree) would have l.in.op = 2 (NAME x) * and l.in.type = 5 (long if x is a long) or set to the proper value * similary yypvt[-3].nodep (aka 'r'), would have * r.tn.type = 4 (ICON constant) * and r.tn.lval = 42 (the value). */ NODE *l, * r; l = yypvt[-2].nodep; r = yypvt[-0].nodep; if (r->tn.op == ICON) { if (r->tn.lval > dimtab[ l->in.type ]) { werror("Shift of %d is > object size of %d", r->tn.lval, dimtab[ l->in.type]); } } 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->in.type) || ISARY($2->in.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 ); $$->in.left->in.op = FREE; $$->in.op = FREE; $$ = $$->in.right; } | SIZEOF LP cast_type RP %prec SIZEOF ={ $$ = doszof( $3 ); } | term LB e RB ={ $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); } | asm_idn /* RAP001 */ ={ $$=buildtree(UNARY CALL,$1,NIL); } | funct_idn RP ={ $$=buildtree(UNARY CALL,$1,NIL); } | funct_idn elist RP ={ $$=buildtree(CALL,$1,$2); } | term STROP NAME ={ if( $2 == DOT ){ if( notlval( $1 ) )uerror("structure reference must be addressable"); $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;#ifndef FLEXNAMES werror( "undeclared initializer name %.8s", stab[idname].sname );#else werror( "undeclared initializer name %s", stab[idname].sname );#endif q = block( FREE, NIL, NIL, INT, 0, INT ); q->tn.rval = idname; defid( q, EXTERN ); } $$=buildtree(NAME,NIL,NIL); stab[$1].suse = -lineno; } | ICON ={ $$=bcon(0); $$->tn.lval = lastcon; $$->tn.rval = NONAME; if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG); } | FCON ={ $$=buildtree(FCON,NIL,NIL); $$->fpn.fval = fcon; } /* vdp004 -maintain a distinction between floating * constants and double constants */ | DCON ={ $$= buildtree(DCON,NIL,NIL); $$->dpn.dval = dcon; } | STRING ={ $$ = getstr(); /* get string contents */ } | LP e RP ={ $$=$2; } ;cast_type: typehead null_decl ={ $$ = tymerge( $1, $2 ); $$->in.op = NAME; $1->in.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->tn.rval = $1; defid( q, EXTERN ); } idname = $1; $$=buildtree(NAME,NIL,NIL); stab[idname].suse = -lineno; } | term LP ;asm_idn: asmpart /* RAP001 Put asm in the symbol table as a function that doesn't return a value (if not already there). Then build a NAME node with it and pass back a pointer to it. Store asmptr (set up by procasm in scan.c) in the NAME node. This is a pointer to a block containing the characters in the asm. The code will be put out later in match.c */ ={ if( stab[$1].stype == UNDEF ){ register NODE *q; q = block( FREE, NIL, NIL, FTN|UNDEF, 0, INT ); q->tn.rval = $1; defid( q, EXTERN ); } idname = $1; $$=buildtree(NAME,NIL,NIL);#ifdef ONEPASS $$->in.asminfo = asmptr;#endif stab[idname].suse = -lineno; }%%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: if (v == BCONST_PTR || v == BVOLATILE_PTR) { /* vjh005 */ q->in.typattr = v; } else { q->in.typattr = 0; } break; case UNARY CALL: break; case LB: q->in.right = bcon(v); break; case NAME: q->tn.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->in.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->tn.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 + -