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