|
|
1.1 ! root 1: %term NAME 2 ! 2: %term STRING 3 ! 3: %term ICON 4 ! 4: %term FCON 5 ! 5: %term PLUS 6 ! 6: %term MINUS 8 ! 7: %term MUL 11 ! 8: %term AND 14 ! 9: %term OR 17 ! 10: %term ER 19 ! 11: %term QUEST 21 ! 12: %term COLON 22 ! 13: %term ANDAND 23 ! 14: %term OROR 24 ! 15: ! 16: /* special interfaces for yacc alone */ ! 17: /* These serve as abbreviations of 2 or more ops: ! 18: ASOP =, = ops ! 19: RELOP LE,LT,GE,GT ! 20: EQUOP EQ,NE ! 21: DIVOP DIV,MOD ! 22: SHIFTOP LS,RS ! 23: ICOP ICR,DECR ! 24: UNOP NOT,COMPL ! 25: STROP DOT,STREF ! 26: ! 27: */ ! 28: %term ASOP 25 ! 29: %term RELOP 26 ! 30: %term EQUOP 27 ! 31: %term DIVOP 28 ! 32: %term SHIFTOP 29 ! 33: %term INCOP 30 ! 34: %term UNOP 31 ! 35: %term STROP 32 ! 36: ! 37: /* reserved words, etc */ ! 38: %term TYPE 33 ! 39: %term CLASS 34 ! 40: %term STRUCT 35 ! 41: %term RETURN 36 ! 42: %term GOTO 37 ! 43: %term IF 38 ! 44: %term ELSE 39 ! 45: %term SWITCH 40 ! 46: %term BREAK 41 ! 47: %term CONTINUE 42 ! 48: %term WHILE 43 ! 49: %term DO 44 ! 50: %term FOR 45 ! 51: %term DEFAULT 46 ! 52: %term CASE 47 ! 53: %term SIZEOF 48 ! 54: %term ENUM 49 ! 55: ! 56: ! 57: /* little symbols, etc. */ ! 58: /* namely, ! 59: ! 60: LP ( ! 61: RP ) ! 62: ! 63: LC { ! 64: RC } ! 65: ! 66: LB [ ! 67: RB ] ! 68: ! 69: CM , ! 70: SM ; ! 71: ! 72: */ ! 73: ! 74: %term LP 50 ! 75: %term RP 51 ! 76: %term LC 52 ! 77: %term RC 53 ! 78: %term LB 54 ! 79: %term RB 55 ! 80: %term CM 56 ! 81: %term SM 57 ! 82: %term ASSIGN 58 ! 83: ! 84: /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts ! 85: /* these involved: ! 86: if/else ! 87: recognizing functions in various contexts, including declarations ! 88: error recovery ! 89: */ ! 90: ! 91: %left CM ! 92: %right ASOP ASSIGN ! 93: %right QUEST COLON ! 94: %left OROR ! 95: %left ANDAND ! 96: %left OR ! 97: %left ER ! 98: %left AND ! 99: %left EQUOP ! 100: %left RELOP ! 101: %left SHIFTOP ! 102: %left PLUS MINUS ! 103: %left MUL DIVOP ! 104: %right UNOP ! 105: %right INCOP SIZEOF ! 106: %left LB LP STROP ! 107: %{ ! 108: # include "mfile1" ! 109: %} ! 110: ! 111: /* define types */ ! 112: %start ext_def_list ! 113: ! 114: %type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart ! 115: enum_head str_head name_lp ! 116: %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl ! 117: cast_type null_decl funct_idn declarator fdeclarator nfdeclarator ! 118: elist ! 119: ! 120: %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ER ANDAND OROR ! 121: ASSIGN STROP INCOP UNOP ICON ! 122: %token <nodep> TYPE ! 123: ! 124: %% ! 125: ! 126: %{ ! 127: static int fake = 0; ! 128: static char fakename[NCHNAM+1]; ! 129: %} ! 130: ! 131: ext_def_list: ext_def_list external_def ! 132: | ! 133: =ftnend(); ! 134: ; ! 135: external_def: data_def ! 136: ={ curclass = SNULL; blevel = 0; } ! 137: | error ! 138: ={ curclass = SNULL; blevel = 0; } ! 139: ; ! 140: data_def: ! 141: oattributes SM ! 142: ={ $1->op = FREE; } ! 143: | oattributes init_dcl_list SM ! 144: ={ $1->op = FREE; } ! 145: | oattributes fdeclarator { ! 146: defid( tymerge($1,$2), curclass==STATIC?STATIC:EXTDEF ); ! 147: #ifndef LINT ! 148: pfstab(stab[$2->rval].sname); ! 149: #endif ! 150: } function_body ! 151: ={ ! 152: if( blevel ) cerror( "function level error" ); ! 153: if( reached ) retstat |= NRETVAL; ! 154: $1->op = FREE; ! 155: ftnend(); ! 156: } ! 157: ; ! 158: ! 159: function_body: arg_dcl_list compoundstmt ! 160: ; ! 161: arg_dcl_list: arg_dcl_list declaration ! 162: | ={ blevel = 1; } ! 163: ; ! 164: ! 165: stmt_list: stmt_list statement ! 166: | /* empty */ ! 167: ={ bccode(); ! 168: locctr(PROG); ! 169: } ! 170: ; ! 171: ! 172: r_dcl_stat_list : dcl_stat_list attributes SM ! 173: ={ $2->op = FREE; ! 174: #ifndef LINT ! 175: plcstab(blevel); ! 176: #endif ! 177: } ! 178: | dcl_stat_list attributes init_dcl_list SM ! 179: ={ $2->op = FREE; ! 180: #ifndef LINT ! 181: plcstab(blevel); ! 182: #endif ! 183: } ! 184: ; ! 185: ! 186: dcl_stat_list : dcl_stat_list attributes SM ! 187: ={ $2->op = FREE; } ! 188: | dcl_stat_list attributes init_dcl_list SM ! 189: ={ $2->op = FREE; } ! 190: | /* empty */ ! 191: ; ! 192: declaration: attributes declarator_list SM ! 193: ={ curclass = SNULL; $1->op = FREE; } ! 194: | attributes SM ! 195: ={ curclass = SNULL; $1->op = FREE; } ! 196: | error SM ! 197: ={ curclass = SNULL; } ! 198: ; ! 199: oattributes: attributes ! 200: | /* VOID */ ! 201: ={ $$ = mkty(INT,0,INT); curclass = SNULL; } ! 202: ; ! 203: attributes: class type ! 204: ={ $$ = $2; } ! 205: | type class ! 206: | class ! 207: ={ $$ = mkty(INT,0,INT); } ! 208: | type ! 209: ={ curclass = SNULL ; } ! 210: ; ! 211: ! 212: ! 213: class: CLASS ! 214: ={ curclass = $1; } ! 215: ; ! 216: ! 217: type: TYPE ! 218: | TYPE TYPE ! 219: ={ $1->type = types( $1->type, $2->type, UNDEF ); ! 220: $2->op = FREE; ! 221: } ! 222: | TYPE TYPE TYPE ! 223: ={ $1->type = types( $1->type, $2->type, $3->type ); ! 224: $2->op = $3->op = FREE; ! 225: } ! 226: | struct_dcl ! 227: | enum_dcl ! 228: ; ! 229: ! 230: enum_dcl: enum_head LC moe_list optcomma RC ! 231: ={ $$ = dclstruct($1); } ! 232: | ENUM NAME ! 233: ={ $$ = rstruct($2,0); stwart = instruct; } ! 234: ; ! 235: ! 236: enum_head: ENUM ! 237: ={ $$ = bstruct(-1,0); } ! 238: | ENUM NAME ! 239: ={ $$ = bstruct($2,0); } ! 240: ; ! 241: ! 242: moe_list: moe ! 243: | moe_list CM moe ! 244: ; ! 245: ! 246: moe: NAME ! 247: ={ moedef( $1 ); } ! 248: | NAME ASSIGN con_e ! 249: ={ strucoff = $3; moedef( $1 ); } ! 250: ; ! 251: ! 252: struct_dcl: str_head LC type_dcl_list optsemi RC ! 253: ={ $$ = dclstruct($1); } ! 254: | STRUCT NAME ! 255: ={ $$ = rstruct($2,$1); } ! 256: ; ! 257: ! 258: str_head: STRUCT ! 259: ={ $$ = bstruct(-1,$1); stwart=0; } ! 260: | STRUCT NAME ! 261: ={ $$ = bstruct($2,$1); stwart=0; } ! 262: ; ! 263: ! 264: type_dcl_list: type_declaration ! 265: | type_dcl_list SM type_declaration ! 266: ; ! 267: ! 268: type_declaration: type declarator_list ! 269: ={ curclass = SNULL; stwart=0; $1->op = FREE; } ! 270: | type ! 271: ={ if( curclass != MOU ){ ! 272: curclass = SNULL; ! 273: } ! 274: else { ! 275: sprintf( fakename, "$%dFAKE", fake++ ); ! 276: defid( tymerge($1, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass ); ! 277: } ! 278: stwart = 0; ! 279: $1->op = FREE; ! 280: } ! 281: ; ! 282: ! 283: ! 284: declarator_list: declarator ! 285: ={ defid( tymerge($<nodep>0,$1), curclass); stwart = instruct; } ! 286: | declarator_list CM {$<nodep>$=$<nodep>0;} declarator ! 287: ={ defid( tymerge($<nodep>0,$4), curclass); stwart = instruct; } ! 288: ; ! 289: declarator: fdeclarator ! 290: | nfdeclarator ! 291: | nfdeclarator COLON con_e ! 292: %prec CM ! 293: ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); ! 294: if( $3<0 || $3 >= FIELD ){ ! 295: uerror( "illegal field size" ); ! 296: $3 = 1; ! 297: } ! 298: defid( tymerge($<nodep>0,$1), FIELD|$3 ); ! 299: $$ = NIL; ! 300: } ! 301: | COLON con_e ! 302: %prec CM ! 303: ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); ! 304: falloc( stab, $2, -1, $<nodep>0 ); /* alignment or hole */ ! 305: $$ = NIL; ! 306: } ! 307: | error ! 308: ={ $$ = NIL; } ! 309: ; ! 310: ! 311: /* int (a)(); is not a function --- sorry! */ ! 312: nfdeclarator: MUL nfdeclarator ! 313: ={ umul: ! 314: $$ = bdty( UNARY MUL, $2, 0 ); } ! 315: | nfdeclarator LP RP ! 316: ={ uftn: ! 317: $$ = bdty( UNARY CALL, $1, 0 ); } ! 318: | nfdeclarator LB RB ! 319: ={ uary: ! 320: $$ = bdty( LB, $1, 0 ); } ! 321: | nfdeclarator LB con_e RB ! 322: ={ bary: ! 323: if( (int)$3 <= 0 ) werror( "zero or negative subscript" ); ! 324: $$ = bdty( LB, $1, $3 ); } ! 325: | NAME ! 326: ={ $$ = bdty( NAME, NIL, $1 ); } ! 327: | LP nfdeclarator RP ! 328: ={ $$=$2; } ! 329: ; ! 330: fdeclarator: MUL fdeclarator ! 331: ={ goto umul; } ! 332: | fdeclarator LP RP ! 333: ={ goto uftn; } ! 334: | fdeclarator LB RB ! 335: ={ goto uary; } ! 336: | fdeclarator LB con_e RB ! 337: ={ goto bary; } ! 338: | LP fdeclarator RP ! 339: ={ $$ = $2; } ! 340: | name_lp name_list RP ! 341: ={ ! 342: if( blevel!=0 ) uerror("function declaration in bad context"); ! 343: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); ! 344: stwart = 0; ! 345: } ! 346: | name_lp RP ! 347: ={ ! 348: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); ! 349: stwart = 0; ! 350: } ! 351: ; ! 352: ! 353: name_lp: NAME LP ! 354: ={ ! 355: /* turn off typedefs for argument names */ ! 356: stwart = SEENAME; ! 357: } ! 358: ; ! 359: ! 360: name_list: NAME ! 361: ={ ftnarg( $1 ); stwart = SEENAME; } ! 362: | name_list CM NAME ! 363: ={ ftnarg( $3 ); stwart = SEENAME; } ! 364: ; ! 365: /* always preceeded by attributes: thus the $<nodep>0's */ ! 366: init_dcl_list: init_declarator ! 367: %prec CM ! 368: | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator ! 369: ; ! 370: /* always preceeded by attributes */ ! 371: xnfdeclarator: nfdeclarator ! 372: ={ defid( $1 = tymerge($<nodep>0,$1), curclass); ! 373: beginit($1->rval); ! 374: } ! 375: | error ! 376: ; ! 377: /* always preceeded by attributes */ ! 378: init_declarator: nfdeclarator ! 379: ={ nidcl( tymerge($<nodep>0,$1) ); } ! 380: | fdeclarator ! 381: ={ defid( tymerge($<nodep>0,$1), uclass(curclass) ); ! 382: } ! 383: | xnfdeclarator optasgn e ! 384: %prec CM ! 385: ={ doinit( $3 ); ! 386: endinit(); } ! 387: | xnfdeclarator optasgn LC init_list optcomma RC ! 388: ={ endinit(); } ! 389: ; ! 390: ! 391: init_list: initializer ! 392: %prec CM ! 393: | init_list CM initializer ! 394: ; ! 395: initializer: e ! 396: %prec CM ! 397: ={ doinit( $1 ); } ! 398: | ibrace init_list optcomma RC ! 399: ={ irbrace(); } ! 400: ; ! 401: ! 402: optcomma : /* VOID */ ! 403: | CM ! 404: ; ! 405: ! 406: optsemi : /* VOID */ ! 407: | SM ! 408: ; ! 409: ! 410: optasgn : /* VOID */ ! 411: ={ werror( "old-fashioned initialization: use =" ); } ! 412: | ASSIGN ! 413: ; ! 414: ! 415: ibrace : LC ! 416: ={ ilbrace(); } ! 417: ; ! 418: ! 419: /* STATEMENTS */ ! 420: ! 421: compoundstmt: dcmpstmt ! 422: | cmpstmt ! 423: ; ! 424: ! 425: dcmpstmt: begin r_dcl_stat_list stmt_list RC ! 426: ={ ! 427: #ifndef LINT ! 428: prcstab(blevel); ! 429: #endif ! 430: --blevel; ! 431: if( blevel == 1 ) blevel = 0; ! 432: clearst( blevel ); ! 433: checkst( blevel ); ! 434: autooff = *--psavbc; ! 435: regvar = *--psavbc; ! 436: } ! 437: ; ! 438: ! 439: cmpstmt: begin stmt_list RC ! 440: ={ --blevel; ! 441: if( blevel == 1 ) blevel = 0; ! 442: clearst( blevel ); ! 443: checkst( blevel ); ! 444: autooff = *--psavbc; ! 445: regvar = *--psavbc; ! 446: } ! 447: ; ! 448: ! 449: begin: LC ! 450: ={ if( blevel == 1 ) dclargs(); ! 451: ++blevel; ! 452: if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" ); ! 453: *psavbc++ = regvar; ! 454: *psavbc++ = autooff; ! 455: } ! 456: ; ! 457: ! 458: statement: e SM ! 459: ={ ecomp( $1 ); } ! 460: | compoundstmt ! 461: | ifprefix statement ! 462: ={ deflab($1); ! 463: reached = 1; ! 464: } ! 465: | ifelprefix statement ! 466: ={ if( $1 != NOLAB ){ ! 467: deflab( $1 ); ! 468: reached = 1; ! 469: } ! 470: } ! 471: | whprefix statement ! 472: ={ branch( contlab ); ! 473: deflab( brklab ); ! 474: if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1; ! 475: else reached = 0; ! 476: resetbc(0); ! 477: } ! 478: | doprefix statement WHILE LP e RP SM ! 479: ={ deflab( contlab ); ! 480: if( flostat & FCONT ) reached = 1; ! 481: ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) ); ! 482: deflab( brklab ); ! 483: reached = 1; ! 484: resetbc(0); ! 485: } ! 486: | forprefix .e RP statement ! 487: ={ deflab( contlab ); ! 488: if( flostat&FCONT ) reached = 1; ! 489: if( $2 ) ecomp( $2 ); ! 490: branch( $1 ); ! 491: deflab( brklab ); ! 492: if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; ! 493: else reached = 0; ! 494: resetbc(0); ! 495: } ! 496: | switchpart statement ! 497: ={ if( reached ) branch( brklab ); ! 498: deflab( $1 ); ! 499: swend(); ! 500: deflab(brklab); ! 501: if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; ! 502: resetbc(FCONT); ! 503: } ! 504: | BREAK SM ! 505: ={ if( brklab == NOLAB ) uerror( "illegal break"); ! 506: else if(reached) branch( brklab ); ! 507: flostat |= FBRK; ! 508: if( brkflag ) goto rch; ! 509: reached = 0; ! 510: } ! 511: | CONTINUE SM ! 512: ={ if( contlab == NOLAB ) uerror( "illegal continue"); ! 513: else branch( contlab ); ! 514: flostat |= FCONT; ! 515: goto rch; ! 516: } ! 517: | RETURN SM ! 518: ={ retstat |= NRETVAL; ! 519: branch( retlab ); ! 520: rch: ! 521: if( !reached ) werror( "statement not reached"); ! 522: reached = 0; ! 523: } ! 524: | RETURN e SM ! 525: ={ register NODE *temp; ! 526: idname = curftn; ! 527: temp = buildtree( NAME, NIL, NIL ); ! 528: temp->type = DECREF( temp->type ); ! 529: temp = buildtree( RETURN, temp, $2 ); ! 530: /* now, we have the type of the RHS correct */ ! 531: temp->left->op = FREE; ! 532: temp->op = FREE; ! 533: ecomp( buildtree( FORCE, temp->right, NIL ) ); ! 534: retstat |= RETVAL; ! 535: branch( retlab ); ! 536: reached = 0; ! 537: } ! 538: | GOTO NAME SM ! 539: ={ register NODE *q; ! 540: q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); ! 541: q->rval = idname = $2; ! 542: defid( q, ULABEL ); ! 543: stab[idname].suse = -lineno; ! 544: branch( stab[idname].offset ); ! 545: goto rch; ! 546: } ! 547: | SM ! 548: | error SM ! 549: | error RC ! 550: | label statement ! 551: ; ! 552: label: NAME COLON ! 553: ={ register NODE *q; ! 554: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); ! 555: q->rval = $1; ! 556: defid( q, LABEL ); ! 557: reached = 1; ! 558: } ! 559: | CASE e COLON ! 560: ={ addcase($2); ! 561: reached = 1; ! 562: } ! 563: | DEFAULT COLON ! 564: ={ reached = 1; ! 565: adddef(); ! 566: flostat |= FDEF; ! 567: } ! 568: ; ! 569: doprefix: DO ! 570: ={ savebc(); ! 571: if( !reached ) werror( "loop not entered at top"); ! 572: brklab = getlab(); ! 573: contlab = getlab(); ! 574: deflab( $$ = getlab() ); ! 575: reached = 1; ! 576: } ! 577: ; ! 578: ifprefix: IF LP e RP ! 579: ={ ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ; ! 580: reached = 1; ! 581: } ! 582: ; ! 583: ifelprefix: ifprefix statement ELSE ! 584: ={ if( reached ) branch( $$ = getlab() ); ! 585: else $$ = NOLAB; ! 586: deflab( $1 ); ! 587: reached = 1; ! 588: } ! 589: ; ! 590: ! 591: whprefix: WHILE LP e RP ! 592: ={ savebc(); ! 593: if( !reached ) werror( "loop not entered at top"); ! 594: if( $3->op == ICON && $3->lval != 0 ) flostat = FLOOP; ! 595: deflab( contlab = getlab() ); ! 596: reached = 1; ! 597: brklab = getlab(); ! 598: if( flostat == FLOOP ) tfree( $3 ); ! 599: else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) ); ! 600: } ! 601: ; ! 602: forprefix: FOR LP .e SM .e SM ! 603: ={ if( $3 ) ecomp( $3 ); ! 604: else if( !reached ) werror( "loop not entered at top"); ! 605: savebc(); ! 606: contlab = getlab(); ! 607: brklab = getlab(); ! 608: deflab( $$ = getlab() ); ! 609: reached = 1; ! 610: if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) ); ! 611: else flostat |= FLOOP; ! 612: } ! 613: ; ! 614: switchpart: SWITCH LP e RP ! 615: ={ savebc(); ! 616: brklab = getlab(); ! 617: ecomp( buildtree( FORCE, $3, NIL ) ); ! 618: branch( $$ = getlab() ); ! 619: swstart(); ! 620: reached = 0; ! 621: } ! 622: ; ! 623: /* EXPRESSIONS */ ! 624: con_e: { $<intval>$=instruct; stwart=instruct=0; } e ! 625: %prec CM ! 626: ={ $$ = icons( $2 ); instruct=$<intval>1; } ! 627: ; ! 628: .e: e ! 629: | ! 630: ={ $$=0; } ! 631: ; ! 632: elist: e ! 633: %prec CM ! 634: | elist CM e ! 635: ={ goto bop; } ! 636: ; ! 637: ! 638: e: e RELOP e ! 639: ={ ! 640: preconf: ! 641: if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){ ! 642: precplaint: ! 643: if( hflag ) werror( "precedence confusion possible: parenthesize!" ); ! 644: } ! 645: bop: ! 646: $$ = buildtree( $2, $1, $3 ); ! 647: } ! 648: | e CM e ! 649: ={ $2 = COMOP; ! 650: goto bop; ! 651: } ! 652: | e DIVOP e ! 653: ={ goto bop; } ! 654: | e PLUS e ! 655: ={ if(yychar==SHIFTOP) goto precplaint; else goto bop; } ! 656: | e MINUS e ! 657: ={ if(yychar==SHIFTOP ) goto precplaint; else goto bop; } ! 658: | e SHIFTOP e ! 659: ={ if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } ! 660: | e MUL e ! 661: ={ goto bop; } ! 662: | e EQUOP e ! 663: ={ goto preconf; } ! 664: | e AND e ! 665: ={ if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } ! 666: | e OR e ! 667: ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 668: | e ER e ! 669: ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 670: | e ANDAND e ! 671: ={ goto bop; } ! 672: | e OROR e ! 673: ={ goto bop; } ! 674: | e MUL ASSIGN e ! 675: ={ abop: ! 676: $$ = buildtree( ASG $2, $1, $4 ); ! 677: } ! 678: | e DIVOP ASSIGN e ! 679: ={ goto abop; } ! 680: | e PLUS ASSIGN e ! 681: ={ goto abop; } ! 682: | e MINUS ASSIGN e ! 683: ={ goto abop; } ! 684: | e SHIFTOP ASSIGN e ! 685: ={ goto abop; } ! 686: | e AND ASSIGN e ! 687: ={ goto abop; } ! 688: | e OR ASSIGN e ! 689: ={ goto abop; } ! 690: | e ER ASSIGN e ! 691: ={ goto abop; } ! 692: | e QUEST e COLON e ! 693: ={ $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) ); ! 694: } ! 695: | e ASOP e ! 696: ={ werror( "old-fashioned assignment operator" ); goto bop; } ! 697: | e ASSIGN e ! 698: ={ goto bop; } ! 699: | term ! 700: ; ! 701: term: term INCOP ! 702: ={ $$ = buildtree( $2, $1, bcon(1) ); } ! 703: | MUL term ! 704: ={ ubop: ! 705: $$ = buildtree( UNARY $1, $2, NIL ); ! 706: } ! 707: | AND term ! 708: ={ if( ISFTN($2->type) || ISARY($2->type) ){ ! 709: werror( "& before array or function: ignored" ); ! 710: $$ = $2; ! 711: } ! 712: else goto ubop; ! 713: } ! 714: | MINUS term ! 715: ={ goto ubop; } ! 716: | UNOP term ! 717: ={ ! 718: $$ = buildtree( $1, $2, NIL ); ! 719: } ! 720: | INCOP term ! 721: ={ $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS, ! 722: $2, ! 723: bcon(1) ); ! 724: } ! 725: | SIZEOF term ! 726: ={ $$ = doszof( $2 ); } ! 727: | LP cast_type RP term %prec INCOP ! 728: ={ $$ = buildtree( CAST, $2, $4 ); ! 729: $$->left->op = FREE; ! 730: $$->op = FREE; ! 731: $$ = $$->right; ! 732: } ! 733: | SIZEOF LP cast_type RP %prec SIZEOF ! 734: ={ $$ = doszof( $3 ); } ! 735: | term LB e RB ! 736: ={ $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); } ! 737: | funct_idn RP ! 738: ={ $$=buildtree(UNARY CALL,$1,NIL); } ! 739: | funct_idn elist RP ! 740: ={ $$=buildtree(CALL,$1,$2); } ! 741: | term STROP NAME ! 742: ={ if( $2 == DOT ){ ! 743: $1 = buildtree( UNARY AND, $1, NIL ); ! 744: } ! 745: idname = $3; ! 746: $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) ); ! 747: } ! 748: | NAME ! 749: ={ idname = $1; ! 750: /* recognize identifiers in initializations */ ! 751: if( blevel==0 && stab[idname].stype == UNDEF ) { ! 752: register NODE *q; ! 753: werror( "undeclared initializer name %.8s", stab[idname].sname ); ! 754: q = block( FREE, NIL, NIL, INT, 0, INT ); ! 755: q->rval = idname; ! 756: defid( q, EXTERN ); ! 757: } ! 758: $$=buildtree(NAME,NIL,NIL); ! 759: stab[$1].suse = -lineno; ! 760: } ! 761: | ICON ! 762: ={ $$=bcon(0); ! 763: $$->lval = lastcon; ! 764: $$->rval = NONAME; ! 765: if( $1 ) $$->csiz = $$->type = ctype(LONG); ! 766: } ! 767: | FCON ! 768: ={ $$=buildtree(FCON,NIL,NIL); ! 769: $$->dval = dcon; ! 770: } ! 771: | STRING ! 772: ={ $$ = getstr(); /* get string contents */ } ! 773: | LP e RP ! 774: ={ $$=$2; } ! 775: ; ! 776: ! 777: cast_type: type null_decl ! 778: ={ ! 779: $$ = tymerge( $1, $2 ); ! 780: $$->op = NAME; ! 781: $1->op = FREE; ! 782: } ! 783: ; ! 784: ! 785: null_decl: /* empty */ ! 786: ={ $$ = bdty( NAME, NIL, -1 ); } ! 787: | LP RP ! 788: ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } ! 789: | LP null_decl RP LP RP ! 790: ={ $$ = bdty( UNARY CALL, $2, 0 ); } ! 791: | MUL null_decl ! 792: ={ goto umul; } ! 793: | null_decl LB RB ! 794: ={ goto uary; } ! 795: | null_decl LB con_e RB ! 796: ={ goto bary; } ! 797: | LP null_decl RP ! 798: ={ $$ = $2; } ! 799: ; ! 800: ! 801: funct_idn: NAME LP ! 802: ={ if( stab[$1].stype == UNDEF ){ ! 803: register NODE *q; ! 804: q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); ! 805: q->rval = $1; ! 806: defid( q, EXTERN ); ! 807: } ! 808: idname = $1; ! 809: $$=buildtree(NAME,NIL,NIL); ! 810: stab[idname].suse = -lineno; ! 811: } ! 812: | term LP ! 813: ; ! 814: %% ! 815: ! 816: NODE * ! 817: mkty( t, d, s ) unsigned t; { ! 818: return( block( TYPE, NIL, NIL, t, d, s ) ); ! 819: } ! 820: ! 821: NODE * ! 822: bdty( op, p, v ) NODE *p; { ! 823: register NODE *q; ! 824: ! 825: q = block( op, p, NIL, INT, 0, INT ); ! 826: ! 827: switch( op ){ ! 828: ! 829: case UNARY MUL: ! 830: case UNARY CALL: ! 831: break; ! 832: ! 833: case LB: ! 834: q->right = bcon(v); ! 835: break; ! 836: ! 837: case NAME: ! 838: q->rval = v; ! 839: break; ! 840: ! 841: default: ! 842: cerror( "bad bdty" ); ! 843: } ! 844: ! 845: return( q ); ! 846: } ! 847: ! 848: dstash( n ){ /* put n into the dimension table */ ! 849: if( curdim >= DIMTABSZ-1 ){ ! 850: cerror( "dimension table overflow"); ! 851: } ! 852: dimtab[ curdim++ ] = n; ! 853: } ! 854: ! 855: savebc() { ! 856: if( psavbc > & asavbc[BCSZ-4 ] ){ ! 857: cerror( "whiles, fors, etc. too deeply nested"); ! 858: } ! 859: *psavbc++ = brklab; ! 860: *psavbc++ = contlab; ! 861: *psavbc++ = flostat; ! 862: *psavbc++ = swx; ! 863: flostat = 0; ! 864: } ! 865: ! 866: resetbc(mask){ ! 867: ! 868: swx = *--psavbc; ! 869: flostat = *--psavbc | (flostat&mask); ! 870: contlab = *--psavbc; ! 871: brklab = *--psavbc; ! 872: ! 873: } ! 874: ! 875: addcase(p) NODE *p; { /* add case to switch */ ! 876: ! 877: p = optim( p ); /* change enum to ints */ ! 878: if( p->op != ICON ){ ! 879: uerror( "non-constant case expression"); ! 880: return; ! 881: } ! 882: if( swp == swtab ){ ! 883: uerror( "case not in switch"); ! 884: return; ! 885: } ! 886: if( swp >= &swtab[SWITSZ] ){ ! 887: cerror( "switch table overflow"); ! 888: } ! 889: swp->sval = p->lval; ! 890: deflab( swp->slab = getlab() ); ! 891: ++swp; ! 892: tfree(p); ! 893: } ! 894: ! 895: adddef(){ /* add default case to switch */ ! 896: if( swtab[swx].slab >= 0 ){ ! 897: uerror( "duplicate default in switch"); ! 898: return; ! 899: } ! 900: if( swp == swtab ){ ! 901: uerror( "default not inside switch"); ! 902: return; ! 903: } ! 904: deflab( swtab[swx].slab = getlab() ); ! 905: } ! 906: ! 907: swstart(){ ! 908: /* begin a switch block */ ! 909: if( swp >= &swtab[SWITSZ] ){ ! 910: cerror( "switch table overflow"); ! 911: } ! 912: swx = swp - swtab; ! 913: swp->slab = -1; ! 914: ++swp; ! 915: } ! 916: ! 917: swend(){ /* end a switch block */ ! 918: ! 919: register struct sw *swbeg, *p, *q, *r, *r1; ! 920: CONSZ temp; ! 921: int tempi; ! 922: ! 923: swbeg = &swtab[swx+1]; ! 924: ! 925: /* sort */ ! 926: ! 927: r1 = swbeg; ! 928: r = swp-1; ! 929: ! 930: while( swbeg < r ){ ! 931: /* bubble largest to end */ ! 932: for( q=swbeg; q<r; ++q ){ ! 933: if( q->sval > (q+1)->sval ){ ! 934: /* swap */ ! 935: r1 = q+1; ! 936: temp = q->sval; ! 937: q->sval = r1->sval; ! 938: r1->sval = temp; ! 939: tempi = q->slab; ! 940: q->slab = r1->slab; ! 941: r1->slab = tempi; ! 942: } ! 943: } ! 944: r = r1; ! 945: r1 = swbeg; ! 946: } ! 947: ! 948: /* it is now sorted */ ! 949: ! 950: for( p = swbeg+1; p<swp; ++p ){ ! 951: if( p->sval == (p-1)->sval ){ ! 952: uerror( "duplicate case in switch, %d", tempi=p->sval ); ! 953: return; ! 954: } ! 955: } ! 956: ! 957: genswitch( swbeg-1, swp-swbeg ); ! 958: swp = swbeg-1; ! 959: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.