|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/lalex.c 1.6.3.21" */ ! 2: /************************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: lalex.c: ! 11: ! 12: lookahead ! 13: ! 14: *****************************************************************************/ ! 15: #include <stdio.h> ! 16: #include "cfront.h" ! 17: #include "yystype.h" ! 18: #include "tqueue.h" ! 19: ! 20: // external functions ! 21: extern void la_backup( TOK, YYSTYPE ); ! 22: extern int la_decl(); ! 23: extern int la_cast(); ! 24: extern TOK lalex(); ! 25: extern TOK la_look(); ! 26: ! 27: static int laexpr( TOK ); ! 28: static int latype( TOK ); ! 29: ! 30: /* make this a toknode! */ ! 31: static int lasttk = 0; // one token history ! 32: static YYSTYPE lastval; // yylval lasttk value ! 33: ! 34: int must_be_expr = 0; // handle redundant parentheses ! 35: int must_be_id = 0; // !0, TNAME => ID, i.e., int X ! 36: ! 37: extern int in_mem_fct; ! 38: extern int in_class_decl; ! 39: extern int in_arg_list; ! 40: extern int DECL_TYPE; ! 41: ! 42: toknode* latok; // current lookahead token ! 43: toknode* front = 0; ! 44: toknode* rear = 0; ! 45: ! 46: static toknode* free_toks = 0; ! 47: const TQCHUNK = 16; ! 48: ! 49: toknode::toknode(TOK t, YYSTYPE r) ! 50: { ! 51: if (free_toks == 0) { ! 52: // extern char* calloc(unsigned,unsigned); ! 53: register toknode* q; ! 54: int sz = sizeof( toknode ); ! 55: free_toks = q = (toknode*)calloc( TQCHUNK, sz ); ! 56: for (; q != &free_toks[TQCHUNK-1]; q->next = q+1, ++q); ! 57: } ! 58: this = free_toks; free_toks = free_toks->next; ! 59: tok = t; ! 60: retval = r; ! 61: next = last = 0; ! 62: } ! 63: ! 64: toknode::~toknode() ! 65: { ! 66: next = free_toks; ! 67: free_toks = this; ! 68: this = 0; ! 69: } ! 70: ! 71: void addtok(TOK t, YYSTYPE r) ! 72: { ! 73: toknode* T = new toknode(t,r); ! 74: if (front == 0) ! 75: front = rear = T; ! 76: else { ! 77: rear->next = T; ! 78: T->last = rear; ! 79: rear = T; ! 80: } ! 81: } ! 82: ! 83: extern TOK ! 84: deltok( int noset = 0 ) ! 85: { ! 86: register toknode* T = front; ! 87: register TOK tk = T->tok; ! 88: if ( !noset ) yylval = T->retval; ! 89: if (front = front->next) ! 90: front->last = 0; ! 91: else ! 92: latok = rear = 0; ! 93: delete T; ! 94: return tk; ! 95: } ! 96: ! 97: static void ! 98: add_tokens() ! 99: /* ! 100: extend lookahead token queue when depleted ! 101: */ ! 102: { ! 103: TOK tk = tlex(); ! 104: if ( tk != ID ) ! 105: return; ! 106: ! 107: while (tk == ID || tk == MEM || tk == DOT ) ! 108: tk = tlex(); ! 109: } ! 110: ! 111: extern TOK ! 112: la_look() ! 113: /* ! 114: peek at head of token queue ! 115: */ ! 116: { ! 117: if ( front == 0 ) ! 118: add_tokens(); ! 119: ! 120: latok = front; ! 121: return latok->tok; ! 122: } ! 123: ! 124: static int ! 125: latype( TOK t ) ! 126: { ! 127: switch ( t ) { ! 128: default: // includes friend, typedef, storage classes, etc. ! 129: return 0; ! 130: case CHAR: case SHORT: case INT: case LONG: ! 131: case FLOAT: case DOUBLE: ! 132: case UNSIGNED: ! 133: return 1; ! 134: } ! 135: } ! 136: ! 137: static int ! 138: laexpr( TOK t ) ! 139: { ! 140: switch ( t ) { ! 141: default: ! 142: return 0; ! 143: case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR: ! 144: case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS: ! 145: case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP: ! 146: case SHIFTOP: case ICOP: ! 147: return 1; ! 148: } ! 149: } ! 150: ! 151: ! 152: static TOK ! 153: lookahead() ! 154: /* ! 155: advance lookahead pointer, lexing at end of Q ! 156: handle occurrences of TNAME and TSCOPE ! 157: (should be kept up to date with lalex()) ! 158: */ ! 159: { ! 160: TOK tk; ! 161: TOK prev_tk = 0; ! 162: YYSTYPE lastval; ! 163: ! 164: if ( latok == rear ) { ! 165: add_tokens(); ! 166: if ( latok ) ! 167: latok = latok->next; ! 168: else ! 169: latok = front; ! 170: } ! 171: else ! 172: latok = latok->next; ! 173: ! 174: if ( latok->last ) { ! 175: prev_tk = latok->last->tok; ! 176: lastval = latok->last->retval; ! 177: } ! 178: ! 179: nexttok: ! 180: tk = latok->tok; ! 181: if ( tk == ID || tk == TNAME ) ! 182: { ! 183: if (latok->next == 0) add_tokens(); ! 184: TOK tk2 = latok->next->tok; ! 185: if ( tk == TNAME ) { ! 186: if ( tk2 == MEM || tk2 == DOT ) { ! 187: tk = TSCOPE; ! 188: latok = latok->next; ! 189: if (latok->next == 0) add_tokens(); ! 190: tk2 = latok->next->tok; ! 191: if ( tk2 == MUL ) ! 192: { ! 193: tk = MEMPTR; ! 194: latok = latok->next; ! 195: } ! 196: } ! 197: else if (( prev_tk == MUL && tk2 != RP ) ! 198: || prev_tk == AND ) ! 199: { ! 200: tk = ID; ! 201: latok->retval.pn->hide(); ! 202: latok->tok = ID; ! 203: latok->retval.s = latok->retval.pn->string; ! 204: } ! 205: } ! 206: else if ( tk2 == MEM ) { ! 207: // ID :: ! 208: latok = latok->next->next; ! 209: goto nexttok; ! 210: } ! 211: ! 212: if ( tk == ID && ! 213: ( tk2 == ID || ! 214: ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) { ! 215: // ID ID ! 216: latok = latok->next; ! 217: goto nexttok; ! 218: } ! 219: } ! 220: ! 221: return tk; ! 222: } ! 223: ! 224: extern Ptype in_typedef; ! 225: extern Pname statStat; ! 226: static Pname mem_sel = 0; ! 227: ! 228: extern TOK ! 229: lalex() ! 230: /* return next token to grammar */ ! 231: { ! 232: register TOK tk; ! 233: if ( front == 0 ) ! 234: add_tokens(); // extend lookahead queue ! 235: ! 236: gettok: ! 237: tk = deltok(); ! 238: ! 239: if ( tk == ID || tk == TNAME ) ! 240: { ! 241: TOK tk2 = la_look(); ! 242: extern int bl_level; ! 243: int lex_level = bl_level - in_class_decl - (tk2 == LC ); ! 244: ! 245: if ( tk == TNAME ) ! 246: { ! 247: // error('d', "lalex %n lasttk: %k tk2: %k must_be_id: %d", yylval.pn, lasttk, tk2, must_be_id ); ! 248: if ( tk2 == LP ! 249: && (bl_level == 0 || in_class_decl ) ! 250: && ( laexpr(lasttk) == 0 ) ! 251: && must_be_expr == 0 ! 252: && DECL_TYPE == 0 ) { ! 253: if (la_decl()) { ! 254: must_be_id = 0; ! 255: DECL_TYPE = tk; ! 256: tk = DECL_MARKER; ! 257: goto ret; ! 258: } ! 259: } ! 260: ! 261: if ( lasttk == AGGR || lasttk == ENUM ) { ! 262: if ( in_typedef == 0 ) { ! 263: TOK type_tk = yylval.pn->tp->base==COBJ ! 264: ? AGGR ! 265: : (yylval.pn->tp->base==EOBJ?ENUM:TYPEDEF); ! 266: if ( lasttk != type_tk ) ! 267: error( "%nredefined: %k and %k", yylval.pn, type_tk, lasttk ); ! 268: } ! 269: ! 270: ! 271: if ( lex_level && (tk2 == LC || tk2 == COLON) ! 272: // temporary ! 273: && lasttk != ENUM ) { ! 274: Pname bn = Pbase(yylval.pn->tp)->b_name; ! 275: Pclass cl = Pclass(bn->tp); ! 276: if ( yylval.pn->lex_level != lex_level || cl->lcl ) { ! 277: extern void local_hide( Pname ); // place in cfront.h ! 278: extern Plist local_blk; // place in cfront.h ! 279: local_hide( yylval.pn ); ! 280: Pname n = new name( yylval.pn->string ); ! 281: n->lex_level = lex_level>=0?lex_level:0; ! 282: n = n->tname( lastval.t ); ! 283: modified_tn = modified_tn->l; ! 284: n->n_key = LOCAL; ! 285: local_class = new name_list( n, local_class ); ! 286: local_blk = new name_list( n, local_blk ); ! 287: yylval.pn = n; ! 288: } ! 289: // catch redefinition of local classes ! 290: else if ( lex_level == yylval.pn->lex_level && cl->defined ) ! 291: error( "localC%nredefined", yylval.pn ); ! 292: } ! 293: } // end: if (lasttk == AGGR or ENUM ) ! 294: ! 295: if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) { ! 296: if (tk2==DOT) ! 297: error('w',"``.'' used for qualification, please use ``::''"); ! 298: tk = TSCOPE; ! 299: tk2 = deltok(1); ! 300: tk2 = la_look(); ! 301: if ( tk2 == MUL ) { ! 302: tk = MEMPTR; ! 303: tk2 = deltok(1); ! 304: } ! 305: } ! 306: ! 307: // Have a TNAME. Check to be sure. ! 308: else if ( must_be_id ){ ! 309: ! 310: if ( in_class_decl ! 311: && lasttk == TYPE ! 312: && tk2 == LP ! 313: && strcmp(yylval.pn->string,ccl->string) == 0 ) ! 314: error("%nK with returnT", yylval.pn); ! 315: ! 316: else if ( lasttk == TYPE && lastval.t == OVERLOAD ! 317: && ( tk2 == SM || tk2 == LP ) ) ! 318: { ! 319: tk = ID; ! 320: yylval.pn->hide(); ! 321: yylval.pn = new name( yylval.pn->string ); ! 322: yylval.pn->n_oper = TNAME; ! 323: } ! 324: else if ( lasttk == OPERATOR ) ! 325: must_be_id = 0; ! 326: else ! 327: // watch out for X::X ! 328: if ( lasttk != TSCOPE ! 329: || lastval.pn != yylval.pn ! 330: || ( in_typedef && in_typedef->check( yylval.pn->tp,0) == 0 )) ! 331: { ! 332: tk = ID; ! 333: extern int defer_check; ! 334: extern Pname in_tag; ! 335: if ( in_typedef && (lasttk == MUL || lasttk == REF)) { ! 336: defer_check = 1; ! 337: in_tag = yylval.pn; ! 338: } ! 339: ! 340: if ( lasttk == MEM && yylval.pn->lex_level ) { ! 341: Pname nn = gtbl->look( yylval.pn->string, 0 ); ! 342: if (nn == 0 ) ! 343: error( "%k%s undeclared", lasttk, yylval.pn->string); ! 344: else ! 345: yylval.pn = nn; ! 346: } ! 347: else { ! 348: // error('d',"lalex: else: lasttk: %k", lasttk ); ! 349: if (lasttk!=DOT && lasttk!=REF && lasttk!=TSCOPE && lasttk !=GOTO) yylval.pn->hide(); ! 350: yylval.pn = new name (yylval.pn->string); ! 351: if (lasttk!=DOT && lasttk!=REF && lasttk!=TSCOPE && lasttk !=GOTO) yylval.pn->n_oper = TNAME; ! 352: } ! 353: if ( defer_check ) defer_check = 0; ! 354: } ! 355: } // must_be_id ! 356: ! 357: if ((lasttk == SM || lasttk == RC || lasttk == LC) ! 358: && tk2 == COLON ) { // label ! 359: tk = ID; ! 360: yylval.pn = new name (yylval.pn->string); ! 361: } ! 362: ! 363: if ( in_class_decl && ! 364: ccl->lex_level && ! 365: yylval.pn->lex_level != 0 && ! 366: yylval.pn->tp && ! 367: (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ)) ! 368: { ! 369: Pname n = gtbl->look( yylval.pn->string,0); ! 370: // error( 'd', "bl_level: %d in_mem_fct: %d", bl_level, in_mem_fct ); ! 371: if ( in_mem_fct ) { ! 372: if (n && n->base == TNAME ) { ! 373: error('w', "local typedef %n(%t) is not in scope of local class %s members; using global (%t)", yylval.pn, yylval.pn->tp, ccl->string, n->tp ); ! 374: yylval.pn = n; ! 375: } ! 376: else ! 377: error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string); ! 378: } ! 379: } ! 380: } ! 381: else ! 382: { // tk == ID ! 383: char *s = yylval.s; ! 384: Pname n = ktbl->look( s, HIDDEN ); ! 385: //error( 'd', "n: %n, beenhid: %n, in_arg_list: %d", n, beenHid,in_ arg_list ); ! 386: if (tk2 == MEM) { ! 387: // ID :: ! 388: if (n) { ! 389: tk = TSCOPE; ! 390: tk2 = deltok(1); ! 391: yylval.pn = n; ! 392: tk2 = la_look(); ! 393: if ( tk2 == MUL ) { ! 394: tk = MEMPTR; ! 395: tk2 = deltok(1); ! 396: } ! 397: } ! 398: else { ! 399: error( "%s:: %sis not aTN", s, s ); ! 400: tk2 = deltok(1); ! 401: goto gettok; ! 402: } ! 403: } ! 404: // Have an ID. Check last token to be sure. ! 405: else if (lasttk==ENUM || lasttk==AGGR) { ! 406: tk = TNAME; ! 407: if (n==0) { // new tag, define it ! 408: n = new name( s ); ! 409: n->lex_level = lex_level>=0?lex_level:0; ! 410: n = n->tname( lastval.t ); ! 411: modified_tn = modified_tn->l; ! 412: if (lex_level == 0 ) { ! 413: if (gtbl->look(n->string,0)) ! 414: // don't know yet if n has ctor(): defer ! 415: statStat = n; ! 416: } ! 417: else if ( lex_level > 0 ! 418: // temporary ! 419: && lasttk != ENUM ) { ! 420: n->n_key = LOCAL; ! 421: local_class = new name_list( n, local_class ); ! 422: extern Plist local_blk; // place in cfront.h ! 423: local_blk = new name_list( n, local_blk ); ! 424: } ! 425: } ! 426: else { ! 427: if (n->tp->base!=COBJ && n->tp->base!=EOBJ) { ! 428: error( 'i', "hidden%n:%t",n,n->tp ); ! 429: goto gettok; ! 430: } ! 431: ! 432: if ( tk2 == LC || tk2 == COLON ) { ! 433: // class declared and hidden but not yet defined ! 434: // may have ctor defined which invalidates hiding ! 435: statStat = n; ! 436: n->n_key = 0; // inside class definition it cannot be hidden ! 437: } ! 438: } ! 439: yylval.pn = n; ! 440: } ! 441: else { ! 442: tk = ID; ! 443: yylval.pn = new name( s ); ! 444: } ! 445: ! 446: if ( tk == ID ) ! 447: { ! 448: if ( tk2 == ID ) { ! 449: Pname n = ktbl->look( s, HIDDEN ); ! 450: if ( n ) { ! 451: // add handling of enum ! 452: if ( n->tp->base == COBJ ) ! 453: error("%sis hidden: use struct %s%s", s,s,front->retval.s); ! 454: else if ( n->tp->base == EOBJ ) ! 455: error("%sis hidden: use enum %s%s", s,s,front->retval.s); ! 456: else error("typedef %sis not visible in this scope", s ); ! 457: } ! 458: else ! 459: error("%s%s: %sis not aTN", s,front->retval.s,s); ! 460: } ! 461: else ! 462: if ( tk2 == DOT || tk2 == REF ) ! 463: mem_sel = yylval.pn; ! 464: else ! 465: if ( lasttk == TNAME && tk2 == LC ) ! 466: { ! 467: error("T%s %k: %s is unexpected", s, tk2, s ); ! 468: goto gettok; ! 469: } ! 470: } ! 471: ! 472: } ! 473: } ! 474: if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) ) ! 475: || tk == TSCOPE || tk == MEM ! 476: || tk == REF || tk == DOT || tk == GOTO ! 477: || tk == MEMPTR ) ! 478: // TNAME cannot immediately follow a type name, ! 479: // scope operator, right curly, selection, or goto ! 480: must_be_id = 1; ! 481: else ! 482: must_be_id = 0; ! 483: ! 484: switch ( tk ) { ! 485: case SM: ! 486: mem_sel = 0; // no break ! 487: case RP: case RC: must_be_expr = 0; break; ! 488: case COLON: ! 489: //if (lasttk == TYPE ) ! 490: //error( 'd', "lasttk: %k, lastval.t: %k", lasttk, lastval.t); ! 491: if (lasttk == RP || ! 492: (lasttk == TYPE && lastval.t == CONST)) ! 493: must_be_expr = 1; ! 494: break; ! 495: }; ! 496: ret: ! 497: lasttk = tk; ! 498: lastval = yylval; ! 499: return tk; ! 500: } ! 501: ! 502: extern void ! 503: la_backup( TOK t, YYSTYPE r ) ! 504: /* ! 505: called by parser to push token back on front of queue ! 506: */ ! 507: { ! 508: if ( t == ID ) r.s = r.pn->string; ! 509: register toknode* T = new toknode(t,r); ! 510: if (front) { ! 511: front->last = T; ! 512: T->next = front; ! 513: T->last = 0; ! 514: front = T; ! 515: } else ! 516: front = rear = T; ! 517: } ! 518: ! 519: extern int ! 520: la_sctype( TOK t ) { ! 521: ! 522: if ( t != latok->tok && t != TSCOPE ) error( 'i', "la_sctype, lalex.c" ); ! 523: ! 524: switch( latok->retval.t ) { ! 525: case TYPEDEF: ! 526: case EXTERN: ! 527: case STATIC: ! 528: case AUTO: ! 529: case REGISTER: ! 530: case OVERLOAD: ! 531: case INLINE: ! 532: case FRIEND: ! 533: case CONST: ! 534: case VOLATILE: ! 535: return 1; ! 536: default: ! 537: return 0; ! 538: } ! 539: } ! 540: ! 541: extern int ! 542: la_cast() ! 543: /* ! 544: called in reduction of term_lp to check for ambiguous prefix-style cast ! 545: if result is 1, caller inserts DECL_MARKER to force reduction of cast ! 546: */ ! 547: { ! 548: // yychar already designates TYPE or TNAME ! 549: // LP must start the lookahead queue! ! 550: int tk, tk2 = latok->tok; ! 551: ! 552: for ( ; ; ) { ! 553: tk = tk2; ! 554: tk2 = lookahead(); ! 555: ! 556: switch( tk ) { ! 557: case LP: ! 558: if ( tk2 == MUL || tk2 == AND || ! 559: tk2 == TSCOPE || tk2 == MEMPTR ) ! 560: // T ( * ... ! 561: // T ( C ::* ... ! 562: continue; ! 563: else ! 564: // T ( exp ) ! 565: return 0; ! 566: case MUL: case AND: ! 567: //if ( tk2 == SCTYPE ) ! 568: if ( la_sctype( tk2 ) ) ! 569: // T ( * const ... ! 570: // T ( * volatile ... ! 571: tk2 = lookahead(); ! 572: continue; ! 573: case TSCOPE: ! 574: if ( tk2 == MUL ) ! 575: // T ( C :: * ... ! 576: continue; ! 577: else ! 578: // T ( exp ) ! 579: return 0; ! 580: case RP: case LB: ! 581: // T (*)() ! 582: // T (*[])() ! 583: return 1; ! 584: case MEMPTR: ! 585: if ( tk2 == RP ) ! 586: continue; ! 587: } ! 588: ! 589: return 0; ! 590: } ! 591: } ! 592: ! 593: extern int ! 594: la_decl() ! 595: /* ! 596: handles ambiguities ! 597: type (*x) () ! 598: type (*x) [] ! 599: at start of arg list / statement ! 600: return val == 1 if lookahead finds a declaration ! 601: (used for error messages only) ! 602: if declaration is "ambiguous" (i.e., can't be recognized with ! 603: 1-symbol lookahead), insert DECL_MARKER to force reduction ! 604: of "type" ! 605: */ ! 606: { ! 607: ! 608: // LP must start the lookahead queue! ! 609: int tk, tk2 = latok->tok; ! 610: int paren = 0; ! 611: int ptr = 0; ! 612: ! 613: for ( ; ; ) { ! 614: ! 615: tk = tk2; ! 616: tk2 = lookahead(); ! 617: ! 618: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]); ! 619: switch( tk ) { ! 620: case LP: ! 621: if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) { ! 622: // T ( * ... ! 623: ++paren; ! 624: ptr = 1; ! 625: continue; ! 626: } else ! 627: if ( tk2 == MEMPTR ) { ! 628: // T ( C ::* ... ! 629: return 1; ! 630: } else ! 631: // possible redundant parens ! 632: if ( tk2 == ID && lookahead() == RP ) { ! 633: TOK tp = lookahead(); ! 634: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 ); ! 635: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl ); ! 636: if ( tp == SM || tp == CM || tp == ASSIGN ) ! 637: { ! 638: // member initialization list ! 639: if ( tp != SM && in_arg_list == 0 ) return 1; ! 640: } ! 641: else ! 642: if ( tp == RP && (bl_level-in_class_decl==0)) ! 643: return 1; ! 644: if ( tp != LP ) ! 645: return 0; ! 646: latok=latok->last; // restore lookahead ! 647: ++paren; ! 648: continue; ! 649: } ! 650: else ! 651: // T ( exp ) ! 652: return 0; ! 653: case MUL: case AND: ! 654: //if ( tk2 == SCTYPE ) ! 655: if ( la_sctype( tk2 )) ! 656: // T ( * const ... ! 657: // T ( * volatile ... ! 658: return 1; ! 659: else { ! 660: ptr = 0; ! 661: continue; ! 662: } ! 663: case TSCOPE: ! 664: if ( tk2 == MUL ) ! 665: // T ( C :: * ... ! 666: return 1; ! 667: else if ( ptr ) ! 668: // T ( exp ) ! 669: return 0; ! 670: else if ( tk2 == ID || tk2 == OPERATOR ) ! 671: // T ( * C :: id ... ! 672: continue; ! 673: else ! 674: // error ! 675: return 0; ! 676: } ! 677: ! 678: break; ! 679: } ! 680: ! 681: if ( tk == RP || tk == LB ) ! 682: // T (*)() ! 683: // T (*[])() ! 684: return 1; ! 685: ! 686: if ( tk != ID && tk != OPERATOR ) ! 687: // T ( exp ) ! 688: return 0; ! 689: ! 690: if ( tk == OPERATOR ) ! 691: switch ( tk2 ) { ! 692: case PLUS: case MINUS: case MUL: case REFMUL: ! 693: case AND: case OR: case ER: case SHIFTOP: case EQUOP: ! 694: case DIVOP: case RELOP: case ANDAND: case OROR: ! 695: case NOT: case COMPL: case ICOP: case ASSIGN: ! 696: case ASOP: case NEW: case GNEW: case DELETE: ! 697: // OPERATOR oper ! 698: tk2 = lookahead(); ! 699: break; ! 700: case LP: ! 701: // OPERATOR () ! 702: tk2 = lookahead(); ! 703: if ( tk2 == RP ) { ! 704: tk2 = lookahead(); ! 705: break; ! 706: } else ! 707: return 0; ! 708: case LB: ! 709: // OPERATOR [] ! 710: tk2 = lookahead(); ! 711: if ( tk2 == LB ) { ! 712: tk2 = lookahead(); ! 713: break; ! 714: } else ! 715: return 0; ! 716: default: // illegal operator ! 717: return 0; ! 718: } ! 719: ! 720: int allow_lp = 1; ! 721: int allow_rp = 1; ! 722: for ( ; ; ) { ! 723: tk = tk2; ! 724: tk2 = lookahead(); ! 725: ! 726: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]); ! 727: switch( tk ) { ! 728: case LP: ! 729: if ( !allow_lp ) ! 730: // T ( * id [ exp ] ( ... ! 731: return 0; ! 732: ! 733: // Current lookahead will be a decl if ! 734: // the next lookahead is an arg decl ! 735: if ( tk2 == RP || tk2 == ENUM || tk2==AGGR ! 736: || tk2==ELLIPSIS || la_sctype( tk2 )) ! 737: // T ( * id () ! 738: // T ( * id ) () ! 739: return 1; ! 740: ! 741: if ( tk2 == TYPE || tk2 == TNAME ) { ! 742: // T ( * id ) ( T2 ... ! 743: if ( lookahead() == LP && !la_decl() ) ! 744: return 0; ! 745: return 1; ! 746: } ! 747: ! 748: return 0; ! 749: case LB: ! 750: if ( tk2 == RB || lookahead() == RB ) ! 751: // T ( * id [] ... ! 752: return 1; ! 753: else { ! 754: // T ( * id [ exp ] ... ! 755: allow_lp = 0; ! 756: allow_rp = 1; ! 757: while ( lookahead() != RB ); ! 758: tk2 = lookahead(); ! 759: continue; ! 760: } ! 761: case RP: ! 762: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren ); ! 763: if ( !allow_rp || !paren ) ! 764: // T ( * id ) ) ! 765: return 0; ! 766: // permit redundant parentheses ! 767: else ! 768: if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN ) ! 769: return 1; ! 770: else ! 771: if ( tk2 == RP && (bl_level-in_class_decl == 0)) ! 772: return 1; ! 773: else ! 774: { ! 775: // T ( * id ) ... ! 776: allow_lp = 1; ! 777: allow_rp = 0; ! 778: --paren; ! 779: continue; ! 780: } ! 781: default: ! 782: return 0; ! 783: } ! 784: } ! 785: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.