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