|
|
1.1 root 1: /*ident "@(#)ctrans:src/lalex.c 1.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:
17: #ifdef c_plusplus
18: overload is_empty;
19: #endif
20:
21: #include "cfront.h"
22: #include "yystype.h"
23: #include "tqueue.h"
24: #include "template.h"
25:
26: #ifdef DBG
27: #define LDB(val,a) { if(Ldebug>=val) {a;} }
28: #else
29: #define LDB(val,a) /**/
30: #endif
31:
32: #ifdef DBG
33: static char*
34: image( int t )
35: {
36: if(keys[t]) return keys[t];
37: else { static char b[20];
38: sprintf(b,"token(%d)",t);
39: return b;
40: }
41: }
42: static void
43: printok( toknode* t )
44: {
45: switch(t->tok) {
46: default:
47: fprintf(stderr,"\t%s",image(t->tok));
48: break;
49: case ID: case ICON: case CCON: case FCON: case STRING:
50: fprintf(stderr,"ID '%s'",t->retval.s);
51: break;
52: case TNAME:
53: fprintf(stderr,"TNAME '%s'",t->retval.pn->string);
54: break;
55: case PTNAME:
56: fprintf(stderr,"PTNAME '%s'",t->retval.pn->string);
57: break;
58: case TSCOPE:
59: fprintf(stderr,"TSCOPE '%s'::",t->retval.pn->string);
60: break;
61: case MEMPTR:
62: fprintf(stderr,"MEMPTR '%s'::*",t->retval.pn->string);
63: break;
64: }
65: putc(' ',stderr);
66: t->place.put(stderr);
67: putc('\n',stderr);
68: }
69: static void
70: showQ( char* where )
71: /*
72: display token Q
73: */
74: {
75: fprintf(stderr,"TOKEN Q (%s):\n",where);
76: for (register toknode* t = front; t; t = t->next) printok(t);
77: putc('\n',stderr);
78: }
79: #endif
80:
81: int bl_level;
82:
83: static int laexpr( TOK );
84: static int latype( TOK );
85: static int la_decl();
86: static TOK lookahead();
87:
88: /* make this a toknode! */
89: static int lasttk = 0; // one token history
90: static YYSTYPE lastval; // yylval lasttk value
91:
92: int must_be_expr = 0; // handle redundant parentheses
93: int must_be_id = 0; // !0, TNAME => ID, i.e., int X
94:
95: loc curloc;
96: int curr_file;
97:
98: toknode* latok; // current lookahead token
99: toknode* front = 0;
100: toknode* rear = 0;
101:
102: const TQCHUNK = 16;
103:
104: void*
105: toknode::operator new(size_t)
106: {
107: register toknode* p;
108:
109: if ((p=free_toks) == 0) {
110: register toknode* q;
111: free_toks = q = (toknode*)malloc( TQCHUNK * sizeof(toknode) );
112: p = free_toks;
113: for (; q != &p[TQCHUNK-1]; q->next = q+1, ++q);
114: q->next = 0;
115: }
116: free_toks = p->next;
117: return p;
118: }
119:
120: toknode::toknode(TOK t, YYSTYPE r, loc tloc)
121: {
122: tok = t;
123: used = 0;
124: retval = r;
125: place = tloc;
126: next = last = 0;
127: }
128:
129: void
130: toknode::operator delete(void* vp,size_t)
131: {
132: register toknode* p = (toknode*)vp;
133: p->next = free_toks;
134: free_toks = p;
135: vp = 0;
136: }
137:
138: #define USE_TOKEN(T,W) \
139: LDB(2,error('d',&(T)->place,"use_token('%k','%s')",(T)->tok,W);); \
140: if ( !(T)->used ) use_token(T);
141:
142: Ptype
143: return_nstd_local_type( Pname n, TOK &sw )
144: {
145: Ptype tt;
146: switch ( n->tp->base ) {
147: case EOBJ:
148: case COBJ:
149: tt = Pbase(n->tp)->b_name->tp;
150: sw = n->tp->base;
151: break;
152: default:
153: tt = n->tpdef;
154: sw = NESTED; // in repr.c, prints ``typedef''
155: break;
156: }
157: return tt;
158: }
159:
160: static Pname
161: local_nested_kludge( Pname n, Pname tn )
162: /*
163: * for backward compatibility with 2.0
164: * in transitional model of nested class types
165: *
166: * struct T { ... };
167: * foobar() {
168: * class X {
169: * typedef int T;
170: * // ...
171: * };
172: * T t;
173: * }
174: *
175: * pure nested classes, choose global struct T{};
176: * no nested classes, choose typedef int T
177: * transitional model: choose typedef, and generate warning
178: * BUG: local typedefs and enums do not have lex_level set
179: */
180: {
181: // error( 'd', "local_nested_kludge: n: %n", n );
182: for ( Pname nn = n; nn; nn = nn->n_tbl_list )
183: {
184: Pname local_class;
185: TOK ntd;
186: if ( nn->n_key != NESTED ) continue;
187: Ptype tt = return_nstd_local_type(nn,ntd);
188: Pclass cl = tt->in_class;
189: while ( cl->in_class ) cl = cl->in_class;
190: if (cl->lex_level &&
191: (local_class = ktbl->look(cl->string,LOCAL)))
192: {
193: // same typedef at nested and non-nested scope
194: if (ntd == NESTED && tn && tn->tp == nn->tp )
195: ;
196: else
197: error('w',"%s occurs at outer and nested localC scope; using %k %t::%s", n->string,ntd,cl,n->string);
198:
199: /*
200: if ( ntd == NESTED && nn->n_dcl_printed != 2 ) {
201: nn->dcl_print(0);
202: nn->n_dcl_printed = 2;
203: }
204: */
205: return nn;
206: }
207: }
208: return 0;
209: }
210:
211: enum { one_back, two_back };
212:
213: static void
214: use_token( toknode* T )
215: /*
216: lookup TNAMEs here instead of in tlex()
217: maintain block level
218: */
219: {
220: static TOK last_tokens[2]; // TSCOPE not reduced at this point
221: static Pname last_tname; // tname :: id, where id is nested class
222: static Pname tdef_name; // typedef tname tdef_name
223: T->used = 1;
224:
225: DB(if(Ldebug>=1) {
226: error('d',&T->place,"\n*** use_token(%k )",T->tok);
227: printok(T);
228: error('D',&T->place," lasttk%k last_tname%n last tokens%k%k",lasttk,last_tname,last_tokens[one_back],last_tokens[two_back]);
229: });
230:
231: switch ( T->tok ) {
232: case ID:
233: Pname n;
234: // error('d', &T->place, "use_token: %s", T->retval.s );
235: if (last_tokens[one_back]==COLON &&
236: last_tokens[two_back]==PR &&
237: (n=ktbl->look(T->retval.s,NESTED))) {
238: T->tok=TNAME;
239: T->retval.pn=n;
240: break;
241: }
242:
243: if (last_tokens[one_back]==LC &&
244: last_tokens[two_back]==RP &&
245: (n=ktbl->look(T->retval.s,NESTED))) {
246: T->tok=TNAME;
247: T->retval.pn=n;
248: break;
249: }
250:
251: if (last_tokens[one_back]==SM &&
252: last_tokens[two_back]==RP &&
253: (n=ktbl->look(T->retval.s,NESTED))) {
254: T->tok=TNAME;
255: T->retval.pn=n;
256: break;
257: }
258:
259: if (last_tokens[one_back] == MEM &&
260: last_tokens[two_back] != TNAME &&
261: (n=ktbl->look(T->retval.s,HIDDEN))) {
262: T->tok=TNAME;
263: T->retval.pn=n;
264: break;
265: }
266:
267:
268: if ( last_tokens[one_back] == MEM &&
269: last_tokens[two_back] == TNAME &&
270: (n=ktbl->look(T->retval.s,NESTED)))
271: { // TYPEDEF :: ID, nested class ctor
272: if (tdef_name && tdef_name->n_key==NESTED &&
273: strcmp(tdef_name->string,n->string)==0)
274: {
275: T->tok = TNAME;
276: T->retval.pn = n;
277: break;
278: }
279: else { // TNAME :: ID, where ID may be nested class
280: for ( Pname nn = n; nn; nn = nn->n_tbl_list )
281: {
282: TOK sw;
283: if ( nn->n_key != NESTED ) continue;
284: Ptype tt = return_nstd_local_type(nn,sw);
285: Pclass cl = tt->in_class;
286: if (cl == 0) {
287: error("%nU",nn);
288: T->tok = TNAME;
289: T->retval.pn=nn;
290: break;
291: }
292: if (strcmp(last_tname->string,cl->string)==0)
293: {
294: T->tok = TNAME;
295: T->retval.pn = nn;
296: break;
297: }
298: }
299: }
300: }
301: else
302: if ( bl_level &&
303: // TNAME:: and :: cannot refer to ``local'' TNAME
304: last_tokens[one_back] != MEM &&
305: (n=ktbl->look(T->retval.s,LOCAL)) )
306: {
307: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: local class instance: %n", n ) );
308: T->tok = TNAME;
309: T->retval.pn = n;
310: }
311: else if ( n=ktbl->look(T->retval.s,0) ) {
312: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token:GC instance: %n", n ) );
313: // error( 'd', &T->place, "use_token:GC instance: %n %t", n, n->tp );
314:
315: // X:: ?, then n cannot be a global TNAME
316: // except in the case of a constructor
317: if (last_tokens[one_back] == MEM &&
318: last_tokens[two_back] == TNAME &&
319: strcmp(T->retval.s,last_tname->string))
320: ; // do nothing; i.e., return ID
321: else
322: if ( bl_level && n->tp->base != COBJ &&
323: last_tokens[one_back] == MEM &&
324: last_tokens[two_back] != TNAME &&
325: gtbl->look(T->retval.s,0))
326: ; // do nothing: local typedefs & enums not implemented
327: else {
328: Pname nn = 0;
329: TOK ntd;
330: if (bl_level && (nn=ktbl->look(T->retval.s,NESTED)))
331: {
332: (void) return_nstd_local_type(n,ntd);
333: nn = local_nested_kludge(nn,ntd==NESTED?n:0);
334: }
335: T->tok = TNAME;
336: T->retval.pn = nn?nn:n;
337: }
338: }
339: #ifdef DBG
340: else if(Ldebug>=1)
341: error('d',&T->place,"use_token: id %s",T->retval.s);
342: #endif
343: break;
344: case LC: ++bl_level; break;
345: case RC: --bl_level; break;
346: }
347:
348: if (T->tok != COMPL || last_tokens[one_back] != MEM) {
349: last_tokens[two_back] = last_tokens[one_back];
350: last_tokens[one_back] = T->tok;
351: if (T->tok == TNAME) last_tname = T->retval.pn;
352: if ( last_tname &&
353: last_tname->tp->base == TYPE )
354: {
355: tdef_name = last_tname;
356: do
357: tdef_name = Pbase(tdef_name->tp)->b_name;
358: while ( tdef_name->tp->base == TYPE );
359: }
360: }
361: }
362:
363: void
364: addtok(TOK t, YYSTYPE r, loc tloc)
365: {
366: toknode* T = new toknode(t,r,tloc);
367: if (front == 0)
368: front = rear = T;
369: else {
370: rear->next = T;
371: T->last = rear;
372: rear = T;
373: }
374: //error('d',&tloc,"addtok: %k '%s'",t,t==ID?r.s:"");
375: //showQ("addtok");
376: }
377:
378: extern TOK
379: deltok( int noset = 0 )
380: {
381: register toknode* T = front;
382: USE_TOKEN(T,"deltok");
383: register TOK tk = T->tok;
384: if ( !noset ) { yylval = T->retval; curloc = T->place; }
385: curr_file = curloc.file;
386: if (front = front->next)
387: front->last = 0;
388: else
389: latok = rear = 0;
390: delete T;
391: return tk;
392: }
393:
394: static void
395: add_tokens()
396: /*
397: extend lookahead token queue when depleted
398: */
399: {
400: TOK tk = tlex();
401: if ( tk != ID )
402: return;
403:
404: while (tk == ID || tk == MEM || tk == DOT )
405: tk = tlex();
406: }
407:
408: extern TOK
409: la_look()
410: /*
411: peek at head of token queue
412: */
413: {
414: LDB(1,fprintf(stderr,"\n*** la_look()"));
415: if ( front == 0 )
416: add_tokens();
417:
418: latok = front;
419: USE_TOKEN(latok,"la_look");
420: LDB(1,fprintf(stderr," -- %s\n",image(latok->tok)));
421: return latok->tok;
422: }
423:
424: #define NEXTTOK() ( (yychar==-1) ? (yychar=lalex(),yychar) : yychar )
425: void
426: check_decl()
427: /*
428: Lookahead to direct parsing of local/arg type declarations
429: la_decl() returns 1 if lookahead sees a declaration.
430: */
431: {
432: TOK tk2;
433: switch( NEXTTOK() ) {
434: default:
435: break;
436: case TSCOPE: //XXX
437: tk2 = la_look();
438: while ( tk2 == TSCOPE ) tk2 = lookahead();
439: if ( tk2 == TNAME ) {
440: toknode* t = latok;
441: if(t->tok!=TNAME)
442: error('i',&t->place,"check_decl() token scan");
443: tk2 = lookahead();
444: if ( tk2 == LP && la_decl() ) {
445: t->tok = DECL_MARKER; //TNAME
446: }
447: }
448: break;
449: case TYPE: case TNAME:
450: if ( la_look() == LP && la_decl() ) {
451: must_be_id = 0;
452: DECL_TYPE=yychar;
453: yychar = DECL_MARKER;
454: }
455: }
456: }
457:
458: void
459: check_cast()
460: /*
461: Lookahead to direct parsing of cast
462: la_cast() returns 1 if lookahead sees an ambiguous old-style C cast.
463: */
464: {
465: TOK tk2;
466: switch( NEXTTOK() ) {
467: case TSCOPE: //XXX
468: tk2 = la_look();
469: while ( tk2 == TSCOPE ) tk2 = lookahead();
470: if ( tk2 == TNAME ) {
471: toknode* t = latok;
472: if(t->tok!=TNAME)
473: error('i',&t->place,"check_cast() token scan");
474: tk2 = lookahead();
475: if ( tk2 == LP && la_decl() ) {
476: t->tok = DECL_MARKER;//TNAME
477: }
478: }
479: break;
480: case TYPE: case TNAME:
481: if ( la_look() == LP && la_cast() ) {
482: must_be_id = 0;
483: DECL_TYPE = yychar;
484: yychar = DECL_MARKER;
485: }
486: }
487: }
488:
489:
490: static int
491: latype( TOK t )
492: {
493: switch ( t ) {
494: default: // includes friend, typedef, storage classes, etc.
495: return 0;
496: case CHAR: case SHORT: case INT: case LONG:
497: case FLOAT: case DOUBLE:
498: case UNSIGNED:
499: return 1;
500: }
501: }
502:
503: static int
504: laexpr( TOK t )
505: {
506: switch ( t ) {
507: default:
508: return 0;
509: case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR:
510: case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS:
511: case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP:
512: case SHIFTOP: case ICOP:
513: return 1;
514: }
515: }
516:
517: static toknode *get_next_token(toknode *t) {
518: if (! t->next)
519: add_tokens() ;
520:
521: return t->next ;
522: }
523:
524:
525: static int template_tscope(Pname tn, toknode *lt)
526: /* provide the looakhead for determining TSCOPE tokens when the name is a
527: * parametrized type name; the lookahead here is non-trivial, because it
528: * involves stepping over the template arguments.
529: */
530: {
531: int nest = 0 ; // the LT has been fetched
532:
533: if (lt->tok != LT) error ('i', "a `<' token was expected") ;
534:
535: // assume the worst, ensure that name strings are consed in the heap
536: templp->parameters_in_progress++ ;
537:
538: for (toknode *t = lt;; t = get_next_token(t))
539: switch (t->tok) {
540:
541: case LT:
542: ++nest;
543: continue;
544: case GT:
545: // ***************
546: // need to fold in awareness of x::y::z
547: if (--nest == 0) {
548: t = get_next_token(t);
549: if (t->tok == MEM) {
550: // determine whether it is a memptr
551: if (t->next == 0) add_tokens();
552: if (t->next->tok == MUL) {
553: t->tok = MEMPTR;
554: t->next = t->next->next ;
555: } else t->tok = TSCOPE ;
556: t->retval.pn = tn ;
557: --templp->parameters_in_progress;
558: return 1;
559: }
560: else return 0 ;
561: }
562: continue;
563:
564: case SM: case LC: case RC: // a quick exit in case of error
565: case EOFTOK:
566: --templp->parameters_in_progress;
567: return 0 ;
568:
569: default:
570: continue;
571: }
572: }
573:
574: static TOK
575: lookahead()
576: /*
577: advance lookahead pointer, lexing at end of Q
578: handle occurrences of TNAME and TSCOPE
579: (should be kept up to date with lalex())
580: */
581: {
582: TOK tk;
583: TOK tk2;
584: TOK prev_tk = 0;
585: YYSTYPE lastval;
586:
587: if ( latok == rear ) {
588: add_tokens();
589: if ( latok )
590: latok = latok->next;
591: else
592: latok = front;
593: }
594: else
595: latok = latok->next;
596:
597: if ( latok->last ) {
598: prev_tk = latok->last->tok;
599: lastval = latok->last->retval;
600: }
601:
602: nexttok:
603: USE_TOKEN(latok,"lookahead1");
604: tk = latok->tok;
605: if ( tk == ID || tk == TNAME )
606: {
607: if (latok->next == 0) add_tokens();
608: USE_TOKEN(latok->next,"lookahead2");
609: /* TOK */ tk2 = latok->next->tok;
610: if ( tk == TNAME ) {
611: if (tk2 == LT) {
612: // a parametrized type name -- differentiate from TNAME
613: // so that it can be dealt with in the grammar.
614: if (template_tscope(latok->retval.pn, latok->next)) tk = PTNAME;
615: }
616: else
617: if ( tk2 == MEM || tk2 == DOT ) {
618: tscope:
619: tk = TSCOPE;
620: // error('d',"lookahead: tk: %k tk2: %k", tk, tk2 );
621: // XXX -- should be modified to loop and do lookup
622: latok = latok->next;
623: if (latok->next == 0) add_tokens();
624: USE_TOKEN(latok->next,"lookahead3");
625: tk2 = latok->next->tok;
626: if ( tk2 == MUL ) {
627: tk = MEMPTR;
628: latok = latok->next;
629: }
630: }
631: else if (( prev_tk == MUL && tk2 != RP )
632: || prev_tk == AND )
633: {
634: tk = ID;
635: latok->retval.pn->hide();
636: latok->tok = ID;
637: latok->retval.s = latok->retval.pn->string;
638: }
639: }
640: else if ( tk2 == MEM ) {
641: // ID ::
642: //XXX latok = latok->next->next;
643: //XXX goto nexttok;
644: goto tscope; // treat as tscope
645: }
646:
647: if ( tk == ID &&
648: ( tk2 == ID ||
649: ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) {
650: // ID ID
651: latok = latok->next;
652: goto nexttok;
653: }
654: }
655:
656: if ( tk == ID ) {
657: Pname nstd = ktbl->look(latok->retval.s,NESTED);
658: if (nstd && (must_be_id == 0 ||
659: must_be_id && prev_tk == LP)) {
660: extern Pname check_for_nested(Pname,TOK,YYSTYPE,TOK); // use this in lalex, too
661: Pname n = check_for_nested(nstd,prev_tk,lastval,tk2);
662: if ( n ) {
663: tk = latok->tok = TNAME;
664: latok->retval.pn = n;
665: }
666: }
667: }
668:
669: return tk;
670: }
671:
672: static Pname mem_sel = 0;
673:
674: static Pname
675: do_local_class( Pname n, int lex_level )
676: { /*
677: * modify to ``do_local_type:
678: * do local types: enums and typedefs
679: */
680: Pname nn = n;
681: if ( n->tp ) { // already a TNAME
682: Pclass cl = n->tp->base==COBJ ? Pclass(Pbase(n->tp)->b_name->tp) : 0;
683: if ( n->lex_level != lex_level || (cl && cl->lcl) ) {
684: local_hide( n );
685: nn = new name( n->string );
686: nn->lex_level = lex_level>=0?lex_level:0;
687: }
688: else
689: if ( lex_level == n->lex_level && cl->defined ) {
690: error( "localC %n redefined", n );
691: return n;
692: }
693: }
694:
695: nn = nn->tname( lastval.t );
696: modified_tn = modified_tn->l;
697: nn->n_key = LOCAL;
698: local_class = new name_list( nn, local_class );
699: local_blk = new name_list( nn, local_blk );
700:
701: // error('d', "do_local_class: nn %n tp %t", nn, Pclass(Pbase(nn->tp)->b_name->tp));
702: return nn;
703: }
704:
705: static char*
706: make_nested_name( char *s, Pclass cl )
707: { // Q<cnt>_<class_names><space><null>
708: const nested_depth = 9;
709: char *str_arr[nested_depth];
710: int size_arr[nested_depth];
711: int cnt = 2;
712: int size = 4; // Q,<cnt>,<_>,<null>
713:
714: str_arr[0] = s; str_arr[1] = cl->string;
715:
716: size += size_arr[0] = strlen(s);
717: size += size_arr[1] = cl->strlen?cl->strlen:strlen(cl->string);
718:
719: for (Pclass nc = cl->in_class; nc; nc = nc->in_class ) {
720: if (cnt > nested_depth-1) error('s',"nested depth class beyond %d unsupported",nested_depth);
721: size += size_arr[cnt] = nc->strlen?nc->strlen:strlen(nc->string);
722: str_arr[cnt++] = nc->string;
723: }
724:
725: for ( int i=0; i<cnt; i++ ) // <nnn><string>
726: size += size_arr[i]>99?3:size_arr[i]<10?1:2;
727:
728: //error('d', "make_nested_name( %s, %t ) cnt: %d size: %d", s, cl, cnt, size );
729: char *result = new char[size];
730: sprintf(result, "Q%d_", cnt );
731: size = 3;
732: for ( i=cnt; i; i-- ) {
733: sprintf(result+size,"%d%s", size_arr[i-1], str_arr[i-1]);
734: size += size_arr[i-1] + (size_arr[i-1]>99?3:size_arr[i-1]<10?1:2);
735: }
736:
737: //error('d', "size: %d ", size );
738: result[size] = '\0';
739: //error('d', "make_nested_name result: %s", result );
740: return result;
741: }
742:
743: int is_empty( Pclass cl, bit const_chk )
744: { /* for nested class check, empty means *no* members
745: * for const object check, means no *data* members
746: */
747:
748: // error('d',"%t->is_empty: max: %d real_size: %d", cl, cl->memtbl->max(),cl->real_size );
749:
750: int mbr_cnt = cl->memtbl->max();
751: if ( mbr_cnt == 0 ) return 1;
752:
753: if ( cl->baselist == 0 && cl->real_size!=1 )
754: return 0;
755:
756: // empty class to turn on transitional nested class scope
757: if ( const_chk == 0 &&
758: ( cl->baselist != 0 || mbr_cnt > 1 )) return 0;
759:
760: int i = 1;
761: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i)) {
762: if (nn->base==NAME &&
763: nn->n_union==0 &&
764: nn->tp->base!=FCT &&
765: nn->tp->base!=OVERLOAD &&
766: nn->tp->base!=CLASS &&
767: nn->tp->base!=ENUM &&
768: nn->tp->base!=EOBJ &&
769: nn->n_stclass != STATIC)
770: {
771: if ( nn->string[0]=='_' &&
772: nn->string[1]=='_' &&
773: nn->string[2]=='W' )
774: return 1;
775: else return 0;
776: }
777: }
778:
779: return 1; // if here, no data members encountered
780: }
781:
782: static int
783: is_empty( Penum en )
784: { // is this an empty enum ??
785:
786: // error('d', "%t no_of_enumerators: %d", en, en->no_of_enumerators);
787: if ( en->no_of_enumerators != 0 )
788: return 0;
789:
790: return 1;
791: }
792:
793: static Pname
794: check_nested_type( Pname nm )
795: {
796: // error('d', "check nested type: %n ccl: %t", nm, ccl );
797:
798: Pname nx, n = ktbl->look(nm->string, NESTED);
799: if ( n == 0 || n == nm ) return nm;
800:
801: int cnt = 1;
802: for (nx = n; n; n=n->n_tbl_list )
803: if (n->n_key == NESTED) ++cnt;
804:
805: if ( cnt > 1 ) {
806: error( "ambiguous nested type %s (%d instances), use x::y syntax", nm->string, cnt );
807: error( 'i', "cannot recover from previous errors" );
808: }
809: else {
810: TOK ntk;
811: Ptype tt = return_nstd_local_type(nx,ntk);
812: error('w', "use %t:: to access nested %k %s (anachronism)", tt->in_class, ntk, nx->string);
813: }
814: return nx;
815: }
816:
817: static int
818: in_local_class( Pclass cl )
819: {
820: if ( cl->lex_level )
821: return 1;
822: if ( cl->in_class )
823: return in_local_class( cl->in_class );
824: return 0;
825: }
826:
827: static Pname
828: do_nested_type( Pname n )
829: {
830: Pname nn = n;
831: char *str = 0;
832:
833: // error('d', "do_nested_type: %s in_typedef: %d ccl: %t", n->string, in_typedef, ccl );
834: if ( in_typedef && ccl->string[0]=='_'
835: && ccl->string[1]=='_'
836: && ccl->string[2]=='C') return n;
837:
838: if ( n->tp )
839: { // already a TNAME :
840: // hide existing instance, encode new instance
841: /*
842: * need handle the anomaly:
843: * class x;
844: * x *p;
845: * class y {
846: * class x{ ... }; // oops
847: * };
848: */
849: if (n->tp->base==COBJ) {
850: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
851: if (cl->defined == 0 && lasttk == AGGR) {
852: error('w',"forwardD ofC%n resolved to nested%t::%s",n,ccl,n->string);
853: cl->lcl = new char[9];
854: strcpy(cl->lcl,"FUDGE007"); // license to hack
855: n->lex_level=Pbase(n->tp)->b_name->lex_level=0;
856: return n;
857: }
858: }
859: else if (n->tp->base==EOBJ) { // watch out for enum x;
860: Penum en = Penum(Pbase(n->tp)->b_name->tp);
861: if (en->defined == 0 && lasttk == ENUM) return n;
862: }
863:
864: nested_hide( n );
865: nn = new name( n->string );
866: str = make_nested_name( n->string, ccl );
867: }
868: else
869: // make sure we haven't already seen a nested instance
870: // if so, for transition, this needs to be an error
871: if (ktbl->look( n->string, NESTED ))
872: error("multiple type %s nestings (to do this define an empty class/enum %s {};)",n->string,n->string);
873: if ( in_typedef ) {
874: if (strcmp(ccl->string, nn->string)==0) { // class x { typedef T x;
875: error( "nested Tdef %s redefines immediately enclosing class", nn->string );
876: error( 'i', "cannot recover from previous errors" );
877: }
878:
879: // make sure there isn't an identifier at global scope being defined
880: // by a nested typedef -- previously an error; keep it so for transition
881: Pname tn;
882: if ( n->tp == 0 && in_local_class(ccl)==0 &&
883: (tn=gtbl->look(n->string,0))) {
884: error( "nested Tdef %s redefinesG %n", n->string, tn );
885: error( 'i', "cannot recover from previous errors" );
886: }
887:
888: nn->tpdef = new type;
889: nn->tpdef->nested_sig = str;
890: nn->tpdef->in_class = ccl;
891: nn->tpdef->lex_level = NESTED;
892: PERM(nn->tpdef);
893: }
894: else {
895: nn = nn->tname( lastval.t );
896: Pname tn = Pbase(nn->tp)->b_name;
897: Ptype tt = tn->tp;
898: if ( tt->defined && tt->in_class == ccl) {
899: error( "nested %t redefines immediately enclosing class", nn->string );
900: error( 'i', "cannot recover from previous errors" );
901: }
902: tt->nested_sig = str;
903: modified_tn = modified_tn->l;
904: nn->lex_level = tn->lex_level = 0;
905: nested_type = new name_list( nn, nested_type );
906: }
907: nn->n_key = NESTED;
908: return nn;
909: }
910:
911: static Pname dtor_seen;
912: static int in_expr;
913: extern int in_sizeof;
914:
915: extern TOK
916: lalex()
917: /* return next token to grammar */
918: {
919: register TOK tk;
920: if ( front == 0 )
921: add_tokens(); // extend lookahead queue
922: LDB(1,fprintf(stderr,"\n*** lalex()\n");showQ("before"));
923:
924: gettok:
925: tk = deltok();
926: // error('d',&curloc,"lalex: just got %k '%s' in_typedef: %d",tk,tk==ID?yylval.s:tk==TNAME?yylval.pn->string:"", in_typedef);
927:
928: if ( tk == ID || tk == TNAME )
929: {
930: TOK tk2 = la_look();
931: int lex_level = bl_level - in_class_decl - (tk2 == LC );
932:
933: if ( tk == TNAME )
934: {
935: //error('d', "lalex tname %n; lasttk: %k tk2: %k", yylval.pn, lasttk, tk2);
936: //error('d', " must_be_id: %d must_be_expr %d decl_type %d",must_be_id,must_be_expr,DECL_TYPE);
937: //error('d', " bl_level: %d parsing_members %d",bl_level,parsing_class_members);
938: if ( tk2 == LP
939: && (bl_level == 0 || parsing_class_members)
940: && ( laexpr(lasttk) == 0 )
941: && must_be_expr == 0
942: && DECL_TYPE == 0 ) {
943: if (la_decl()) {
944: must_be_id = 0;
945: DECL_TYPE = tk;
946: tk = DECL_MARKER;
947: goto ret;
948: }
949: }
950:
951: // note: *** can handle local typedefs here, too!
952: if ( in_typedef &&
953: in_typedef->base != 0 &&
954: ccl && in_mem_fct == 0 &&
955: (tk2 == SM || tk2 == RP || tk2 == LB))
956: yylval.pn = do_nested_type(yylval.pn);
957:
958: if ( lasttk == AGGR || lasttk == ENUM ) {
959: if ( tk2 == LC || tk2 == COLON ) { // class definition
960: if ( lex_level
961: && (in_class_decl==0 || in_mem_fct)
962: && lasttk != ENUM ) // temporary
963: yylval.pn = do_local_class( yylval.pn, lex_level );
964: else
965: if ( in_class_decl && ccl )
966: yylval.pn = do_nested_type( yylval.pn );
967: }
968: }
969:
970: if (tk2 == LT) {
971: // a parametrized type name
972: if (template_tscope(yylval.pn,latok))
973: tk = PTNAME ;
974: } else
975: if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) {
976: if (tk2==DOT)
977: error(strict_opt?0:'w',"``.'' used for qualification; please use ``::'' (anachronism)");
978: crunch:
979: tk = TSCOPE;
980: {//XXX -- should be modified to do lookup and del at each ::
981: while ( (tk2 = lookahead()) == TSCOPE ) ;
982: if ( tk2 == TNAME ) {
983: tk2 = lookahead();
984: if ( tk2 == LP
985: && (bl_level == 0 || parsing_class_members)
986: && ( laexpr(lasttk) == 0 )
987: && must_be_expr == 0
988: && DECL_TYPE == 0 ) {
989: if (la_decl()) {
990: must_be_id = 0;
991: //DECL_TYPE = tk;//???
992: DECL_TYPE = TNAME;
993: //front should be ::
994: front->tok = TSCOPE;
995: front->retval.pn = yylval.pn;
996: yylval.pn = 0;
997: tk = DECL_MARKER;
998: goto ret;
999: }
1000: }
1001: }
1002: }
1003: tk2 = deltok(1);
1004: tk2 = la_look();
1005: if ( tk2 == MUL ) {
1006: tk = MEMPTR;
1007: tk2 = deltok(1);
1008: }
1009: }
1010: // Have a TNAME. Check to be sure.
1011: else if ( must_be_id ){
1012: //error('d',"lalex: must_be_id: <tname %n> <%k>",yylval.pn,tk2);
1013: if ( in_class_decl
1014: && lasttk == TYPE
1015: && tk2 == LP
1016: && strcmp(yylval.pn->string,ccl->string) == 0 )
1017: error("%nK with returnT", yylval.pn);
1018:
1019: else if ( lasttk == TYPE && lastval.t == OVERLOAD
1020: && ( tk2 == SM || tk2 == LP ) )
1021: {
1022: tk = ID;
1023: yylval.pn->hide();
1024: yylval.pn = new name( yylval.pn->string );
1025: yylval.pn->n_oper = TNAME;
1026: }
1027: else if ( lasttk == OPERATOR ||
1028: in_typedef && yylval.pn->n_key == NESTED)
1029: must_be_id = 0;
1030: else if ( lasttk != TSCOPE // watch out for X::X
1031: || lastval.pn != yylval.pn
1032: || (in_typedef &&
1033: in_typedef->check( yylval.pn->tp,0) == 0 ))
1034: {
1035: tk = ID;
1036: if ( in_typedef && (lasttk == MUL || lasttk == REF)) {
1037: defer_check = 1;
1038: in_tag = yylval.pn;
1039: }
1040:
1041: if ( lasttk == MEM && yylval.pn->lex_level ) {
1042: Pname nn = gtbl->look( yylval.pn->string, 0 );
1043: if (nn == 0 )
1044: error( "%k%s undeclared", lasttk, yylval.pn->string);
1045: else
1046: yylval.pn = nn;
1047: }
1048: else {
1049: // error('d',"lalex: else: lasttk: %k", lasttk );
1050: if (lasttk!=DOT && lasttk!=REF
1051: && lasttk!=TSCOPE && lasttk != GOTO ) {
1052: // handle typedefs in basetype::check
1053: // when type is available
1054: if (!in_typedef) {
1055: // error('d',"\"%s\" line %d: hiding%n",__FILE__,__LINE__,yylval.pn);
1056: yylval.pn->hide();
1057: }
1058: yylval.pn = new name(yylval.pn->string);
1059: yylval.pn->n_oper = TNAME;
1060: } else
1061: yylval.pn = new name(yylval.pn->string);
1062: }
1063: if ( defer_check ) defer_check = 0;
1064: }
1065: } // must_be_id
1066:
1067: if ( in_class_decl &&
1068: ccl->lex_level &&
1069: yylval.pn->lex_level != 0 &&
1070: yylval.pn->tp &&
1071: (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ))
1072: {
1073: Pname n = gtbl->look( yylval.pn->string,0);
1074: if ( in_mem_fct ) {
1075: if (n && n->base == TNAME ) {
1076: error('w', "local typedef %n(%t) is not in scope of local class %s members; usingG (%t)", yylval.pn, yylval.pn->tp, ccl->string, n->tp );
1077: yylval.pn = n;
1078: } else
1079: error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string);
1080: }
1081: }
1082:
1083: // if we still have a TNAME, make sure have the right TNAME
1084: // possibility of ananchronistic reference to nested type
1085: Ptype nbt = yylval.pn->tp;
1086: if (tk == TNAME && curr_scope == 0 && nbt && // Y y; not X::Y y;
1087: (nbt->base == EOBJ || nbt->base == COBJ))
1088: {
1089: Ptype t = Pbase(nbt)->b_name->tp;
1090: if ( ccl && t->in_class &&
1091: strcmp(t->in_class->string, ccl->string))
1092: {
1093: switch( nbt->base ) {
1094: case COBJ:
1095: if (is_empty(Pclass(t)))
1096: yylval.pn = check_nested_type( yylval.pn );
1097: break;
1098: case EOBJ:
1099: if (is_empty(Penum(t)))
1100: yylval.pn = check_nested_type( yylval.pn );
1101: break;
1102: };
1103: }
1104: }
1105: }
1106: else
1107: { // tk == ID
1108: char *s = yylval.s;
1109: Pname n = ktbl->look( s, HIDDEN );
1110: Pname nstd = ktbl->look( s, NESTED );
1111:
1112: // inside a class definition, ccl, that is nested
1113: // s is a nested class name, and is the name of ccl
1114: if (ccl && ccl->in_class && nstd &&
1115: strcmp(s, ccl->string)==0)
1116: {
1117: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
1118: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
1119: ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
1120: Pclass cl = tt->in_class;
1121: if ( nn->n_key != NESTED ) continue;
1122: if (strcmp(ccl->in_class->string,cl->string) == 0) {
1123: tk = TNAME;
1124: yylval.pn = nn;
1125: n = nstd = nn;
1126: }
1127: }
1128: }
1129:
1130: if (tk2 == MEM) {
1131: // ID ::
1132: if (n) {
1133: yylval.pn = n;
1134: /*XXX*/ goto crunch;
1135: }
1136: else
1137: if (nstd &&
1138: nstd->n_tbl_list==0)
1139: {
1140: yylval.pn = nstd;
1141: tk = TSCOPE;
1142: tk2 = deltok(1);
1143: tk2 = la_look();
1144: if (tk2 == MUL ) {
1145: tk = MEMPTR;
1146: tk2 = deltok(1);
1147: }
1148: }
1149: else {
1150: error( "%s:: %sis not aTN", s, s );
1151: tk2 = deltok(1);
1152: goto gettok;
1153: }
1154: }
1155: else // transitional kludge
1156: if ( n && nstd && n == nstd )
1157: ; // null statement
1158:
1159: // Have an ID. Check last token to be sure.
1160: else if (lasttk==ENUM || lasttk==AGGR &&
1161: // template <class id, class id>
1162: (tk2 != GT && tk2 != CM))
1163: {
1164: int fd = tk2!=LC && tk2!=COLON;
1165: tk = TNAME;
1166: if ( nstd ) {
1167: // in transitional model, need flag this as error
1168: if ( fd == 0 ) { // real definition
1169: if ( ccl == 0 )
1170: error("nested andG%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS, s);
1171: else
1172: error("multiple nested%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS,s);
1173: error( 'i', "cannot recover from previous errors" );
1174: }
1175: }
1176: else
1177: // new tag, define it
1178: if (n==0 ||
1179: (n->n_template_arg == template_type_formal))
1180: {
1181: // error('d', "ccl: %t fd: %d, in_mem_fct: %d, in_class_decl: %d", ccl, fd, in_mem_fct, in_class_decl);
1182: n = new name( s );
1183: if ( fd ) // struct X*, etc.
1184: n->lex_level=0;
1185: else
1186: n->lex_level=lex_level>=0?lex_level:0;
1187:
1188: if ( ccl && fd == 0 &&
1189: in_class_decl &&
1190: (bl_level == ccl->lex_level + in_class_decl + 1))
1191: n = do_nested_type( n );
1192: else
1193: // note: ***** modify to handle local typedef
1194: // note: ***** add local enums
1195: if ( n->lex_level &&
1196: lasttk != ENUM ) // temporary
1197: n = do_local_class( n, n->lex_level );
1198: else {
1199: n = n->tname( lastval.t );
1200: modified_tn = modified_tn->l;
1201: if (gtbl->look(n->string,0)) statStat = n;
1202: }
1203: }
1204: else {
1205: if (n->tp->base!=COBJ && n->tp->base!=EOBJ) {
1206: error( 'i', "hidden%n:%t",n,n->tp );
1207: goto gettok;
1208: }
1209:
1210: if ( tk2 == LC || tk2 == COLON ) {
1211: // class declared and hidden but not yet defined
1212: // may have ctor defined which invalidates hiding
1213: statStat = n;
1214: n->n_key = 0; // inside class definition it cannot be hidden
1215: }
1216: }
1217: yylval.pn = nstd?nstd:n;
1218: }
1219: else {
1220: tk = ID;
1221: yylval.pn = new name( s );
1222: }
1223:
1224: if ( tk == ID )
1225: {
1226: switch ( tk2 ) {
1227: case ID: case TNAME: case AGGR: case ENUM:
1228: {
1229: Pname n = 0;
1230:
1231: if ((curr_scope||ccl) && nstd) {
1232: // within class scope in which nested class is visible
1233: // curr_scope == set by TSCOPE, X::foo() { ... }
1234: // ccl == parsing class definition ``ccl''
1235:
1236: char *str = curr_scope?curr_scope->string:ccl->string;
1237: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
1238: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
1239: ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
1240: Pclass cl = tt->in_class;
1241: if ( nn->n_key != NESTED ) continue;
1242: if ( strcmp(str,cl->string) == 0){
1243: tk = TNAME;
1244: yylval.pn = nn;
1245: if (lasttk == TYPE &&
1246: lastval.t == TYPEDEF )
1247: in_typedef = yylval.pn->tp;
1248: break;
1249: }
1250: }
1251: }
1252: if (tk == TNAME) break; // found nested class
1253:
1254: n = ktbl->look( s, HIDDEN );
1255: if ( n ) {
1256: Pname nn = n;
1257: switch ( n->tp->base ) {
1258: default:
1259: error("typedef %sis not visible in this scope", s );
1260: break;
1261: case COBJ:
1262: if (is_empty(Pclass(Pbase(n->tp)->b_name->tp)))
1263: n = check_nested_type( nn );
1264: if (nn == n)
1265: error("%sis hidden: use struct %s%s", s,s,front->retval.s);
1266: break;
1267: case EOBJ:
1268: if (is_empty(Penum(Pbase(n->tp)->b_name->tp)))
1269: n = check_nested_type( nn );
1270: if (nn == n)
1271: error("%sis hidden: use enum %s%s", s,s,front->retval.s);
1272: break;
1273: };
1274: tk = TNAME;
1275: yylval.pn = n;
1276: }
1277: else
1278: if (n=ktbl->look(s,NESTED))
1279: {
1280: TOK ntk;
1281: bit ok = 0;
1282: Ptype tt = return_nstd_local_type(n,ntk);
1283: Pclass cl = tt->in_class;
1284: if (ccl) {
1285: // x::y unncessary with in_class,
1286: // a derived class of in_class
1287: // or classes enclosing in_class
1288: if (ccl==cl || ccl->has_base(cl))
1289: ok++;
1290: else {
1291: for (Pclass eccl=ccl->in_class;eccl; eccl=eccl->in_class)
1292: if ( eccl == cl ) { ok++; break; }
1293: }
1294: }
1295: if (!ok)
1296: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, n->string );
1297: tk = TNAME;
1298: yylval.pn = n;
1299: }
1300: else { // probably a typo
1301: if ( tk2 == ID )
1302: error("%s%s: %sis not aTN", s,front->retval.s,s);
1303: else if ( tk2 == TNAME )
1304: error("%s%s: %sis not aTN", s,front->retval.pn->string,s);
1305: else
1306: error("%s%k: %sis not aTN", s,front->retval.t,s);
1307: goto gettok;
1308: }
1309: break;
1310: }
1311: case DOT: case REF:
1312: mem_sel = yylval.pn;
1313: break;
1314: default:
1315: if ( lasttk == TNAME && tk2 == LC )
1316: {
1317: error("T%s %k: %s is unexpected", s, tk2, s );
1318: goto gettok;
1319: }
1320:
1321: // have an ID. lets just make sure it should not be a TNAME
1322: if (curr_scope||ccl||nstd) {
1323: if (ccl && in_typedef &&
1324: in_typedef->base != 0 &&
1325: in_mem_fct == 0 &&
1326: (tk2 == SM || tk2 == RP || tk2 == LB))
1327: {
1328: yylval.pn = do_nested_type( yylval.pn );
1329: tk = TNAME;
1330: }
1331: else
1332: if (nstd && must_be_id == 0 && (in_expr == 0 || (lasttk==LP && tk2==RP))) {
1333: // error('d',"nstd: %n must_be_id 0 have id tk2: %k lasttk: %k",nstd,tk2,lasttk);
1334: // error('d',"nstd: in_expr %d lex_level %d",in_expr,lex_level);
1335: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
1336: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
1337: TOK ntk;
1338: bit ok = 0;
1339: Ptype tt = return_nstd_local_type(nn,ntk);
1340: Pclass cl = tt->in_class;
1341: // error('d',"xcl: %t ccl: %t", xcl, ccl );
1342: if ( xcl ) {
1343: if (xcl==cl || xcl->has_base(cl) || ccl == cl)
1344: ok++;
1345: else {
1346: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
1347: if ( eccl == cl ) { ok++; break; }
1348: }
1349: }
1350:
1351: if (nn == nstd)
1352: {
1353: if (
1354: // special case: foo(X,
1355: // in_arg_list not set until **after** X is handled
1356: ((in_arg_list || lasttk==LP) && // foo(nestedX
1357: (tk2==CM || tk2==ASSIGN ||
1358: (tk2==RP && lasttk!=MUL && lasttk!=REF)))
1359: || // class x : public nestedX
1360: (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
1361: || // nestedX [*&]
1362: (tk2 == MUL || tk2==AND)
1363: || (lasttk==LP && tk2==RP)
1364: || (lasttk==TSCOPE && lastval.pn == nn)
1365: || (lasttk==COMPL && dtor_seen == nn)
1366: || (lasttk==TYPE && lastval.t == TYPEDEF)
1367: || lasttk == OPERATOR
1368: || lasttk == NEW || in_sizeof )
1369: { // must be type name, and it must be nested:
1370: if ( nstd->n_tbl_list == 0 ) { // only one: ok
1371: if (lasttk != TSCOPE && !ok )
1372: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, nn->string);
1373: break;
1374: }
1375: else {
1376: if (lasttk != TSCOPE && lasttk != TYPE && !ok){
1377: error("ambiguous nested type %s, use %t::%s",nn->string,xcl,nn->string);
1378: error( 'i', "cannot recover from previous errors" );
1379: }
1380: }
1381: }
1382:
1383: }
1384: if ( nn->n_key != NESTED ) continue;
1385: if (xcl &&
1386: strcmp(xcl->string,cl->string) == 0) break;
1387: } // end: for nn = nstd
1388:
1389: if (nn) {
1390: tk = TNAME;
1391: yylval.pn = nn;
1392: if (lasttk == TYPE &&
1393: lastval.t == TYPEDEF )
1394: in_typedef = yylval.pn->tp;
1395: }
1396: } // end: if (nstd)
1397: } // end: if (curr_scope||ccl)
1398: break;
1399: } // end: switch tk2
1400: } // end: if (tk == ID)
1401: }
1402:
1403: // error('d',"testing for in_expr: in_expr: %d tk: %k", in_expr, tk );
1404: // error('d',"testing for in_expr: tk2: %k lasttk: %k", tk2, lasttk );
1405: if (lex_level && tk==ID && tk2==LP &&
1406: (lasttk==LC || lasttk==RC || lasttk==RP ||
1407: lasttk == ASSIGN || lasttk == SM))
1408: in_expr = 1;
1409: else in_expr = 0;
1410:
1411: }
1412: if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) )
1413: // XXX || tk == TSCOPE || tk == MEM
1414: || tk == REF || tk == DOT || tk == GOTO
1415: || tk == MEMPTR )
1416: // TNAME cannot immediately follow a type name,
1417: // scope operator, right curly, selection, or goto
1418: must_be_id = 1;
1419: else
1420: must_be_id = 0;
1421:
1422: switch ( tk ) {
1423: case SM:
1424: mem_sel = 0; // no break
1425: in_expr = 0;
1426: case RP: case RC: must_be_expr = 0; break;
1427: case COLON:
1428: if (lasttk == RP ||
1429: (lasttk == TYPE && lastval.t == CONST))
1430: must_be_expr = 1;
1431: break;
1432: case SIZEOF:
1433: in_sizeof = 1;
1434: break;
1435: };
1436: ret:
1437: if ( tk == COMPL && lasttk == TSCOPE )
1438: dtor_seen = lastval.pn;
1439: else dtor_seen = 0;
1440: lasttk = tk;
1441: lastval = yylval;
1442: LDB(1,showQ("after");
1443: fprintf(stderr,"returning '%s'",image(tk));
1444: if ( tk==ID || tk==TNAME ) fprintf(stderr," -- '%s'",yylval.pn->string);
1445: fprintf(stderr,"\n");
1446: );
1447: // error('d',"returning tk: %k dtor_seen: %n", tk,dtor_seen );
1448: return tk;
1449: }
1450:
1451: extern void
1452: la_backup( TOK t, YYSTYPE r )
1453: /*
1454: called by parser to push token back on front of queue
1455: */
1456: {
1457: LDB(1,fprintf(stderr,"\n*** la_backup( '%s', ...)\n",image(t)));
1458: if ( t == ID ) { Pname n = r.pn; r.s = n->string; DEL(n); }
1459: register toknode* T = new toknode(t,r,curloc);
1460: if (front) {
1461: front->last = T;
1462: T->next = front;
1463: T->last = 0;
1464: front = T;
1465: } else
1466: front = rear = T;
1467: lasttk = 0;
1468: }
1469:
1470: extern int
1471: la_sctype( TOK t )
1472: {
1473: //error('d',&latok->place,"la_sctype(%k ) -- latok ==%k",t,latok->tok);
1474: if ( t != latok->tok && t != TSCOPE && t != MEMPTR )
1475: error( 'i', &latok->place, "la_sctype, lalex.c" );
1476:
1477: switch( latok->retval.t ) {
1478: case TYPEDEF:
1479: case EXTERN:
1480: case STATIC:
1481: case AUTO:
1482: case REGISTER:
1483: case OVERLOAD:
1484: case INLINE:
1485: case FRIEND:
1486: case CONST:
1487: case VOLATILE:
1488: return 1;
1489: default:
1490: return 0;
1491: }
1492: }
1493:
1494: extern int
1495: la_cast()
1496: /*
1497: called in reduction of term_lp to check for ambiguous prefix-style cast
1498: if result is 1, caller inserts DECL_MARKER to force reduction of cast
1499: */
1500: {
1501: // yychar already designates TYPE or TNAME
1502: // LP must start the lookahead queue!
1503: LDB(1,fprintf(stderr,"\n*** la_cast()\n"););
1504: int tk, tk2 = latok->tok;
1505:
1506: for ( ; ; ) {
1507: tk = tk2;
1508: tk2 = lookahead();
1509:
1510: switch( tk ) {
1511: case LP:
1512: if ( tk2 == MUL || tk2 == AND ||
1513: tk2 == TSCOPE || tk2 == MEMPTR )
1514: // T ( * ...
1515: // T ( C ::* ...
1516: continue;
1517: else
1518: // T ( exp )
1519: return 0;
1520: case MUL: case AND:
1521: //if ( tk2 == SCTYPE )
1522: if ( la_sctype( tk2 ) )
1523: // T ( * const ...
1524: // T ( * volatile ...
1525: tk2 = lookahead();
1526: continue;
1527: case MEMPTR:
1528: if ( tk2 == RP ) continue;
1529: break;
1530: case TSCOPE:
1531: if ( tk2 == MUL )
1532: // T ( C :: * ...
1533: continue;
1534: else
1535: // T ( exp )
1536: return 0;
1537: case RP: case LB:
1538: // T (*)()
1539: // T (*[])()
1540: return 1;
1541: }
1542:
1543: return 0;
1544: }
1545: }
1546:
1547: static int
1548: la_decl()
1549: /*
1550: handles ambiguities
1551: type (*x) ()
1552: type (*x) []
1553: at start of arg list / statement
1554: return val == 1 if lookahead finds a declaration
1555: (used for error messages only)
1556: if declaration is "ambiguous" (i.e., can't be recognized with
1557: 1-symbol lookahead), insert DECL_MARKER to force reduction
1558: of "type"
1559: */
1560: {
1561:
1562: // LP must start the lookahead queue!
1563: LDB(1,fprintf(stderr,"\n*** la_decl()\n"););
1564: int tk, tk2 = latok->tok;
1565: int paren = 0;
1566: int ptr = 0;
1567:
1568: for ( ; ; ) {
1569:
1570: tk = tk2;
1571: tk2 = lookahead();
1572:
1573: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
1574: switch( tk ) {
1575: case LP:
1576: if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) {
1577: // T ( * ...
1578: ++paren;
1579: ptr = 1;
1580: continue;
1581: } else
1582: if ( tk2 == MEMPTR ) {
1583: // T ( C ::* ...
1584: return 1;
1585: } else
1586: // possible redundant parens
1587: if ( tk2 == ID && lookahead() == RP ) {
1588: TOK tp = lookahead();
1589: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 );
1590: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl );
1591: if ( tp == SM || tp == CM || tp == ASSIGN )
1592: {
1593: // member initialization list
1594: if ( tp != SM && in_arg_list == 0 ) return 1;
1595: }
1596: else
1597: if ( tp == RP && (bl_level-in_class_decl==0))
1598: return 1;
1599: if ( tp != LP )
1600: return 0;
1601: latok=latok->last; // restore lookahead
1602: ++paren;
1603: continue;
1604: }
1605: else
1606: // T ( exp )
1607: return 0;
1608: case MUL: case AND:
1609: //if ( tk2 == SCTYPE )
1610: if ( la_sctype( tk2 ))
1611: // T ( * const ...
1612: // T ( * volatile ...
1613: return 1;
1614: else {
1615: ptr = 0;
1616: continue;
1617: }
1618: case MEMPTR:
1619: // T ( C :: * ...
1620: return 1;
1621: case TSCOPE:
1622: if ( tk2 == MUL ) //??tk SHOULD HAVE TRANSLATED TO MEMPTR!!
1623: // T ( C :: * ...
1624: return 1;
1625: else if ( ptr )
1626: // T ( exp )
1627: return 0;
1628: else if ( tk2 == ID || tk2 == OPERATOR )
1629: // T ( * C :: id ...
1630: continue;
1631: else
1632: // error
1633: return 0;
1634: }
1635:
1636: break;
1637: }
1638:
1639: if ( tk == RP || tk == LB )
1640: // T (*)()
1641: // T (*[])()
1642: return 1;
1643:
1644: if ( tk != ID && tk != OPERATOR )
1645: // T ( exp )
1646: return 0;
1647:
1648: if ( tk == OPERATOR )
1649: switch ( tk2 ) {
1650: case PLUS: case MINUS: case MUL: case REFMUL:
1651: case AND: case OR: case ER: case SHIFTOP: case EQUOP:
1652: case DIVOP: case RELOP: case ANDAND: case OROR:
1653: case NOT: case COMPL: case ICOP: case ASSIGN:
1654: case ASOP: case NEW: case GNEW: case DELETE:
1655: // OPERATOR oper
1656: tk2 = lookahead();
1657: break;
1658: case LP:
1659: // OPERATOR ()
1660: tk2 = lookahead();
1661: if ( tk2 == RP ) {
1662: tk2 = lookahead();
1663: break;
1664: } else
1665: return 0;
1666: case LB:
1667: // OPERATOR []
1668: tk2 = lookahead();
1669: if ( tk2 == LB ) {
1670: tk2 = lookahead();
1671: break;
1672: } else
1673: return 0;
1674: default: // illegal operator
1675: return 0;
1676: }
1677:
1678: int allow_lp = 1;
1679: int allow_rp = 1;
1680: for ( ; ; ) {
1681: tk = tk2;
1682: tk2 = lookahead();
1683:
1684: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
1685: switch( tk ) {
1686: case LP:
1687: if ( !allow_lp )
1688: // T ( * id [ exp ] ( ...
1689: return 0;
1690:
1691: // Current lookahead will be a decl if
1692: // the next lookahead is an arg decl
1693: if ( tk2 == RP || tk2 == ENUM || tk2==AGGR
1694: || tk2==ELLIPSIS || la_sctype( tk2 ))
1695: // T ( * id ()
1696: // T ( * id ) ()
1697: return 1;
1698:
1699: if ( tk2 == TYPE || tk2 == TNAME ) {
1700: // T ( * id ) ( T2 ...
1701: if ( lookahead() == LP && !la_decl() )
1702: return 0;
1703: return 1;
1704: }
1705:
1706: return 0;
1707: case LB:
1708: if ( tk2 == RB || lookahead() == RB )
1709: // T ( * id [] ...
1710: return 1;
1711: else {
1712: // T ( * id [ exp ] ...
1713: allow_lp = 0;
1714: allow_rp = 1;
1715: while ( lookahead() != RB );
1716: tk2 = lookahead();
1717: continue;
1718: }
1719: case RP:
1720: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren );
1721: if ( !allow_rp || !paren )
1722: // T ( * id ) )
1723: return 0;
1724: // permit redundant parentheses
1725: else
1726: if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN )
1727: return 1;
1728: else
1729: if ( tk2 == RP && (bl_level-in_class_decl == 0))
1730: return 1;
1731: else
1732: {
1733: // T ( * id ) ...
1734: allow_lp = 1;
1735: allow_rp = 0;
1736: --paren;
1737: continue;
1738: }
1739: default:
1740: return 0;
1741: }
1742: }
1743: }
1744:
1745:
1746:
1747: /*
1748: ** PROCESSING OF INLINE MEMBER FUNCTIONS
1749: */
1750: static int la_snarf();
1751:
1752: extern toknode*
1753: save_text()
1754: /*
1755: save text of inline def on q of class
1756: */
1757: {
1758: // Q should contain at least the tokens < FDEF, X ... >
1759: // where X is either LC or COLON (start of ftn)
1760: LDB(2,fprintf(stderr,"save_text()"));
1761: LDB(3,fprintf(stderr,"front: %s",image(front->tok)));
1762: LDB(3,fprintf(stderr,"front->next: %s",image(front->next->tok)));
1763: latok = front->next;
1764: if ( la_snarf() ) {
1765: // append this set of tokens to
1766: // inline tokenq for class
1767: toknode* t = front; // FDEF
1768: if ( ccl->c_funqf == 0 )
1769: ccl->c_funqf = front;
1770: else {
1771: ccl->c_funqr->next = front;
1772: front->last = ccl->c_funqr;
1773: }
1774: ccl->c_funqr = latok;
1775: front = latok->next;
1776: latok->next = 0;
1777: if (front) front->last = 0;
1778: return t;
1779: }
1780: return 0;
1781: }
1782:
1783:
1784: extern void
1785: restore_text()
1786: /*
1787: restore tokens for member inlines onto token q
1788: */
1789: {
1790: LDB(2,fprintf(stderr,"restore_text()"));
1791: if (ccl->c_funqf == 0) // no inlines on Q
1792: return;
1793: LDB(3,fprintf(stderr," Q present: %d,%d",ccl->c_funqf,ccl->c_funqr));
1794: LDB(3,fprintf(stderr," front==%s",image(ccl->c_funqf->tok)));
1795: LDB(3,fprintf(stderr," rear ==%s",image(ccl->c_funqr->tok)));
1796: ccl->c_funqr->next = front;
1797: if (front) front->last = ccl->c_funqr;
1798: front = ccl->c_funqf;
1799: ccl->c_funqf = ccl->c_funqr = 0;
1800: }
1801:
1802:
1803: static void
1804: del_tokens( toknode* marker )
1805: /*
1806: delete tokens from marker to latok, not inclusive
1807: */
1808: {
1809: if ( marker == 0 || marker == latok || marker->next == 0 )
1810: error('i', "bad token queue");
1811:
1812: LDB(2,fprintf(stderr,"del_tokens: %s..%s\n",image(marker->tok),image(latok->tok)));
1813:
1814: register toknode* tt = marker->next;
1815: if ( tt == latok ) return;
1816: marker->next = latok;
1817: latok->last->next = 0;
1818: latok->last = marker;
1819: register toknode* tx = tt;
1820: do {
1821: LDB(3,fprintf(stderr," deleting %s\n",image(tt->tok)));
1822: tx = tx->next;
1823: delete tt;
1824: tt = tx;
1825: } while ( tx );
1826: }
1827:
1828:
1829: static int
1830: la_snarf()
1831: /*
1832: scan function def without processing declarations
1833: */
1834: {
1835: LDB(2,fprintf(stderr,"la_snarf()"));
1836: loc *L = &latok->place;
1837: //DBPLACE(1,L.l,L.f);
1838: int parens = 0;
1839: int paren_error = 0;
1840: toknode* marker = latok;
1841: switch ( latok->tok ) {
1842: default:
1843: error('i', L, "bad token Q snarfing function: %d", latok->tok);
1844: case COLON:
1845: break;
1846: case LC:
1847: --bl_level;
1848: goto eatf;
1849: }
1850: LDB(2,fprintf(stderr,"\"eat\" member initializers"));
1851: for (;;) {
1852: if (latok->next == 0) add_tokens();
1853: switch ( (latok=latok->next)->tok ) {
1854: case LP:
1855: ++parens;
1856: default:
1857: LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
1858: continue;
1859: case RP:
1860: if ( (--parens < 0) && (paren_error++ == 0) )
1861: error(0,&latok->place,"unbalanced ()");
1862: continue;
1863: case LC:
1864: case RC:
1865: if ( parens <= 0 )
1866: goto eatf;
1867: continue;
1868: case SM:
1869: if ( parens <= 0 ) {
1870: error(0, L, "illegal bit field");
1871: del_tokens( front );
1872: delete front;
1873: front = latok;
1874: front->last = 0;
1875: return 0;
1876: }
1877: continue;
1878: case EOFTOK:
1879: error('i',&latok->place,"unexpected end of file");
1880: } // switch
1881: } // for
1882:
1883: eatf:
1884: int level = 1;
1885: for (;;) {
1886: if (latok->next == 0) add_tokens();
1887: switch ( (latok=latok->next)->tok ) {
1888: case LC:
1889: ++level;
1890: default:
1891: LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
1892: continue;
1893: case RC:
1894: LDB(3,fprintf(stderr,"...RC"));
1895: if (--level <= 0) {
1896: if (level < 0) {
1897: error(0,&latok->place,"unexpected '}'");
1898: goto bad;
1899: }
1900: return 1;
1901: }
1902: break;
1903: case EOFTOK:
1904: error('e', &latok->place, "unbalanced {}");
1905: goto bad;
1906: } // switch
1907: } // for
1908: bad:
1909: del_tokens( marker );
1910: marker->tok = SM;
1911: return 0;
1912: }
1913:
1914: Pname check_for_nested( Pname nstd, TOK lasttk, YYSTYPE lastval, TOK tk2)
1915: {
1916: // error('d',"nstd: %n must_be_id 0 tk2: %k lasttk: %d",nstd,tk2,lasttk);
1917: TOK tk = ID;
1918: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
1919:
1920: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
1921: TOK ntk;
1922: bit ok = 0;
1923: Ptype tt = return_nstd_local_type(nn,ntk);
1924: Pclass cl = tt->in_class;
1925: if ( xcl ) {
1926: if (xcl==cl || xcl->has_base(cl))
1927: ok++;
1928: else {
1929: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
1930: if ( eccl == cl ) { ok++; break; }
1931: }
1932: }
1933:
1934: if (nn == nstd)
1935: {
1936: if ( ((in_arg_list || lasttk==LP) && // foo(nestedX
1937: (tk2==CM || tk2==ASSIGN || tk2==RP))
1938: || (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
1939: || (tk2 == MUL || tk2==AND)
1940: || (lasttk==LP && tk2==RP)
1941: || (lasttk==TSCOPE && lastval.pn == nn)
1942: || (lasttk==COMPL && dtor_seen == nn)
1943: || (lasttk==TYPE && lastval.t == TYPEDEF)
1944: || lasttk == NEW || in_sizeof )
1945: {
1946: if ( nstd->n_tbl_list == 0 ) { // only one: ok
1947: break;
1948: } else {
1949: if (lasttk != TSCOPE && !ok){
1950: error("ambiguous nested type %s, use X::%s",nn->string,nn->string);
1951: error( 'i', "cannot recover from previous errors" );
1952: }
1953: }
1954: }
1955: }
1956: if ( nn->n_key != NESTED ) continue;
1957: if (xcl && strcmp(xcl->string,cl->string) == 0) break;
1958: } // end: for nn = nstd
1959: return nn;
1960: }
1961:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.