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

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

unix.superglobalmegacorp.com

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