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