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