Annotation of researchv10no/cmd/cfront/cfront2.00/lalex.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.