|
|
1.1 root 1: /*ident "@(#)ctrans:src/gram.y 1.6.5.35" */
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: gram.y:
11:
12: This is the C++ syntax analyser.
13:
14: Syntax extensions for error handling:
15: nested functions
16: any expression can be empty
17: any expression can be a constant_expression
18:
19: A call to error() does not change the parser's state
20:
21: ***************************************************************************/
22:
23: %{
24: #include "cfront.h"
25: #include "size.h"
26: // include tqueue.h after YYSTYPE is defined ...
27:
28: #define YYMAXDEPTH 600
29:
30: #ifdef DBG
31: #ifndef YYDEBUG
32: #define YYDEBUG 1
33: #endif
34: #endif
35:
36: static init_seen = 0;
37: static cdi = 0;
38: static Pnlist cd = 0, cd_vec[BLMAX];
39: static char stmt_seen = 0, stmt_vec[BLMAX];
40:
41: //local class
42: static Plist tn_vec[BLMAX], lcl_tn_vec[BLMAX], lcl_blk_vec[BLMAX];
43: extern void local_restore();
44: extern void local_name();
45:
46: //nested class
47: static Plist nested_tn_vec[BLMAX], nested_type_vec[BLMAX];
48: extern void nested_restore();
49: extern char *class_typedef;
50:
51: static Pname err_name = 0;
52:
53: // fcts put into norm2.c just to get them out of gram.y
54: void sig_name(Pname);
55: Ptype tok_to_type(TOK);
56: void memptrdcl(Pname, Pname, Ptype, Pname);
57:
58: static Pptr doptr(TOK p, TOK t)
59: {
60: Pptr r = new ptr(p,0);
61: switch (t) {
62: case CONST:
63: r->rdo = 1;
64: // if (p == RPTR) error('w',"redundant `const' after &");
65: break;
66: case VOLATILE:
67: error('w',"\"volatile\" not implemented (ignored)");
68: break;
69: default:
70: error("syntax error: *%k",t);
71: }
72: return r;
73: }
74:
75: static Pbcl dobase(TOK pr, Pname n, TOK v = 0)
76: {
77: Pbcl b = new basecl(0,0);
78:
79: if (pr == PROTECTED) {
80: pr = PUBLIC;
81: error("protectedBC");
82: }
83: b->ppp = pr; // save protection indicator
84:
85: if (n) {
86: if (n->base != TNAME) {
87: error("BN%n not aTN",n);
88: return 0;
89: }
90:
91: Pbase bt = Pbase(n->tp);
92: while (bt->base == TYPE) bt = Pbase(bt->b_name->tp);
93:
94: if (bt->base != COBJ) {
95: error("BN%n not aCN",n);
96: return 0;
97: }
98:
99: if (v) {
100: if (v != VIRTUAL) error("syntax error:%k inBCD",v);
101: b->base = VIRTUAL;
102: }
103: else
104: b->base = NAME;
105:
106: b->bclass = Pclass(bt->b_name->tp);
107: }
108:
109: return b;
110: }
111:
112:
113: #define Ndata(a,b) b->normalize(Pbase(a),0,0)
114: #define Ncast(a,b) b->normalize(Pbase(a),0,1)
115: #define Nfct(a,b,c) b->normalize(Pbase(a),Pblock(c),0)
116: #define Ncopy(n) (n->base==TNAME)?new name(n->string):n
117:
118: #define Finit(p) Pfct(p)->f_init
119: #define Fargdcl(p,q,r) Pfct(p)->argdcl(q,r)
120: #define Freturns(p) Pfct(p)->returns
121: #define Vtype(v) Pvec(v)->typ
122: #define Ptyp(p) Pptr(p)->typ
123:
124: /* avoid redefinitions */
125: #undef EOFTOK
126: #undef ASM
127: #undef BREAK
128: #undef CASE
129: #undef CONTINUE
130: #undef DEFAULT
131: #undef DELETE
132: #undef DO
133: #undef ELSE
134: #undef ENUM
135: #undef FOR
136: #undef FORTRAN
137: #undef GOTO
138: #undef IF
139: #undef NEW
140: #undef OPERATOR
141: #undef RETURN
142: #undef SIZEOF
143: #undef SWITCH
144: #undef THIS
145: #undef WHILE
146: #undef LP
147: #undef RP
148: #undef LB
149: #undef RB
150: #undef REF
151: #undef DOT
152: #undef NOT
153: #undef COMPL
154: #undef MUL
155: #undef AND
156: #undef PLUS
157: #undef MINUS
158: #undef ER
159: #undef OR
160: #undef ANDAND
161: #undef OROR
162: #undef QUEST
163: #undef COLON
164: #undef ASSIGN
165: #undef CM
166: #undef SM
167: #undef LC
168: #undef RC
169: #undef ID
170: #undef STRING
171: #undef ICON
172: #undef FCON
173: #undef CCON
174: #undef ZERO
175: #undef ASOP
176: #undef RELOP
177: #undef EQUOP
178: #undef DIVOP
179: #undef SHIFTOP
180: #undef ICOP
181: #undef TYPE
182: #undef TNAME
183: #undef EMPTY
184: #undef NO_ID
185: #undef NO_EXPR
186: #undef FDEF
187: #undef ELLIPSIS
188: #undef AGGR
189: #undef MEM
190: #undef MEMPTR
191: #undef PR
192: #undef TSCOPE
193: #undef DECL_MARKER
194: #undef REFMUL
195: #undef LDOUBLE
196: #undef LINKAGE
197: #undef LOCAL
198: #undef NESTED
199: %}
200:
201: %union {
202: char* s;
203: TOK t;
204: int i;
205: loc l;
206: Pname pn;
207: Ptype pt;
208: Pexpr pe;
209: Pstmt ps;
210: Pbase pb;
211: Pnlist nl;
212: Pslist sl;
213: Pelist el;
214: Pbcl pbc;
215: Pptr pp;
216: PP p; // fudge: pointer to all class node objects
217: Plist pl;
218: toknode* q; // token queue
219: }
220: %{
221: #include "tqueue.h"
222: extern YYSTYPE yylval, yyval;
223: extern int yyparse();
224:
225: // in_typedef should allow for nested in_typedef
226: extern int declTag; // !1: inline, virtual mod permitted
227: int in_sizeof = 0;
228: Ptype in_typedef = 0; // catch redefinition of TNAME
229: Pname in_tag = 0; // handle complex typedefs: int (*)()
230: extern int defer_check; // redefinition typedef check delay
231: Pname curr_scope;
232:
233: extern int must_be_id; // !0, TNAME => ID, i.e., int X
234: int DECL_TYPE = 0; // lalex() wants this set for global x(*fp)()
235: int in_arg_list=0; // !0 when parsing argument list
236: static int in_binit_list=0;
237: int in_class_decl=0; // !0 when processing class definition
238: int parsing_class_members=0; // !0 when parsing class def but not member function body
239: int in_mem_fct=0; // !0 when parsing member function definition
240:
241: #define yylex lalex
242: #define NEXTTOK() ( (yychar==-1) ? (yychar=yylex(),yychar) : yychar )
243: #define EXPECT_ID() must_be_id = 1
244: #define NOT_EXPECT_ID() must_be_id = 0
245:
246: Pname syn()
247: {
248: ll:
249: switch (yyparse()) {
250: case 0: return 0; // EOF
251: case 1: goto ll; // no action needed
252: default: return yyval.pn;
253: }
254: }
255:
256: %}
257: /*
258: the token definitions are copied from token.h,
259: and all %token replaced by %token
260: */
261: /* keywords in alphabetical order */
262: %token EOFTOK 0
263: %token ASM 1
264: %token BREAK 3
265: %token CASE 4
266: %token CONTINUE 7
267: %token DEFAULT 8
268: %token DELETE 9
269: %token DO 10
270: %token ELSE 12
271: %token ENUM 13
272: %token FOR 16
273: %token FORTRAN 17
274: %token GOTO 19
275: %token IF 20
276: %token NEW 23
277: %token OPERATOR 24
278: %token RETURN 28
279: %token SIZEOF 30
280: %token SWITCH 33
281: %token THIS 34
282: %token WHILE 39
283:
284: /* operators in priority order (sort of) */
285: %token LP 40
286: %token RP 41
287: %token LB 42
288: %token RB 43
289: %token REF 44
290: %token DOT 45
291: %token NOT 46
292: %token COMPL 47
293: %token MUL 50
294: %token AND 52
295: %token PLUS 54
296: %token MINUS 55
297: %token ER 64
298: %token OR 65
299: %token ANDAND 66
300: %token OROR 67
301: %token QUEST 68
302: %token COLON 69
303: %token ASSIGN 70
304: %token CM 71
305: %token SM 72
306: %token LC 73
307: %token RC 74
308: %token MEMPTR 173
309:
310: /* constants etc. */
311: %token ID 80
312: %token STRING 81
313: %token ICON 82
314: %token FCON 83
315: %token CCON 84
316:
317: %token ZERO 86
318:
319: /* groups of tokens */
320: %token ASOP 90 /* op= */
321: %token RELOP 91 /* LE GE LT GT */
322: %token EQUOP 92 /* EQ NE */
323: %token DIVOP 93 /* DIV MOD */
324: %token SHIFTOP 94 /* LS RS */
325: %token ICOP 95 /* INCR DECR */
326:
327: %token TYPE 97 /* INT FLOAT CHAR DOUBLE
328: REGISTER STATIC EXTERN AUTO
329: CONST INLINE VIRTUAL FRIEND
330: LONG SHORT UNSIGNED OVERLOAD
331: TYPEDEF */
332: %token TNAME 123
333: %token EMPTY 124
334: %token NO_ID 125
335: %token NO_EXPR 126
336: %token FDEF 127
337: %token ELLIPSIS 155 /* ... */
338: %token AGGR 156 /* CLASS STRUCT UNION */
339: %token MEM 160 /* :: */
340: %token PR 175 /* PUBLIC PRIVATE PROTECTED */
341: %token TSCOPE 178 /* TNAME :: */
342: %token DECL_MARKER 179
343: %token REFMUL 180 /* ->*, .* */
344: %token LDOUBLE 181
345: %token LINKAGE 182 /* extern "asdf" */
346: %token LOCAL 183 /* local class */
347: %token NESTED 190 /* nested class */
348:
349: %type <p> external_def fct_dcl fct_def att_fct_def arg_dcl_list
350: base_init init_list binit
351: data_dcl ext_def vec ptr
352: type tp enum_dcl moe_list
353: moe
354: tag enumtag class_head class_dcl cl_mem_list
355: cl_mem dl decl_list
356: fname decl initializer stmt_list
357: caselab_stmt caselablist
358: block statement simple ex_list elist e ee term prim
359: term_elist
360: cast_decl cast_type c_decl c_type c_tp
361: arg_decl at arg_type arg_list arg_type_list
362: new_decl new_type
363: condition
364: TSCOPE tscope TNAME tn_list MEMPTR
365: qualified_tname
366: %type <l> LC RC SWITCH CASE DEFAULT FOR IF DO WHILE GOTO RETURN DELETE
367: BREAK CONTINUE
368: %type <t> oper ellipsis_opt
369: EQUOP DIVOP SHIFTOP ICOP RELOP ASOP
370: ANDAND OROR PLUS MINUS MUL ASSIGN OR ER AND
371: LP LB NOT COMPL AGGR
372: TYPE PR REFMUL
373: %type <s> CCON ZERO ICON FCON STRING LINKAGE
374: %type <pn> ID FDEF inline_fct_def
375: %type <pbc> base_list base_unit_list base_unit
376: %type <q> EMPTY
377: %type <i> fct_attributes
378: %type <pl> arg_lp
379:
380: %left EMPTY
381: %left NO_ID
382: %left RC LC ID BREAK CONTINUE RETURN GOTO DELETE DO IF WHILE FOR CASE DEFAULT
383: AGGR ENUM TYPE TNAME TSCOPE
384: %left NO_EXPR
385:
386: %left CM
387: %right ASOP ASSIGN
388: %right QUEST COLON
389: %left OROR
390: %left ANDAND
391: %left OR
392: %left ER
393: %left AND
394: %left EQUOP
395: %left RELOP
396: %left SHIFTOP
397: %left PLUS MINUS
398: %left MUL DIVOP MEMPTR
399: %left REFMUL
400: %right NOT COMPL NEW
401: %right ICOP SIZEOF
402: %left LB LP DOT REF MEM
403:
404: %start ext_def
405:
406: %%
407: /*
408: this parser handles declarations one by one,
409: NOT a complete .c file
410: */
411:
412:
413: /************** DECLARATIONS in the outermost scope: returns Pname (in yylval) ***/
414:
415: ext_def : external_def { return 2; }
416: | SM { return 1; }
417: | EOFTOK { return 0; }
418: | LINKAGE LC
419: {
420: set_linkage($<s>1);
421: bl_level--;
422: return 1;
423: }
424: | RC
425: {
426: set_linkage(0);
427: bl_level++;
428: return 1;
429: }
430: ;
431:
432: external_def : data_dcl
433: {
434: /* if function declartion with arguments
435: * need to make sure modified_tn is traversed */
436: if ( $<pn>1 != 0
437: && $<pn>1->tp->base == FCT
438: && Pfct($<pn>1->tp)->nargs !=0 )
439: goto mod;
440: else {
441: modified_tn = 0;
442: curr_scope = 0;
443: if ($<pn>1==0) $<i>$ = 1;
444: }
445: }
446: | att_fct_def
447: { goto mod; }
448: | fct_def
449: { goto mod; }
450: | fct_dcl
451: { mod: if (modified_tn) {
452: restore();
453: modified_tn = 0;
454: }
455: local_blk = 0;
456: curr_scope = 0;
457: if (local_tn) {
458: local_restore();
459: local_tn = 0;
460: }
461:
462: if (nested_tn) { // x::f(){}
463: nested_restore();
464: nested_tn = 0;
465: nested_type = 0;
466: }
467: }
468: | ASM LP STRING RP SM
469: { Pname n = new name(make_name('A'));
470: n->tp = new basetype(ASM,0);
471: Pbase(n->tp)->b_name = Pname($<s>3);
472: $$ = n;
473: }
474: ;
475:
476: fct_dcl : decl ASSIGN initializer SM
477: {
478: err_name = $<pn>1;
479: if(err_name) err_name->n_initializer = $<pe>3;
480: goto fix;
481: }
482: | decl SM
483: {
484: Ptype t;
485: err_name = $<pn>1;
486: fix:
487: if (err_name == 0) {
488: error("syntax error:TX");
489: $$ = Ndata(defa_type,err_name);
490: }
491: else if ((t=err_name->tp) == 0) {
492: error("TX for%n",err_name);
493: $$ = Ndata(defa_type,err_name);
494: }
495: else if (t->base==FCT) {
496: if (Pfct(t)->returns==0)
497: $$ = Nfct(defa_type,err_name,0);
498: else
499: $$ = Ndata(0,err_name);
500: }
501: else {
502: error("syntax error:TX for%k%n",t->base,err_name);
503: $$ = Ndata(defa_type,err_name);
504: }
505: }
506: ;
507:
508: att_fct_def : type decl arg_dcl_list check_inline base_init block
509: { Pname n = Nfct($1,$<pn>2,$6);
510: Fargdcl(n->tp,name_unlist($<nl>3),n);
511: Finit(n->tp) = $<pn>5;
512: $$ = n;
513: NOT_EXPECT_ID();
514: }
515: | type decl arg_dcl_list check_inline EMPTY
516: {
517: Pname n = Nfct($1,$<pn>2,dummy);
518: Fargdcl(n->tp,name_unlist($<nl>3),n);
519: $<q>5->retval.pn = n;
520: $$ = n;
521: NOT_EXPECT_ID();
522: }
523: | type decl arg_dcl_list check_inline NO_ID /*syntax error*/
524: {
525: error(&$<pn>2->where,"syntax error -- did you forget a ';'?");
526: Pname n = Nfct($1,$<pn>2,0);
527: $$ = n;
528: NOT_EXPECT_ID();
529: }
530: ;
531:
532: fct_def : decl arg_dcl_list check_inline base_init block
533: { Pname n = Nfct(defa_type,$<pn>1,$5);
534: Fargdcl(n->tp,name_unlist($<nl>2),n);
535: if ( $<pn>4 && $<pn>4->n_list &&
536: ccl && ccl->csu == UNION )
537: error( "multiple initializers in unionK %s::%n", $<pn>1->string, $<pn>1 );
538: Finit(n->tp) = $<pn>4;
539: $$ = n;
540: NOT_EXPECT_ID();
541: }
542: | decl arg_dcl_list check_inline EMPTY
543: {
544: Pname n = Nfct(defa_type,$<pn>1,dummy);
545: Fargdcl(n->tp,name_unlist($<nl>2),n);
546: $<q>4->retval.pn = n;
547: $$ = n;
548: NOT_EXPECT_ID();
549: }
550: | decl arg_dcl_list check_inline NO_ID /*syntax error*/
551: {
552: error(&$<pn>1->where,"badD of%n -- did you forget a ';'?",$<pn>1);
553: Pname n = Nfct(defa_type,$<pn>1,0);
554: $$ = n;
555: NOT_EXPECT_ID();
556: }
557: ;
558:
559: inline_fct_def : FDEF { arg_redec($<pn>1); }
560: base_init block
561: {
562: Finit($1->tp) = $<pn>3;
563: Pfct($1->tp)->body = Pblock($4);
564: $$ = $1;
565: NOT_EXPECT_ID();
566: }
567: ;
568:
569:
570: check_inline : /* empty */
571: {
572: // if parsing implicit inline def, save body
573: // of function for parsing after class def
574: switch ( NEXTTOK() ) {
575: case LC: case COLON:
576: if ( in_class_decl ) {
577: // mem or friend inline def
578: // save text of mem_init & ftn
579: la_backup(yychar,yylval);
580: // yylval used as dummy...
581: la_backup(FDEF, yylval);
582: if ( yylval.q = save_text() )
583: yychar = EMPTY;
584: else { // syntax error
585: // just parse in place
586: yylex(); // FDEF
587: yychar = yylex();
588: }
589: } // if in_class_decl
590: break;
591: default:
592: la_backup(yychar,yylval);
593: yychar = NO_ID; // 'graceful' recovery
594: break;
595: }
596: }
597: ;
598:
599: base_init : COLON { ++in_binit_list; } init_list
600: {
601: $$ = $3;
602: in_arg_list = 0;
603: --in_binit_list;
604: }
605: | %prec EMPTY
606: { $$ = 0; }
607: ;
608:
609: init_list : binit
610: { $$ = $1; }
611: | init_list CM binit
612: { $<pn>$ = $<pn>3; $<pn>$->n_list = $<pn>1; }
613: ;
614:
615: binit : LP elist RP
616: {
617: $<pn>$ = new name;
618: $<pn>$->n_initializer = $<pe>2;
619: }
620: | tag LP elist RP
621: {
622: Pname n = Ncopy($<pn>1);
623: n->base = $<pn>1->base;
624: n->tp = $<pn>1->tp;
625: n->n_initializer = $<pe>3;
626: $<pn>$ = n;
627: }
628:
629: /*
630: | NEW LP elist RP
631: { Pname n = new name;
632: n->base = NEW;
633: n->n_initializer = $<pe>3;
634: $<pn>$ = n;
635: }
636: */
637: ;
638:
639:
640:
641:
642: /*************** declarations: returns Pname ********************/
643:
644: arg_dcl_list : arg_dcl_list data_dcl
645: { if ($<pn>2 == 0)
646: error("badAD");
647: else if ($<pn>2->tp->base == FCT)
648: error("FD inAL (%n)",$<pn>2);
649: else if ($1)
650: $<nl>1->add_list($<pn>2);
651: else
652: $<nl>$ = new nlist($<pn>2);
653: }
654: | %prec EMPTY
655: {
656: $$ = 0;
657: }
658: ;
659:
660: dl : decl
661: | ID COLON e %prec CM
662: { $$ = $<pn>1;
663: $<pn>$->tp = new basetype(FIELD,$<pn>3);
664: }
665: | COLON e %prec CM
666: { $$ = new name;
667: $<pn>$->tp = new basetype(FIELD,$<pn>2);
668: }
669: | decl ASSIGN initializer
670: { Pexpr e = $<pe>3;
671: if (e == dummy) error("emptyIr");
672: $<pn>1->n_initializer = e;
673: init_seen = 0;
674: }
675: ;
676:
677: decl_list : dl
678: {
679: if ($1) $<nl>$ = new nlist($<pn>1);
680: if ( NEXTTOK() == CM && la_look() == TNAME )
681: EXPECT_ID();
682: }
683: | decl_list CM dl
684: { if ($1)
685: if ($3)
686: $<nl>1->add($<pn>3);
687: else
688: error("DL syntax");
689: else {
690: if ($3) $<nl>$ = new nlist($<pn>3);
691: error("DL syntax");
692: }
693: if ( NEXTTOK() == CM && la_look() == TNAME )
694: EXPECT_ID();
695: }
696: ;
697:
698: data_dcl : type decl_list SM
699: {
700: extern int co_hack;
701: co_hack = 1;
702: /*$$ = Ndata($1,name_unlist($<nl>2));*/
703: Pname n = Ndata($1,name_unlist($<nl>2));
704: if ( in_typedef && in_tag ) {
705: if ( n->tp->check( in_tag->tp, 0 ))
706: error("%nredefined: previous: %t now: %t", in_tag, in_tag->tp, n->tp );
707: }
708: in_typedef = 0;
709: class_typedef = 0;
710: in_tag = 0;
711: co_hack = 0;
712: DECL_TYPE = 0;
713: $$ = n;
714: }
715: | type SM
716: {
717: $$ = $<pb>1->aggr();
718: in_typedef = 0;
719: class_typedef = 0;
720: in_tag = 0;
721: DECL_TYPE = 0;
722: }
723:
724: ;
725:
726: tp : TYPE
727: {
728: $$ = new basetype($<t>1,0);
729: if ( $<t>1 == TYPEDEF ) in_typedef = $<pt>$;
730: if (DECL_TYPE == -1) DECL_TYPE = 0;
731: }
732: | LINKAGE
733: { $$ = new basetype(EXTERN,0);
734: $<pb>$->b_linkage = $<s>1;
735: if (DECL_TYPE == -1) DECL_TYPE = 0;
736: }
737: | qualified_tname
738: {
739: $$ = new basetype(TYPE,$<pn>1);
740: if (DECL_TYPE == -1) DECL_TYPE = 0;
741: }
742: /*XXX*/ | tn_list DECL_MARKER
743: { // modified tn_list TNAME
744: $$ = new basetype(TYPE,$<pn>2);
745: //xxx qualifier currently ignored...
746: if (DECL_TYPE == -1) DECL_TYPE = 0;
747: }
748: | class_dcl
749: | enum_dcl
750: | DECL_MARKER
751: {
752: if (DECL_TYPE == TNAME)
753: $$ = new basetype(TYPE,$<pn>1);
754: // else if (DECL_TYPE == TSCOPE)
755: // $$ = 0;
756: else
757: if (DECL_TYPE == 0 &&
758: $<p>1->base == TNAME)
759: $$ = new basetype(TYPE,$<pn>1);
760: else
761: $$ = new basetype($<t>1,0);
762: DECL_TYPE = -1;
763: }
764: ;
765:
766: type : tp
767: | type TYPE
768: {
769: if ( DECL_TYPE != -1 )
770: $$ = $<pb>1->type_adj($<t>2);
771: DECL_TYPE = 0;
772: }
773: | type qualified_tname
774: {
775: //error('d',"decl_type: %d $1: %t $2: %n",DECL_TYPE,$<pb>1,$<pn>2);
776: if ( DECL_TYPE != -1 )
777: $$ = $<pb>1->name_adj($<pn>2);
778: /*XXX*/ else if($<pb>1==0) $$=new basetype(TYPE,$<pn>2);
779: DECL_TYPE = 0;
780: }
781: | type class_dcl { $$ = $<pb>1->base_adj($<pb>2); }
782: | type enum_dcl { $$ = $<pb>1->base_adj($<pb>2); }
783: | type DECL_MARKER
784: {
785: if (DECL_TYPE == TYPE)
786: $$ = $<pb>1->type_adj($<t>2);
787: /*XXX*/ else if (DECL_TYPE == TSCOPE) {
788: /*XXX*/ error('i',"type decl_marker(tscope)");
789: /*XXX*/ // $$ = $1;//ignore(?)
790: /*XXX*/ }
791: else
792: $$ = $<pb>1->name_adj($<pn>2);
793: DECL_TYPE = -1;
794: }
795: ;
796:
797: /***************** aggregate: returns Pname *****************/
798:
799: enumtag : tag
800: { enumcheck:
801: Ptype tx = $<pn>1->tp;
802: $$ = $1;
803: if ( tx->base == TYPE ) {
804: $$ = Pbase(tx)->b_name;
805: tx = $<pn>$->tp;
806: if ( tx->base != EOBJ
807: || strcmp($<pn>$->string,$<pn>1->string)
808: )
809: error("%n of type%t redeclared as enum.",$<pn>1,tx);
810: } else if ( tx->base != EOBJ )
811: error("%n of type%t redeclared as enum",$<pn>1,tx);
812: }
813: | DECL_MARKER { goto enumcheck; }
814: ;
815:
816: enum_dcl : ENUM LC moe_list RC { $$ = end_enum(0,$<pn>3); }
817: | ENUM enumtag LC moe_list RC { $$ = end_enum($<pn>2,$<pn>4); }
818: | ENUM enumtag { $<pb>$ = (Pbase)$<pn>2->tp; }
819: ;
820:
821: moe_list : moe
822: { if ($1) $<nl>$ = new nlist($<pn>1); }
823: | moe_list CM moe
824: { if( $3)
825: if ($1)
826: $<nl>1->add($<pn>3);
827: else
828: $<nl>$ = new nlist($<pn>3);
829: }
830: ;
831:
832: moe : ID
833: { $$ = $<pn>1; $<pn>$->tp = moe_type; }
834: | ID ASSIGN e
835: { $$ = $<pn>1;
836: $<pn>$->tp = moe_type;
837: $<pn>$->n_initializer = $<pe>3;
838: }
839: | /* empty: handle trailing CM: enum e { a,b, }; */
840: { $$ = 0; }
841: ;
842:
843: class_dcl : class_head cl_mem_list RC
844: { parsing_class_members = 0;
845: switch ( NEXTTOK() ) {
846: case TYPE: case AGGR: case ENUM: case EOFTOK:
847: error("`;' or declaratorX afterCD");
848: la_backup(yychar,yylval);
849: yychar = SM;
850: break;
851: }
852: la_backup(yychar,yylval);
853: yychar = -1;
854: restore_text();
855: ++bl_level; // scope weirdness!
856: ++in_mem_fct;
857: }
858: inline_mem_defs
859: {
860: --in_mem_fct;
861: --bl_level; // scope weirdness!
862: if ( yychar == ID ) {
863: // (yuk!) adjust lex level
864: --yylval.pn->lex_level;
865: }
866: ccl->mem_list = name_unlist($<nl>2);
867: if ( --in_class_decl ) // nested class
868: // continue to parse enclosing class
869: parsing_class_members = 1;
870: ccl->nest_list = nested_type;
871: if ( nested_tn ) nested_restore();
872: nested_type = nested_type_vec[in_class_decl];
873: nested_tn = nested_tn_vec[in_class_decl];
874: end_cl();
875: declTag = 1;
876: }
877: | AGGR tag
878: { aggrcheck:
879: $<pb>$ = (Pbase)$<pn>2->tp;
880: if ( $$->base == TYPE ) {
881: Pname nx = $<pb>$->b_name;
882: $<pb>$ = (Pbase)nx->tp;
883: if ( $$->base != COBJ
884: || strcmp(nx->string,$<pn>2->string)
885: )
886: error("%n of type%t redeclared as%k.",$<pn>2,$<pb>$,$<t>1);
887: } else if ( $$->base != COBJ )
888: error("%n of type%t redeclared as%k",$<pn>2,$<pb>$,$<t>1);
889: check_tag();
890: }
891:
892: | AGGR DECL_MARKER
893: {
894: goto aggrcheck;
895: }
896: ;
897:
898:
899: inline_mem_defs : /* empty */
900: | inline_mem_defs inline_fct_def
901: ;
902:
903: base_list : COLON base_unit_list { $$ = $2; }
904: | %prec EMPTY { $$ = 0; }
905: ;
906:
907: base_unit_list : base_unit
908: | base_unit_list CM base_unit
909: { if ($3) { $$ = $3; $<pbc>$->next = $1; } }
910: ;
911:
912: base_unit : tag { $$ = dobase(0,$<pn>1); }
913: | PR tag { $$ = dobase($<t>1,$<pn>2); }
914: | TYPE tag { $$ = dobase(0,$<pn>2,$<t>1); }
915: | PR TYPE tag { $$ = dobase($<t>1,$<pn>3,$<t>2); }
916: | TYPE PR tag { $$ = dobase($<t>2,$<pn>3,$<t>1); }
917: ;
918:
919: class_head : AGGR LC
920: { parsing_class_members = 1;
921: $$ = start_cl($<t>1,0,0);
922: nested_tn_vec[in_class_decl] = nested_tn;
923: nested_type_vec[in_class_decl++] = nested_type;
924: nested_tn = nested_type = 0;
925: }
926:
927: | AGGR tag base_list LC
928: { parsing_class_members = 1;
929: $$ = start_cl($<t>1,$<pn>2,$<pbc>3);
930: nested_tn_vec[in_class_decl] = nested_tn;
931: nested_type_vec[in_class_decl++] = nested_type;
932: nested_tn = nested_type = 0;
933: }
934: ;
935:
936: tag : ID { $$ = $1; }
937: | qualified_tname { $$=$1; }
938: ;
939:
940: cl_mem_list : cl_mem_list cl_mem
941: {
942: if ($2) {
943: if ($1)
944: $<nl>1->add_list($<pn>2);
945: else
946: $<nl>$ = new nlist($<pn>2);
947: }
948: }
949: | %prec EMPTY
950: { $$ = 0; }
951: ;
952:
953: cl_mem : data_dcl
954: | att_fct_def SM
955: | fct_def SM
956: | fct_def
957: | att_fct_def
958: | fct_dcl
959: | PR COLON
960: { $$ = new name;
961: $<pn>$->base = $<t>1;
962: }
963: /*XXX | tn_list TNAME SM
964: * { Pname n = Ncopy($<pn>2);
965: * n->n_qualifier = $<pn>1;
966: * n->base = PR;
967: * $$ = n;
968: * }
969: */ | tn_list fname SM
970: { Pname n = Ncopy($<pn>2);
971: if (n->n_oper == TYPE) {
972: error('s',"visibilityD for conversion operator");
973: // n->tp = Ptype(n->n_initializer);
974: n->tp = Ptype(n->cond);
975: n->cond = 0;
976: // n->n_initializer = 0;
977: n->n_oper = 0;
978: sig_name(n);
979: }
980: n->n_qualifier = $<pn>1;
981: n->base = PR;
982: $$ = n;
983: }
984: ;
985:
986: /************* declarators: returns Pname **********************/
987: /* a ``decl'' is used for function and data declarations,
988: and for member declarations
989: (it has a name)
990: an ``arg_decl'' is used for argument declarations
991: (it may or may not have a name)
992: an ``cast_decl'' is used for casts
993: (it does not have a name)
994: a ``new_decl'' is used for type specifiers for the NEW operator
995: (it does not have a name, and PtoF and PtoV cannot be expressed)
996: */
997:
998: fname : ID
999: { $$ = $<pn>1; }
1000: | COMPL TNAME /* qualified_tname? */
1001: { $$ = Ncopy($<pn>2);
1002: $<pn>$->n_oper = DTOR;
1003: }
1004: | OPERATOR oper
1005: { $$ = new name(oper_name($2));
1006: $<pn>$->n_oper = $<t>2;
1007: }
1008: | OPERATOR c_type
1009: { Pname n = $<pn>2;
1010: n->string = "_type";
1011: n->n_oper = TYPE;
1012: n->cond = Pexpr(n->tp);
1013: // n->n_initializer = Pexpr(n->tp);
1014: n->tp = 0;
1015: $$ = n;
1016: }
1017: ;
1018:
1019: oper : PLUS
1020: | MINUS
1021: | MUL
1022: | AND
1023: | OR
1024: | ER
1025: | SHIFTOP
1026: | EQUOP
1027: | DIVOP
1028: | RELOP
1029: | ANDAND
1030: | OROR
1031: | LP RP { $$ = CALL; }
1032: | LB RB { $$ = DEREF; }
1033: | NOT
1034: | COMPL
1035: | ICOP
1036: | ASOP
1037: | ASSIGN
1038: | NEW { $$ = NEW; }
1039: | DELETE { $$ = DELETE; }
1040: | REF { $$ = REF; }
1041: | CM { $$ = CM; }
1042: | REFMUL { $$ = REFMUL;
1043: if ($<t>1 == DOT) error(".* cannot be overloaded");
1044: }
1045: ;
1046:
1047: tn_list : tscope
1048: /*XXX*/ { if ( $<pn>1 != sta_name ) {
1049: // error('d',"tn_list: tscope: pn1: %s", $<pn>1->string);
1050: Ptype t = $<pn>1->tp;
1051: while ( t->base == TYPE )
1052: t = Pbase(t)->b_name->tp;
1053: Pname n = Pbase(t)->b_name;
1054: if (NEXTTOK() == TNAME
1055: && strcmp(n->string,yylval.pn->string)==0){
1056: // ctor -- change to ID to avoid
1057: // parsing as type spec
1058: yychar = ID;
1059: yylval.pn = Ncopy(yylval.pn);
1060: yylval.pn->n_oper = TNAME;
1061: }
1062: }
1063: $<pn>$ = $<pn>1;
1064: }
1065: /* YYY | tn_list tscope { $<pn>$ = $<pn>1; } */
1066: | tn_list tscope { error('s', "CNs do not nest, use typedef x::y y_in_x"); };
1067: /*XXX | tn_list ID DOT { error("CNs do not nest"); } */
1068: ;
1069:
1070: qualified_tname : tn_list TNAME
1071: { $<pn>$ = $<pn>2;
1072: //xxx qualifier currently ignored...
1073: // $<pn>$ = Ncopy( $<pn>2 );
1074: // $<pn>$->n_oper = TNAME;
1075: // $<pn>$->n_qualifier = $<pn>1;
1076: }
1077: | TNAME
1078: { $<pn>$ = $<pn>1;
1079: // $<pn>$ = Ncopy( $<pn>1 );
1080: // $<pn>$->n_oper = TNAME;
1081: }
1082: ;
1083:
1084: fct_attributes : /* empty */
1085: { $$ = 0; }
1086: | fct_attributes TYPE
1087: { /* const/volatile function */
1088: switch ( $<t>2 ) {
1089: case VOLATILE:
1090: error('s',"volatile functions");
1091: break;
1092: case CONST:
1093: $$ = ($1 | 1);
1094: break;
1095: default:
1096: if ( NEXTTOK() != SM
1097: && yychar != COLON
1098: && yychar != LC ) {
1099: la_backup(yychar,yylval);
1100: yylval.t = $<t>2;
1101: la_backup(TYPE,yylval);
1102: yylval.t = SM;
1103: yychar = SM;
1104: error("syntax error: unexpected%k (did you forget a `;'?)",$<t>2);
1105: } else error("FD syntax: unexpected%k",$<t>2);
1106: break;
1107: }
1108: }
1109: ;
1110:
1111: decl : decl arg_list
1112: { Freturns($2) = $<pn>1->tp;
1113: $<pn>1->tp = $<pt>2;
1114: }
1115: | decl LP RP fct_attributes
1116: { /* function with no argument */
1117: $<pn>1->tp = new fct($<pn>1->tp,0,1);
1118: Pfct($<pn>1->tp)->f_const = ($<i>4 & 1);
1119: }
1120: | qualified_tname arg_list
1121: { Pname n = $<pn>1;
1122: $$ = Ncopy(n);
1123: if (ccl && strcmp(n->string,ccl->string)) n->hide();
1124: $<pn>$->n_oper = TNAME;
1125: Freturns($2) = $<pn>$->tp;
1126: $<pn>$->tp = $<pt>2;
1127: }
1128: | decl arg_lp elist RP
1129: /* may be class object initializer,
1130: class object vector initializer,
1131: if not elist will be a CM or an ID
1132: */
1133: {
1134: $<pn>1->tp = new fct($<pn>1->tp,$<pn>3,1);
1135: in_arg_list = 0;
1136: end_al($2,0);
1137: }
1138: | qualified_tname LP MUL ID RP arg_list
1139: {
1140: Pptr p = new ptr( PTR, 0 );
1141: Ptyp(p) = new basetype(TYPE,$<pn>1);
1142: Freturns( $6 ) = Ptype(p);
1143: $<pn>4->tp = $<pt>6;
1144: $$ = $4;
1145: if (DECL_TYPE == -1) DECL_TYPE = 0;
1146: }
1147: | qualified_tname LP elist RP
1148: { $$ = Ncopy($<pn>1);
1149: $<pn>$->n_oper = TNAME;
1150: $<pn>$->tp = new fct(0,$<pn>3,1);
1151: }
1152: | qualified_tname LP RP fct_attributes
1153: { /* function with no argument */
1154: $$ = Ncopy($<pn>1);
1155: $<pn>$->n_oper = TNAME;
1156: $<pn>$->tp = new fct(0,0,1);
1157: Pfct($<pn>1->tp)->f_const = ($<i>4 & 1);
1158: }
1159: | qualified_tname LP MEMPTR decl RP arg_list
1160: { memptrdcl($<pn>3,$<pn>1,$<pt>6,$<pn>4);
1161: $$ = $4;
1162: }
1163: | fname
1164: | ID DOT fname
1165: { $$ = Ncopy($<pn>3);
1166: $<pn>$->n_qualifier = $1;
1167: error(strict_opt?0:'w',"`.' used for qualification; please use `::' (anachronism)");
1168: }
1169: | tn_list fname
1170: { $$ = $2;
1171: if ( $<pn>1 != sta_name ) {
1172: set_scope($<pn>1);
1173: $<pn>$->n_qualifier = $<pn>1;
1174: }
1175: }
1176: /*XXX*/ | tn_list ID DOT fname
1177: { $$ = Ncopy($<pn>4);
1178: $<pn>$->n_qualifier = $2;
1179: error(ansi_opt?0:'w',"anachronism `.' used for qualification; please use `::'");
1180: if ( $<pn>1 != sta_name ) {
1181: set_scope($<pn>1);
1182: $<pn>2->n_qualifier = $<pn>1;
1183: }
1184: }
1185: /*XXX | tn_list TNAME
1186: * {
1187: * if ( $<pn>1 == sta_name )
1188: * error( ":: applied to CN%n", $<pn>2 );
1189: * $$ = Ncopy($<pn>2);
1190: * set_scope($<pn>1);
1191: * $<pn>$->n_oper = TNAME;
1192: * $<pn>$->n_qualifier = $<pn>1;
1193: * }
1194: */ | ptr decl %prec MUL
1195: { Ptyp($1) = $<pn>2->tp;
1196: $<pn>2->tp = $<pt>1;
1197: $$ = $2;
1198: }
1199: | ptr qualified_tname %prec MUL
1200: { $$ = Ncopy($<pn>2);
1201: $<pn>$->n_oper = TNAME;
1202: // cannot evaluate at this point: defer until data_dcl
1203: if ( in_typedef ) {
1204: defer_check = 1;
1205: in_tag = $<pn>2;
1206: }
1207: $<pn>2->hide();
1208: defer_check = 0;
1209: $<pn>$->tp = $<pt>1;
1210: }
1211: | qualified_tname vec %prec LB
1212: { $$ = Ncopy($<pn>1);
1213: $<pn>$->n_oper = TNAME;
1214: if ( in_typedef ) {
1215: defer_check = 1;
1216: in_tag = $<pn>2;
1217: }
1218: $<pn>1->hide();
1219: defer_check = 0;
1220: $<pn>$->tp = $<pt>2;
1221: }
1222: | decl vec %prec LB
1223: { Vtype($2) = $<pn>1->tp;
1224: $<pn>1->tp = $<pt>2;
1225: }
1226: /*
1227: | LP decl RP arg_list
1228: {
1229: Freturns($4) = $<pn>2->tp;
1230: $<pn>2->tp = $<pt>4;
1231: $$ = $2;
1232: }
1233: | LP decl RP vec
1234: { Vtype($4) = $<pn>2->tp;
1235: $<pn>2->tp = $<pt>4;
1236: $$ = $2;
1237: }
1238: */
1239: | arg_lp decl RP
1240: {
1241: $$ = $2;
1242: in_arg_list = 0;
1243: end_al($1,0);
1244: }
1245: ;
1246:
1247: arg_decl : ID
1248: { $$ = $<pn>1; }
1249: | ptr qualified_tname %prec MUL
1250: { $$ = Ncopy($<pn>2);
1251: $<pn>$->n_oper = TNAME;
1252: $<pn>2->hide();
1253: $<pn>$->tp = $<pt>1;
1254: }
1255: | %prec NO_ID
1256: {
1257: $$ = new name;
1258: NOT_EXPECT_ID();
1259: }
1260: | ptr arg_decl %prec MUL
1261: { Ptyp($1) = $<pn>2->tp;
1262: $<pn>2->tp = (Ptype)$1;
1263: $$ = $2;
1264: }
1265: | arg_decl vec %prec LB
1266: { Vtype($2) = $<pn>1->tp;
1267: $<pn>1->tp = (Ptype)$2;
1268: }
1269: | arg_decl arg_list
1270: { Freturns($2) = $<pn>1->tp;
1271: $<pn>1->tp = (Ptype)$2;
1272: }
1273: /*
1274: | LP arg_decl RP arg_list
1275: { Freturns($4) = $<pn>2->tp;
1276: $<pn>2->tp = (Ptype)$4;
1277: $$ = $2;
1278: }
1279: | LP arg_decl RP vec
1280: { Vtype($4) = $<pn>2->tp;
1281: $<pn>2->tp = (Ptype)$4;
1282: $$ = $2;
1283: }
1284: */
1285: | arg_lp arg_decl RP
1286: {
1287: // error('d', "arg_lp arg_decl rp in_arg_list: %d", in_arg_list );
1288: $$ = $2;
1289: in_arg_list = 0;
1290: end_al($1,0);
1291: }
1292: ;
1293:
1294: new_decl : %prec NO_ID
1295: { $$ = new name; }
1296: | ptr new_decl %prec MUL
1297: { Ptyp($1) = $<pn>2->tp;
1298: $<pn>2->tp = (Ptype)$1;
1299: $$ = $2;
1300: NOT_EXPECT_ID();
1301: }
1302: | new_decl vec %prec LB
1303: { Vtype($2) = $<pn>1->tp;
1304: $<pn>1->tp = (Ptype)$2;
1305: }
1306: ;
1307:
1308: cast_decl : %prec NO_ID { $$ = new name; }
1309: | ptr cast_decl %prec MUL
1310: { Ptyp($1) = $<pn>2->tp;
1311: $<pn>2->tp = (Ptype)$1;
1312: $$ = $2;
1313: NOT_EXPECT_ID();
1314: }
1315: | cast_decl vec %prec LB
1316: { Vtype($2) = $<pn>1->tp;
1317: $<pn>1->tp = (Ptype)$2;
1318: }
1319: | LP cast_decl RP arg_list
1320: { Freturns($4) = $<pn>2->tp;
1321: $<pn>2->tp = $<pt>4;
1322: $$ = $2;
1323: }
1324: | LP cast_decl RP vec
1325: { Vtype($4) = $<pn>2->tp;
1326: $<pn>2->tp = $<pt>4;
1327: $$ = $2;
1328: }
1329: ;
1330:
1331: c_decl : %prec NO_ID
1332: { $$ = new name; }
1333: | ptr c_decl %prec MUL
1334: { Ptyp($1) = $<pn>2->tp;
1335: $<pn>2->tp = (Ptype)$1;
1336: $$ = $2;
1337: }
1338: ;
1339:
1340:
1341:
1342: /***************** statements: returns Pstmt *****************/
1343: stmt_list : /* empty */
1344: {
1345: $$ = 0;
1346: }
1347: | stmt_list caselab_stmt
1348: {
1349: if ($2)
1350: if ($1)
1351: $<sl>1->add($<ps>2);
1352: else {
1353: $<sl>$ = new slist($<ps>2);
1354: stmt_seen = 1;
1355: }
1356: }
1357: ;
1358: caselab_stmt : caselablist statement
1359: {
1360: $$ = $2;
1361: if ($2) stmt_seen = 1;
1362: }
1363: ;
1364:
1365: caselablist : /* empty */
1366: {
1367: $$ = 0;
1368: check_decl();
1369: }
1370: ;
1371:
1372: condition : LP e RP
1373: { $$ = $2;
1374: /* if ($<pe>$ == dummy) error("empty condition");*/
1375: stmt_seen = 1;
1376: }
1377: ;
1378:
1379: block : LC
1380: { cd_vec[cdi] = cd;
1381: stmt_vec[cdi] = stmt_seen;
1382: tn_vec[cdi] = modified_tn;
1383: lcl_blk_vec[cdi++] = local_blk;
1384: lcl_tn_vec[cdi] = local_tn;
1385: local_blk = 0;
1386: local_tn = 0;
1387: cd = 0;
1388: stmt_seen = 0;
1389: modified_tn = 0;
1390: }
1391: stmt_list RC
1392: { Pname n = name_unlist(cd);
1393: Pstmt ss = stmt_unlist($<sl>3);
1394: $$ = new block($<l>1,n,ss,$<l>4);
1395: if ( local_tn ) local_restore();
1396: if ( local_blk ) local_name();
1397: if (modified_tn) restore();
1398: cd = cd_vec[--cdi];
1399: stmt_seen = stmt_vec[cdi];
1400: modified_tn = tn_vec[cdi];
1401: local_tn = lcl_tn_vec[cdi];
1402: local_blk = lcl_blk_vec[cdi];
1403: if (cdi < 0) error('i',"block level(%d)",cdi);
1404: NOT_EXPECT_ID();
1405: }
1406: | LC RC
1407: { $$ = new block($<l>1,0,0,$<l>2); NOT_EXPECT_ID();}
1408: | LC error RC
1409: { $$ = new block($<l>1,0,0,$<l>3); NOT_EXPECT_ID();}
1410: ;
1411:
1412: simple : ee
1413: { $$ = new estmt(SM,curloc,$<pe>1,0); }
1414: | BREAK
1415: { $$ = new stmt(BREAK,$<l>1,0); }
1416: | CONTINUE
1417: { $$ = new stmt(CONTINUE,$<l>1,0); }
1418: | GOTO ID
1419: { $$ = new lstmt(GOTO,$<l>1,$<pn>2,0); }
1420: | DO { stmt_seen=1; } caselab_stmt WHILE condition
1421: { $$ = new estmt(DO,$<l>1,$<pe>5,$<ps>3); }
1422: | ASM LP STRING RP
1423: {
1424: if (stmt_seen)
1425: $$ = new estmt(ASM,curloc,(Pexpr)$<s>3,0);
1426: else {
1427: Pname n = new name(make_name('A'));
1428: n->tp = new basetype(ASM,(Pname)$<s>3);
1429: if (cd)
1430: cd->add_list(n);
1431: else
1432: cd = new nlist(n);
1433: $$ = 0;
1434: }
1435: }
1436: ;
1437:
1438: sm : {
1439: if ( NEXTTOK() != SM ) {
1440: error("`;' missing afterS");
1441: la_backup(yychar,yylval);
1442: yychar = SM;
1443: }
1444: } SM
1445: ;
1446:
1447: statement : simple sm
1448: | SM
1449: { $$ = new estmt(SM,$<l>1,dummy,0); }
1450: | RETURN e SM
1451: { $$ = new estmt(RETURN,$<l>1,$<pe>2,0); }
1452: | TYPE STRING block
1453: {
1454: error("local linkage specification");
1455: $$ = $<pn>3;
1456: }
1457: | data_dcl
1458: { Pname n = $<pn>1;
1459: if (n)
1460: if (stmt_seen) {
1461: $$ = new block(n->where,n,0);
1462: $<ps>$->base = DCL;
1463: }
1464: else {
1465: if (cd)
1466: cd->add_list(n);
1467: else
1468: cd = new nlist(n);
1469: $$ = 0;
1470: }
1471: }
1472: | att_fct_def
1473: {
1474: Pname n = $<pn>1;
1475: error(&n->where,"%n's definition is nested (did you forget a ``}''?)",n);
1476: if (cd)
1477: cd->add_list(n);
1478: else
1479: cd = new nlist(n);
1480: $$ = 0;
1481: }
1482: | block
1483: | IF condition caselab_stmt
1484: { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,0); }
1485: | IF condition caselab_stmt ELSE caselab_stmt
1486: { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,$<ps>5); }
1487: | WHILE condition caselab_stmt
1488: { $$ = new estmt(WHILE,$<l>1,$<pe>2,$<ps>3); }
1489: | FOR LP { stmt_seen=1; } caselab_stmt e SM e RP caselab_stmt
1490: { $$ = new forstmt($<l>1,$<ps>4,$<pe>5,$<pe>7,$<ps>9); }
1491: | SWITCH condition caselab_stmt
1492: { $$ = new estmt(SWITCH,$<l>1,$<pe>2,$<ps>3); }
1493: | ID COLON { $$ = $1; stmt_seen=1; } caselab_stmt
1494: { Pname n = $<pn>3;
1495: $$ = new lstmt(LABEL,n->where,n,$<ps>4);
1496: }
1497: | TNAME COLON { $$ = new name($<pn>1->string); stmt_seen=1; } caselab_stmt
1498: { Pname n = $<pn>3;
1499: $$ = new lstmt(LABEL,n->where,n,$<ps>4);
1500: }
1501: | CASE { stmt_seen=1; } e COLON caselab_stmt
1502: { if ($<pe>3 == dummy) error("empty case label");
1503: $$ = new estmt(CASE,$<l>1,$<pe>3,$<ps>5);
1504: }
1505: | DEFAULT COLON { stmt_seen=1; } caselab_stmt
1506: { $$ = new stmt(DEFAULT,$<l>1,$<ps>4); }
1507: ;
1508:
1509:
1510:
1511: /********************* expressions: returns Pexpr **************/
1512: elist : ex_list
1513: { Pexpr e = expr_unlist($<el>1);
1514: while (e && e->e1==dummy) {
1515: register Pexpr ee2 = e->e2;
1516: if (ee2) error("EX inEL");
1517: delete e;
1518: e = ee2;
1519: }
1520: $$ = e;
1521: }
1522: ;
1523:
1524: ex_list : initializer %prec CM
1525: { $<el>$ = new elist(new expr(ELIST,$<pe>1,0)); }
1526: | ex_list CM initializer
1527: { $<el>1->add(new expr(ELIST,$<pe>3,0)); }
1528: ;
1529:
1530: initializer : e %prec CM
1531: | LC elist RC
1532: {
1533: if ( in_arg_list )
1534: error( "syntax error: IrL not permitted in AL" );
1535: else if ( in_binit_list )
1536: error( "syntax error: IrL not permitted inMIr" );
1537: else
1538: init_seen = 1;
1539: Pexpr e;
1540: if ($2)
1541: e = $<pe>2;
1542: else
1543: e = new expr(ELIST,dummy,0);
1544: $$ = new expr(ILIST,e,0);
1545: }
1546: ;
1547:
1548: ee : ee ASSIGN ee
1549: { bbinop: $$ = new expr($<t>2,$<pe>1,$<pe>3); }
1550: | ee PLUS ee { goto bbinop; }
1551: | ee MINUS ee { goto bbinop; }
1552: | ee MUL ee { goto bbinop; }
1553: | ee AND ee { goto bbinop; }
1554: | ee OR ee { goto bbinop; }
1555: | ee ER ee { goto bbinop; }
1556: | ee SHIFTOP ee { goto bbinop; }
1557: | ee EQUOP ee { goto bbinop; }
1558: | ee DIVOP ee { goto bbinop; }
1559: | ee RELOP ee { goto bbinop; }
1560: | ee ANDAND ee { goto bbinop; }
1561: | ee OROR ee { goto bbinop; }
1562: | ee ASOP ee { goto bbinop; }
1563: | ee CM ee { goto bbinop; }
1564: | ee QUEST ee COLON ee
1565: { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); }
1566: | DELETE term
1567: { $$ = new expr(DELETE,$<pe>2,0); }
1568: | DELETE LB e RB term
1569: {
1570: if($<pe>3 != dummy) {
1571: if ( warning_opt || strict_opt )
1572: error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)");
1573: }
1574: $$ = new expr(DELETE,$<pe>5,$<pe>3);
1575: }
1576: | MEM DELETE term
1577: { $$ = new expr(GDELETE,$<pe>3,0); }
1578: | MEM DELETE LB e RB term
1579: {
1580: if($<pe>4 != dummy) {
1581: if ( warning_opt || strict_opt )
1582: error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)");
1583: }
1584: $$ = new expr(DELETE,$<pe>6,$<pe>4);
1585: }
1586: | term
1587: ;
1588:
1589: e : e ASSIGN e
1590: { binop: $$ = new expr($<t>2,$<pe>1,$<pe>3); }
1591: | e PLUS e { goto binop; }
1592: | e MINUS e { goto binop; }
1593: | e MUL e { goto binop; }
1594: | e AND e { goto binop; }
1595: | e OR e { goto binop; }
1596: | e ER e { goto binop; }
1597: | e SHIFTOP e { goto binop; }
1598: | e EQUOP e { goto binop; }
1599: | e DIVOP e { goto binop; }
1600: | e RELOP e { goto binop; }
1601: | e ANDAND e { goto binop; }
1602: | e OROR e { goto binop; }
1603: | e ASOP e { goto binop; }
1604: | e CM e { goto binop; }
1605: | e QUEST e COLON e
1606: { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); }
1607: | DELETE term
1608: { $$ = new expr(DELETE,$<pe>2,0); }
1609: | DELETE LB e RB term
1610: {
1611: if($<pe>3 != dummy) {
1612: if ( warning_opt || strict_opt )
1613: error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)");
1614: }
1615: $$ = new expr(DELETE,$<pe>5,$<pe>3);
1616: }
1617: | MEM DELETE term
1618: { $$ = new expr(GDELETE,$<pe>3,0); }
1619: | MEM DELETE LB e RB term
1620: {
1621: if($<pe>4 != dummy) {
1622: if ( warning_opt || strict_opt )
1623: error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)");
1624: }
1625: $$ = new expr(DELETE,$<pe>6,$<pe>4);
1626: }
1627: | term {
1628: init_seen = 0;
1629: }
1630: | %prec NO_EXPR
1631: { $$ = dummy; }
1632: ;
1633:
1634: term : NEW cast_type { goto new1; }
1635: | NEW new_type
1636: { new1:
1637: Ptype t = $<pn>2->tp;
1638: $$ = new texpr(NEW,t,0);
1639: }
1640: | MEM NEW cast_type { goto new3; }
1641: | MEM NEW new_type
1642: { new3:
1643: Ptype t = $<pn>3->tp;
1644: $$ = new texpr(GNEW,t,0);
1645: }
1646: | term ICOP
1647: { $$ = new expr($<t>2,$<pe>1,0); }
1648: | cast_type term %prec ICOP
1649: { $$ = new texpr(CAST,$<pn>1->tp,$<pe>2); }
1650: | MUL term
1651: { $$ = new expr(DEREF,$<pe>2,0); }
1652: | AND term
1653: { $$ = new expr(ADDROF,0,$<pe>2); }
1654: | MINUS term
1655: { $$ = new expr(UMINUS,0,$<pe>2); }
1656: | PLUS term
1657: { $$ = new expr(UPLUS,0,$<pe>2); }
1658: | NOT term
1659: { $$ = new expr(NOT,0,$<pe>2); }
1660: | COMPL term
1661: { $$ = new expr(COMPL,0,$<pe>2); }
1662: | ICOP term
1663: { $$ = new expr($<t>1,0,$<pe>2); }
1664: | SIZEOF term
1665: {
1666: $$ = new texpr(SIZEOF,0,$<pe>2);
1667: in_sizeof = 0;
1668: }
1669: | SIZEOF cast_type %prec SIZEOF
1670: {
1671: $$ = new texpr(SIZEOF,$<pn>2->tp,0);
1672: in_sizeof = 0;
1673: }
1674: | term LB e RB
1675: { $$ = new expr(DEREF,$<pe>1,$<pe>3); }
1676: | term REF prim
1677: { $$ = new ref(REF,$<pe>1,$<pn>3); }
1678: | term REFMUL term
1679: { $$ = new expr($<t>2,$<pe>1,$<pe>3); }
1680: | term REF qualified_tname
1681: { $$ = new ref(REF,$<pe>1,Ncopy($<pn>3)); }
1682: | term DOT prim
1683: { $$ = new ref(DOT,$<pe>1,$<pn>3); }
1684: | term DOT qualified_tname
1685: { $$ = new ref(DOT,$<pe>1,Ncopy($<pn>3)); }
1686: | prim
1687: | term_elist
1688: {
1689: if ( init_seen )
1690: error( "syntax error:IrL illegal within ()");
1691: }
1692:
1693: | term_lp e RP
1694: {
1695: if ( $2 == dummy )
1696: error("syntax error: nullE");
1697: $$ = $2;
1698: }
1699: | ZERO
1700: { $$ = zero; }
1701: | ICON
1702: { $$ = new expr(ICON,0,0);
1703: $<pe>$->string = $<s>1;
1704: }
1705: | FCON
1706: { $$ = new expr(FCON,0,0);
1707: $<pe>$->string = $<s>1;
1708: }
1709: | STRING
1710: { $$ = new expr(STRING,0,0);
1711: $<pe>$->string = $<s>1;
1712: }
1713: | CCON
1714: { $$ = new expr(CCON,0,0);
1715: $<pe>$->string = $<s>1;
1716: }
1717: | THIS
1718: { $$ = new expr(THIS,0,0); }
1719: ;
1720:
1721: term_elist : TYPE LP elist RP
1722: { $$ = new texpr(VALUE,tok_to_type($<t>1),$<pe>3); }
1723: | qualified_tname LP elist RP
1724: { $$ = new texpr(VALUE,$<pn>1->tp,$<pe>3); }
1725: | NEW term_lp elist RP cast_type { goto new2; }
1726: | NEW term_lp elist RP new_type /* allow separate allocation */
1727: { new2:
1728: Ptype t = $<pn>5->tp;
1729: $$=new texpr(NEW,t,0);
1730: $<pe>$->e2 = $<pe>3;
1731: }
1732: | MEM NEW term_lp elist RP cast_type { goto new4; }
1733: | MEM NEW term_lp elist RP new_type /* allow separate allocation */
1734: { new4:
1735: Ptype t = $<pn>6->tp;
1736: $$ = new texpr(GNEW,t,0);
1737: $<pe>$->e2 = $<pe>4;
1738: }
1739: | term LP elist RP
1740: {
1741: Pexpr ee = $<pe>3;
1742: Pexpr e = $<pe>1;
1743: if (e->base==NEW || e->base==GNEW)
1744: e->e1 = ee;
1745: else
1746: $$ = new call(e,ee);
1747: }
1748:
1749: ;
1750: tscope : TSCOPE
1751: {
1752: $<pn>$ = $<pn>1;
1753: curr_scope = $<pn>1;
1754: }
1755: | MEM
1756: { $<pn>$ = sta_name; }
1757: ;
1758:
1759:
1760: prim : ID
1761: { $$ = $<pn>1; }
1762: /*XXX*/ | tn_list ID
1763: { $$ = Ncopy($<pn>2);
1764: $<pn>$->n_qualifier = $<pn>1;
1765: }
1766: | OPERATOR oper
1767: { $$ = new name(oper_name($2));
1768: $<pn>$->n_oper = $<t>2;
1769: }
1770: | tn_list OPERATOR oper
1771: { $$ = new name(oper_name($3));
1772: $<pn>$->n_oper = $<t>3;
1773: $<pn>$->n_qualifier = $<pn>1;
1774: }
1775: | OPERATOR c_type
1776: { $$ = $2;
1777: sig_name($<pn>$);
1778: }
1779: | tn_list OPERATOR c_type
1780: { $$ = $3;
1781: sig_name($<pn>$);
1782: $<pn>$->n_qualifier = $<pn>1;
1783: }
1784: | tn_list COMPL tag /* allow explicit call of destructor */
1785: {
1786: if (strcmp($<pn>1->string,$<pn>3->string)) error("syntax error: inconsistent destructor notation");
1787: $$ = new name(oper_name(DTOR));
1788: $<pn>$->n_oper = DTOR;
1789: $<pn>$->n_qualifier = $<pn>1;
1790: }
1791: ;
1792:
1793:
1794:
1795: /****************** abstract types (return type Pname) *************/
1796: cast_type : term_lp type cast_decl RP
1797: { $$ = Ncast($2,$<pn>3); }
1798: ;
1799:
1800: term_lp : LP { check_cast(); }
1801: ;
1802:
1803: c_tp : TYPE
1804: {
1805: TOK t = $<t>1;
1806:
1807: switch (t) {
1808: case FRIEND:
1809: case OVERLOAD:
1810: case REGISTER:
1811: case STATIC:
1812: case EXTERN:
1813: case AUTO:
1814: case VIRTUAL:
1815: error("%k in operatorT",t);
1816: t = INT;
1817:
1818: }
1819:
1820: $$ = new basetype(t,0);
1821:
1822: }
1823: | qualified_tname { $$ = new basetype(TYPE,$<pn>1); }
1824: | c_tp TYPE
1825: {
1826: if ( DECL_TYPE != -1 )
1827: $$ = $<pb>1->type_adj($<t>2);
1828: DECL_TYPE = 0;
1829: }
1830: | c_tp qualified_tname
1831: {
1832: if ( DECL_TYPE != -1 )
1833: $$ = $<pb>1->name_adj($<pn>2);
1834: DECL_TYPE = 0;
1835: }
1836: ;
1837:
1838: c_type : c_tp c_decl { $$ = Ncast($1,$<pn>2); }
1839: ;
1840:
1841: new_type : type new_decl { $$ = Ncast($1,$<pn>2); };
1842:
1843: arg_type : type arg_decl
1844: { $$ = Ndata($1,$<pn>2); }
1845: | type arg_decl ASSIGN initializer
1846: { $$ = Ndata($1,$<pn>2);
1847: $<pn>$->n_initializer = $<pe>4;
1848: }
1849: ;
1850:
1851: arg_lp : LP
1852: {
1853: check_decl();
1854: in_arg_list=1;
1855: $$ = modified_tn;
1856: modified_tn = 0;
1857: }
1858: ;
1859:
1860: arg_list : arg_lp arg_type_list ellipsis_opt RP fct_attributes
1861: {
1862: $$ = new fct(0,name_unlist($<nl>2),$<t>3);
1863: if ( NEXTTOK() != COLON ) in_arg_list=0;
1864: //in_arg_list=0;
1865: Pfct($<pt>$)->f_const = ($<i>5 & 1);
1866: if ( parsing_class_members
1867: || (NEXTTOK()!=LC && yychar!=COLON))
1868: end_al($1,1);
1869: else
1870: end_al($1,0);
1871: }
1872: ;
1873:
1874: arg_type_list : arg_type_list CM at
1875: {
1876: if ($3)
1877: if ($1)
1878: $<nl>1->add($<pn>3);
1879: else {
1880: error("AD syntax");
1881: $<nl>$ = new nlist($<pn>3);
1882: }
1883: else
1884: error("AD syntax");
1885: }
1886: | at %prec CM
1887: {
1888: if ($1) $<nl>$ = new nlist($<pn>1);
1889: }
1890: ;
1891:
1892: at : arg_type
1893: | %prec EMPTY { $$ = 0; }
1894: ;
1895:
1896: ellipsis_opt : /* empty */
1897: { $$ = 1; }
1898: | ELLIPSIS
1899: { $$ = ELLIPSIS; }
1900: | CM ELLIPSIS
1901: { $$ = ELLIPSIS; }
1902: ;
1903:
1904: ptr : MUL %prec NO_ID
1905: {
1906: $$ = new ptr(PTR,0);
1907: EXPECT_ID();
1908: }
1909: | AND %prec NO_ID
1910: {
1911: $$ = new ptr(RPTR,0);
1912: EXPECT_ID();
1913: }
1914: | MUL TYPE %prec NO_ID
1915: { $$ = doptr(PTR,$<t>2); }
1916: | ptr TYPE %prec NO_ID
1917: {
1918: switch ( $<t>2 ) {
1919: case CONST:
1920: $<pp>1->rdo = 1; break;
1921: case VOLATILE:
1922: error('w',"\"volatile\" not implemented (ignored)");
1923: break;
1924: default:
1925: error( "syntax error: *%k", $<t>2 );
1926: }
1927: $$ = $<pp>1;
1928: }
1929: | AND TYPE %prec NO_ID
1930: { $$ = doptr(RPTR,$<t>2); }
1931: | MEMPTR %prec NO_ID
1932: {
1933: $$ = new ptr(PTR,0);
1934: $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp);
1935: EXPECT_ID();
1936: }
1937: | MEMPTR TYPE %prec NO_ID
1938: { $$ = doptr(PTR,$<t>2);
1939: $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp);
1940: }
1941: ;
1942:
1943: vec : LB e RB { $$ = new vec(0,$<pe>2!=dummy?$<pe>2:0 ); }
1944: | NOT %prec LB { $$ = new vec(0,0); }
1945: ;
1946:
1947: %%
1948:
1949: static void
1950: check_tag()
1951: /*
1952: Allow the case of inline/virtual/overload as
1953: modifiers of return type of form struct/class/union x foo()
1954: SM, COLON, LC ==> real class declaration, not return type
1955: */
1956: {
1957: switch ( NEXTTOK() ) {
1958: case SM: case COLON: case LC:
1959: declTag = 1;
1960: break;
1961: default:
1962: declTag = 0;
1963: break;
1964: }
1965: }
1966:
1967: static void
1968: end_al( Plist mtn, int rst )
1969: // unhide type names hidden by arg names
1970: // mtn == saved modified_tn
1971: {
1972: if ( rst == 0 ) {
1973: // not really an arg list, or we are entering a function def
1974: // merge modified_tn and don't restore
1975: if ( modified_tn == 0 ) modified_tn = mtn;
1976: else {
1977: for ( Plist l = modified_tn; l->l; l = l->l ) ;
1978: l->l = mtn;
1979: }
1980: } else {
1981: restore();
1982: modified_tn = mtn;
1983: }
1984: }
1985: static void
1986: arg_redec( Pname fn )
1987: {
1988: if ( fn==0 || fn->tp->base != FCT )
1989: error('i',"bad inline rewrite!");
1990: Pname al = Pfct(fn->tp)->argtype;
1991: Pname n = 0;
1992: for ( ; al; al = al->n_list ) {
1993: DB( if(Ydebug>=1)error('d',"arg_redec: %n %d",al,al->lex_level); );
1994: // nested function args should have lex_level >= 1
1995: if ( al->lex_level==1 && (n=ktbl->look(al->string,0)) )
1996: n->hide();
1997: else if ( al->lex_level>1 && (n=ktbl->look(al->string,LOCAL)) )
1998: n->hide();
1999: DB( if(Ydebug>=1)error('d'," %n",n); );
2000: }
2001: }
2002:
2003:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.