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