/*ident "@(#)cfront:src/gram.y 1.12" */ /************************************************************************* C++ source for cfront, the C++ compiler front-end written in the computer science research center of Bell Labs Copyright (c) 1984 AT&T, Inc. All Rights Reserved THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. gram.y: This is the C++ syntax analyser. Syntax extensions for error handling: nested functions any expression can be empty any expression can be a constant_expression A call to error() does not change the parser's state ***************************************************************************/ %{ #include "cfront.h" #include "size.h" #define YYMAXDEPTH 300 static cdi = 0; static Pnlist cd = 0, cd_vec[BLMAX]; static char stmt_seen = 0, stmt_vec[BLMAX]; static Plist tn_vec[BLMAX]; void sig_name(Pname); // fcts put into norm2.c just to get them out of gram.y Ptype tok_to_type(TOK); void memptrdcl(Pname, Pname, Ptype, Pname); #define lex_unget(x) back = x #define Ndata(a,b) b->normalize(Pbase(a),0,0) #define Ncast(a,b) b->normalize(Pbase(a),0,1) #define Nfct(a,b,c) b->normalize(Pbase(a),Pblock(c),0) #define Ncopy(n) (n->base==TNAME)?new name(n->string):n #define Finit(p) Pfct(p)->f_init #define Fargdcl(p,q,r) Pfct(p)->argdcl(q,r) #define Freturns(p) Pfct(p)->returns #define Vtype(v) Pvec(v)->typ #define Ptyp(p) Pptr(p)->typ /* avoid redefinitions */ #undef EOFTOK #undef ASM #undef BREAK #undef CASE #undef CONTINUE #undef DEFAULT #undef DELETE #undef DO #undef ELSE #undef ENUM #undef FOR #undef FORTRAN #undef GOTO #undef IF #undef NEW #undef OPERATOR #undef RETURN #undef SIZEOF #undef SWITCH #undef THIS #undef WHILE #undef LP #undef RP #undef LB #undef RB #undef REF #undef DOT #undef NOT #undef COMPL #undef MUL #undef AND #undef PLUS #undef MINUS #undef ER #undef OR #undef ANDAND #undef OROR #undef QUEST #undef COLON #undef ASSIGN #undef CM #undef SM #undef LC #undef RC #undef ID #undef STRING #undef ICON #undef FCON #undef CCON #undef ZERO #undef ASOP #undef RELOP #undef EQUOP #undef DIVOP #undef SHIFTOP #undef ICOP #undef TYPE #undef TNAME #undef EMPTY #undef NO_ID #undef NO_EXPR #undef ELLIPSIS #undef AGGR #undef MEM #undef CAST #undef ENDCAST #undef MEMPTR #undef PR %} %union { char* s; TOK t; int i; loc l; Pname pn; Ptype pt; Pexpr pe; Pstmt ps; Pbase pb; Pnlist nl; Pslist sl; Pelist el; PP p; // fudge: pointer to all class node objects } %{ extern YYSTYPE yylval, yyval; extern int yyparse(); Pname syn() { ll: switch (yyparse()) { case 0: return 0; // EOF case 1: goto ll; // no action needed default: return yyval.pn; } } void look_for_hidden(Pname n, Pname nn) { Pname nx = ktbl->look(n->string,HIDDEN); if (nx == 0) error("nonTN%n before ::%n",n,nn); nn->n_qualifier = nx; } %} /* the token definitions are copied from token.h, and all %token replaced by %token */ /* keywords in alphabetical order */ %token EOFTOK 0 %token ASM 1 %token BREAK 3 %token CASE 4 %token CONTINUE 7 %token DEFAULT 8 %token DELETE 9 %token DO 10 %token ELSE 12 %token ENUM 13 %token FOR 16 %token FORTRAN 17 %token GOTO 19 %token IF 20 %token NEW 23 %token OPERATOR 24 %token RETURN 28 %token SIZEOF 30 %token SWITCH 33 %token THIS 34 %token WHILE 39 /* operators in priority order (sort of) */ %token LP 40 %token RP 41 %token LB 42 %token RB 43 %token REF 44 %token DOT 45 %token NOT 46 %token COMPL 47 %token MUL 50 %token AND 52 %token PLUS 54 %token MINUS 55 %token ER 64 %token OR 65 %token ANDAND 66 %token OROR 67 %token QUEST 68 %token COLON 69 %token ASSIGN 70 %token CM 71 %token SM 72 %token LC 73 %token RC 74 %token CAST 113 %token ENDCAST 122 %token MEMPTR 173 /* constants etc. */ %token ID 80 %token STRING 81 %token ICON 82 %token FCON 83 %token CCON 84 %token ZERO 86 /* groups of tokens */ %token ASOP 90 /* op= */ %token RELOP 91 /* LE GE LT GT */ %token EQUOP 92 /* EQ NE */ %token DIVOP 93 /* DIV MOD */ %token SHIFTOP 94 /* LS RS */ %token ICOP 95 /* INCR DECR */ %token TYPE 97 /* INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO CONST INLINE VIRTUAL FRIEND LONG SHORT UNSIGNED TYPEDEF */ %token TNAME 123 %token EMPTY 124 %token NO_ID 125 %token NO_EXPR 126 %token ELLIPSIS 155 /* ... */ %token AGGR 156 /* CLASS STRUCT UNION */ %token MEM 160 /* :: */ %token PR 175 /* PUBLIC PRIVATE PROTECTED */ %type <p> external_def fct_dcl fct_def att_fct_def arg_dcl_list base_init init_list binit data_dcl ext_def vec ptr type tp enum_dcl moe_list moe tag class_head class_dcl cl_mem_list cl_mem dl decl_list fname decl initializer stmt_list block statement simple ex_list elist e term prim cast_decl cast_type c_decl c_type c_tp arg_decl at arg_type arg_list arg_type_list new_decl new_type condition TNAME tn_list MEMPTR %type <l> LC RC SWITCH CASE DEFAULT FOR IF DO WHILE GOTO RETURN DELETE BREAK CONTINUE %type <t> oper EQUOP DIVOP SHIFTOP ICOP RELOP ASOP ANDAND OROR PLUS MINUS MUL ASSIGN OR ER AND LP LB NOT COMPL AGGR TYPE PR %type <s> CCON ZERO ICON FCON STRING %type <pn> ID %left EMPTY %left NO_ID %left RC LC ID BREAK CONTINUE RETURN GOTO DELETE DO IF WHILE FOR CASE DEFAULT AGGR ENUM TYPE %left NO_EXPR %left CM %right ASOP ASSIGN %right QUEST COLON %left OROR %left ANDAND %left OR %left ER %left AND %left EQUOP %left RELOP %left SHIFTOP %left PLUS MINUS %left MUL DIVOP MEMPTR %right NOT COMPL NEW %right CAST ICOP SIZEOF %left LB LP DOT REF MEM %start ext_def %% /* this parser handles declarations one by one, NOT a complete .c file */ /************** DECLARATIONS in the outermost scope: returns Pname (in yylval) ***/ ext_def : external_def { return 2; } | SM { return 1; } | EOFTOK { return 0; } ; external_def : data_dcl { modified_tn = 0; if ($<pn>1==0) $<i>$ = 1; } | att_fct_def { goto mod; } | fct_def { goto mod; } | fct_dcl { mod: if (modified_tn) { restore(); modified_tn = 0; } } | ASM LP STRING RP SM { Pname n = new name(make_name('A')); n->tp = new basetype(ASM,0); Pbase(n->tp)->b_name = Pname($<s>3); $$ = n; } ; fct_dcl : decl ASSIGN initializer SM { error('s',"T ofIdE too complicated (useTdef or leave out theIr)"); goto fix; } | decl SM { Pname n; Ptype t; fix: if ((n=$<pn>1) == 0) { error("syntax error:TX"); $$ = Ndata(defa_type,n); } else if ((t=n->tp) == 0) { error("TX for%n",n); $$ = Ndata(defa_type,n); } else if (t->base==FCT) { if (Pfct(t)->returns==0) $$ = Nfct(defa_type,n,0); else $$ = Ndata(0,n); } else { error("syntax error:TX for%k%n",t->base,n); $$ = Ndata(defa_type,n); } } ; att_fct_def : type decl arg_dcl_list base_init block { Pname n = Nfct($1,$<pn>2,$5); Fargdcl(n->tp,name_unlist($<nl>3),n); Finit(n->tp) = $<pn>4; $$ = n; } ; fct_def : decl arg_dcl_list base_init block { Pname n = Nfct(defa_type,$<pn>1,$4); Fargdcl(n->tp,name_unlist($<nl>2),n); Finit(n->tp) = $<pn>3; $$ = n; } ; base_init : COLON init_list { $$ = $2; } | %prec EMPTY { $$ = 0; } ; init_list : binit | init_list CM binit { $<pn>$ = $<pn>3; $<pn>$->n_list = $<pn>1; } ; binit : LP elist RP { $<pn>$ = new name; $<pn>$->n_initializer = $<pe>2; } | ID LP elist RP { $<pn>$ = $1; $<pn>$->n_initializer = $<pe>3; } ; /*************** declarations: returns Pname ********************/ arg_dcl_list : arg_dcl_list data_dcl { if ($<pn>2 == 0) error("badAD"); else if ($<pn>2->tp->base == FCT) error("FD inAL (%n)",$<pn>2); else if ($1) $<nl>1->add($<pn>2); else $<nl>$ = new nlist($<pn>2); } | %prec EMPTY { $$ = 0; } ; dl : decl | ID COLON e %prec CM { $$ = $<pn>1; $<pn>$->tp = new basetype(FIELD,$<pn>3); } | COLON e %prec CM { $$ = new name; $<pn>$->tp = new basetype(FIELD,$<pn>2); } | decl ASSIGN initializer { Pexpr e = $<pe>3; if (e == dummy) error("emptyIr"); $<pn>1->n_initializer = e; } ; decl_list : dl { if ($1) $<nl>$ = new nlist($<pn>1); } | decl_list CM dl { if ($1) if ($3) $<nl>1->add($<pn>3); else error("DL syntax"); else { if ($3) $<nl>$ = new nlist($<pn>3); error("DL syntax"); } } ; data_dcl : type decl_list SM { $$ = Ndata($1,name_unlist($<nl>2)); } | type SM { $$ = $<pb>1->aggr(); } ; tp : TYPE { $$ = new basetype($<t>1,0); } | TNAME { $$ = new basetype(TYPE,$<pn>1); } | class_dcl | enum_dcl ; type : tp | type TYPE { $$ = $<pb>1->type_adj($<t>2); } | type TNAME { $$ = $<pb>1->name_adj($<pn>2); } | type class_dcl { $$ = $<pb>1->base_adj($<pb>2); } | type enum_dcl { $$ = $<pb>1->base_adj($<pb>2); } ; /***************** aggregate: returns Pname *****************/ enum_dcl : ENUM LC moe_list RC { $$ = end_enum(0,$<pn>3); } | ENUM tag LC moe_list RC { $$ = end_enum($<pn>2,$<pn>4); } ; moe_list : moe { if ($1) $<nl>$ = new nlist($<pn>1); } | moe_list CM moe { if( $3) if ($1) $<nl>1->add($<pn>3); else $<nl>$ = new nlist($<pn>3); } ; moe : ID { $$ = $<pn>1; $<pn>$->tp = moe_type; } | ID ASSIGN e { $$ = $<pn>1; $<pn>$->tp = moe_type; $<pn>$->n_initializer = $<pe>3; } | /* empty: handle trailing CM: enum e { a,b, }; */ { $$ = 0; } ; class_dcl : class_head cl_mem_list RC { ccl->mem_list = name_unlist($<nl>2); end_cl(); } | class_head cl_mem_list RC TYPE { ccl->mem_list = name_unlist($<nl>2); end_cl(); error("`;' or declaratorX afterCD"); lex_unget($4); /* lex_unget($4); but only one unget, sorry */ } ; class_head : AGGR LC { $$ = start_cl($<t>1,0,0); } | AGGR tag LC { $$ = start_cl($<t>1,$<pn>2,0); } | AGGR tag COLON TNAME LC { $$ = start_cl($<t>1,$<pn>2,$<pn>4); if ($<t>1 == STRUCT) ccl->pubbase = 1; } | AGGR tag COLON PR TNAME LC { $$ = start_cl($<t>1,$<pn>2,$<pn>5); ccl->pubbase = 1; } /* | AGGR tag COLON TNAME TNAME LC { char* s = $<pn>4->string; if (strcmp(s,"public")) error("unX %s after : inCD",s); $$ = start_cl($<t>1,$<pn>2,$<pn>5); ccl->pubbase = 1; } | AGGR tag COLON TNAME ID LC { char* s = $<pn>4->string; if (strcmp(s,"public")) error("unX %s after : inCD",s); $$ = start_cl($<t>1,$<pn>2,$<pn>5); ccl->pubbase = 1; } | AGGR tag COLON ID LC { $$ = start_cl($<t>1,$<pn>2,$<pn>4); if ($<t>1 == STRUCT) ccl->pubbase = 1; } */ ; tag : ID { $$ = $1; } | TNAME ; cl_mem_list : cl_mem_list cl_mem { if ($2) { if ($1) $<nl>1->add_list($<pn>2); else $<nl>$ = new nlist($<pn>2); } } | %prec EMPTY { $$ = 0; } ; cl_mem : data_dcl | att_fct_def SM | att_fct_def | fct_def SM | fct_def | fct_dcl | PR COLON { $$ = new name; $<pn>$->base = $<t>1; } | tn_list tag SM { Pname n = Ncopy($<pn>2); n->n_qualifier = $<pn>1; n->base = PUBLIC; $$ = n; } ; /************* declarators: returns Pname **********************/ /* a ``decl'' is used for function and data declarations, and for member declarations (it has a name) an ``arg_decl'' is used for argument declarations (it may or may not have a name) an ``cast_decl'' is used for casts (it does not have a name) a ``new_decl'' is used for type specifiers for the NEW operator (it does not have a name, and PtoF and PtoV cannot be expressed) */ fname : ID { $$ = $<pn>1; } | COMPL TNAME { $$ = Ncopy($<pn>2); $<pn>$->n_oper = DTOR; } | OPERATOR oper { $$ = new name(oper_name($2)); $<pn>$->n_oper = $<t>2; } | OPERATOR c_type { Pname n = $<pn>2; n->string = "_type"; n->n_oper = TYPE; n->n_initializer = (Pexpr)n->tp; n->tp = 0; $$ = n; } ; oper : PLUS | MINUS | MUL | AND | OR | ER | SHIFTOP | EQUOP | DIVOP | RELOP | ANDAND | OROR | LP RP { $$ = CALL; } | LB RB { $$ = DEREF; } | NOT | COMPL | ICOP | ASOP | ASSIGN | NEW { $$ = NEW; } | DELETE { $$ = DELETE; } | REF { $$ = REF; } | DOT { $$ = DOT; } ; tn_list : TNAME DOT { if ( $<pn>1->tp->base != COBJ ) error( "T of%n not aC", $<pn>1 ); } | TNAME MEM { if ( $<pn>1->tp->base != COBJ ) error( "T of%n not aC", $<pn>1 ); } | tn_list TNAME DOT { error("CNs do not nest"); } | tn_list ID DOT { error("CNs do not nest"); } ; decl : decl arg_list { Freturns($2) = $<pn>1->tp; $<pn>1->tp = $<pt>2; } | TNAME arg_list { Pname n = $<pn>1; $$ = Ncopy(n); if (ccl && strcmp(n->string,ccl->string)) n->hide(); $<pn>$->n_oper = TNAME; Freturns($2) = $<pn>$->tp; $<pn>$->tp = $<pt>2; } | decl LP elist RP /* may be class object initializer, class object vector initializer, if not elist will be a CM or an ID */ { TOK k = 1; Pname l = $<pn>3; if (fct_void && l==0) k = 0; $<pn>1->tp = new fct($<pn>1->tp,l,k); } | TNAME LP elist RP { TOK k = 1; Pname l = $<pn>3; if (fct_void && l==0) k = 0; $$ = Ncopy($<pn>1); $<pn>$->n_oper = TNAME; $<pn>$->tp = new fct(0,l,k); } | TNAME LP MEMPTR decl RP arg_list { memptrdcl($<pn>3,$<pn>1,$<pt>6,$<pn>4); $$ = $4; } | fname | ID DOT fname { $$ = Ncopy($<pn>3); $<pn>$->n_qualifier = $1; } | tn_list fname { $$ = $2; set_scope($<pn>1); $<pn>$->n_qualifier = $<pn>1; } | tn_list TNAME { $$ = Ncopy($<pn>2); set_scope($<pn>1); $<pn>$->n_oper = TNAME; $<pn>$->n_qualifier = $<pn>1; } | ptr decl %prec MUL { Ptyp($1) = $<pn>2->tp; $<pn>2->tp = $<pt>1; $$ = $2; } | ptr TNAME %prec MUL { $$ = Ncopy($<pn>2); $<pn>$->n_oper = TNAME; $<pn>2->hide(); $<pn>$->tp = $<pt>1; } | TNAME vec %prec LB { $$ = Ncopy($<pn>1); $<pn>$->n_oper = TNAME; $<pn>1->hide(); $<pn>$->tp = $<pt>2; } | decl vec %prec LB { Vtype($2) = $<pn>1->tp; $<pn>1->tp = $<pt>2; } | LP decl RP arg_list { Freturns($4) = $<pn>2->tp; $<pn>2->tp = $<pt>4; $$ = $2; } | LP decl RP vec { Vtype($4) = $<pn>2->tp; $<pn>2->tp = $<pt>4; $$ = $2; } ; arg_decl : ID { $$ = $<pn>1; } | ptr TNAME %prec MUL { $$ = Ncopy($<pn>2); $<pn>$->n_oper = TNAME; $<pn>2->hide(); $<pn>$->tp = $<pt>1; } | %prec NO_ID { $$ = new name; } | ptr arg_decl %prec MUL { Ptyp($1) = $<pn>2->tp; $<pn>2->tp = (Ptype)$1; $$ = $2; } | arg_decl vec %prec LB { Vtype($2) = $<pn>1->tp; $<pn>1->tp = (Ptype)$2; } | LP arg_decl RP arg_list { Freturns($4) = $<pn>2->tp; $<pn>2->tp = (Ptype)$4; $$ = $2; } | LP arg_decl RP vec { Vtype($4) = $<pn>2->tp; $<pn>2->tp = (Ptype)$4; $$ = $2; } ; new_decl : %prec NO_ID { $$ = new name; } | ptr new_decl %prec MUL { Ptyp($1) = $<pn>2->tp; $<pn>2->tp = (Ptype)$1; $$ = $2; } | new_decl vec %prec LB { Vtype($2) = $<pn>1->tp; $<pn>1->tp = (Ptype)$2; } ; cast_decl : %prec NO_ID { $$ = new name; } | ptr cast_decl %prec MUL { Ptyp($1) = $<pn>2->tp; $<pn>2->tp = (Ptype)$1; $$ = $2; } | cast_decl vec %prec LB { Vtype($2) = $<pn>1->tp; $<pn>1->tp = (Ptype)$2; } | LP cast_decl RP arg_list { Freturns($4) = $<pn>2->tp; $<pn>2->tp = $<pt>4; $$ = $2; } | LP cast_decl RP vec { Vtype($4) = $<pn>2->tp; $<pn>2->tp = $<pt>4; $$ = $2; } ; c_decl : %prec NO_ID { $$ = new name; } | ptr c_decl %prec MUL { Ptyp($1) = $<pn>2->tp; $<pn>2->tp = (Ptype)$1; $$ = $2; } ; /***************** statements: returns Pstmt *****************/ stmt_list : stmt_list statement { if ($2) if ($1) $<sl>1->add($<ps>2); else { $<sl>$ = new slist($<ps>2); stmt_seen = 1; } } | statement { if ($1) { $<sl>$ = new slist($<ps>1); stmt_seen = 1; } } ; condition : LP e RP { $$ = $2; if ($<pe>$ == dummy) error("empty condition"); stmt_seen = 1; } ; block : LC { cd_vec[cdi] = cd; stmt_vec[cdi] = stmt_seen; tn_vec[cdi++] = modified_tn; cd = 0; stmt_seen = 0; modified_tn = 0; } stmt_list RC { Pname n = name_unlist(cd); Pstmt ss = stmt_unlist($<sl>3); $$ = new block($<l>1,n,ss); if (modified_tn) restore(); cd = cd_vec[--cdi]; stmt_seen = stmt_vec[cdi]; modified_tn = tn_vec[cdi]; if (cdi < 0) error('i',"block level(%d)",cdi); } | LC RC { $$ = new block($<l>1,0,0); } | LC error RC { $$ = new block($<l>1,0,0); } ; simple : e { $$ = new estmt(SM,curloc,$<pe>1,0); } | BREAK { $$ = new stmt(BREAK,$<l>1,0); } | CONTINUE { $$ = new stmt(CONTINUE,$<l>1,0); } | RETURN e { $$ = new estmt(RETURN,$<l>1,$<pe>2,0); } | GOTO ID { $$ = new lstmt(GOTO,$<l>1,$<pn>2,0); } | DO { stmt_seen=1; } statement WHILE condition { $$ = new estmt(DO,$<l>1,$<pe>5,$<ps>3); } ; statement : simple SM | ASM LP STRING RP SM { if (stmt_seen) $$ = new estmt(ASM,curloc,(Pexpr)$<s>3,0); else { Pname n = new name(make_name('A')); n->tp = new basetype(ASM,(Pname)$<s>3); if (cd) cd->add_list(n); else cd = new nlist(n); $$ = 0; } } | data_dcl { Pname n = $<pn>1; if (n) if (stmt_seen) { $$ = new block(n->where,n,0); $<ps>$->base = DCL; } else { if (cd) cd->add_list(n); else cd = new nlist(n); $$ = 0; } } | att_fct_def { Pname n = $<pn>1; lex_unget(RC); error(&n->where,"%n's definition is nested (did you forget a ``}''?)",n); if (cd) cd->add_list(n); else cd = new nlist(n); $$ = 0; } | block | IF condition statement { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,0); } | IF condition statement ELSE statement { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,$<ps>5); } | WHILE condition statement { $$ = new estmt(WHILE,$<l>1,$<pe>2,$<ps>3); } | FOR LP { stmt_seen=1; } statement e SM e RP statement { $$ = new forstmt($<l>1,$<ps>4,$<pe>5,$<pe>7,$<ps>9); } | SWITCH condition statement { $$ = new estmt(SWITCH,$<l>1,$<pe>2,$<ps>3); } | ID COLON { $$ = $1; stmt_seen=1; } statement { Pname n = $<pn>3; $$ = new lstmt(LABEL,n->where,n,$<ps>4); } | CASE { stmt_seen=1; } e COLON statement { if ($<pe>3 == dummy) error("empty case label"); $$ = new estmt(CASE,$<l>1,$<pe>3,$<ps>5); } | DEFAULT COLON { stmt_seen=1; } statement { $$ = new stmt(DEFAULT,$<l>1,$<ps>4); } ; /********************* expressions: returns Pexpr **************/ elist : ex_list { Pexpr e = expr_unlist($<el>1); while (e && e->e1==dummy) { register Pexpr ee2 = e->e2; if (ee2) error("EX inEL"); delete e; e = ee2; } $$ = e; } ex_list : initializer %prec CM { $<el>$ = new elist(new expr(ELIST,$<pe>1,0)); } | ex_list CM initializer { $<el>1->add(new expr(ELIST,$<pe>3,0)); } ; initializer : e %prec CM | LC elist RC { Pexpr e; if ($2) e = $<pe>2; else e = new expr(ELIST,dummy,0); $$ = new expr(ILIST,e,0); } ; e : e ASSIGN e { binop: $$ = new expr($<t>2,$<pe>1,$<pe>3); } | e PLUS e { goto binop; } | e MINUS e { goto binop; } | e MUL e { goto binop; } | e AND e { goto binop; } | e OR e { goto binop; } | e ER e { goto binop; } | e SHIFTOP e { goto binop; } | e EQUOP e { goto binop; } | e DIVOP e { goto binop; } | e RELOP e { goto binop; } | e ANDAND e { goto binop; } | e OROR e { goto binop; } | e ASOP e { goto binop; } | e CM e { goto binop; } | e QUEST e COLON e { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); } | DELETE term { $$ = new expr(DELETE,$<pe>2,0); } | DELETE LB e RB term { $$ = new expr(DELETE,$<pe>5,$<pe>3); } | term | %prec NO_EXPR { $$ = dummy; } ; term : TYPE LP elist RP { $$ = new texpr(VALUE,tok_to_type($<t>1),$<pe>3); } | TNAME LP elist RP { $$ = new texpr(VALUE,$<pn>1->tp,$<pe>3); } | NEW new_type { Ptype t = $<pn>2->tp; $$ = new texpr(NEW,t,0); } | NEW LP new_type RP { Ptype t = $<pn>3->tp; $$ = new texpr(NEW,t,0); } | term ICOP { $$ = new expr($<t>2,$<pe>1,0); } | CAST cast_type ENDCAST term %prec ICOP { $$ = new texpr(CAST,$<pn>2->tp,$<pe>4); } | MUL term { $$ = new expr(DEREF,$<pe>2,0); } | AND term { $$ = new expr(ADDROF,0,$<pe>2); } | MINUS term { $$ = new expr(UMINUS,0,$<pe>2); } | PLUS term { $$ = new expr(UPLUS,0,$<pe>2); } | NOT term { $$ = new expr(NOT,0,$<pe>2); } | COMPL term { $$ = new expr(COMPL,0,$<pe>2); } | ICOP term { $$ = new expr($<t>1,0,$<pe>2); } | SIZEOF term { $$ = new texpr(SIZEOF,0,$<pe>2); } | SIZEOF CAST cast_type ENDCAST %prec SIZEOF { $$ = new texpr(SIZEOF,$<pn>3->tp,0); } | term LB e RB { $$ = new expr(DEREF,$<pe>1,$<pe>3); } /* | term NOT term %prec LB { $$ = new expr(DEREF,$<pe>1,$<pe>3); } */ | term LP elist RP { Pexpr ee = $<pe>3; Pexpr e = $<pe>1; if (e->base == NEW) e->e1 = ee; else $$ = new call(e,ee); } | term REF prim { $$ = new ref(REF,$<pe>1,$<pn>3); } | term REF MUL term { $$ = new expr(REF,$<pe>1,$<pe>4); } | term REF TNAME { $$ = new ref(REF,$<pe>1,Ncopy($<pn>3)); } | term DOT prim { $$ = new ref(DOT,$<pe>1,$<pn>3); } | term DOT MUL term { $$ = new expr(DOT,$<pe>1,$<pe>4); } | term DOT TNAME { $$ = new ref(DOT,$<pe>1,Ncopy($<pn>3)); } | MEM tag { $$ = Ncopy($<pn>2); $<pn>$->n_qualifier = sta_name; } | prim | LP e RP { $$ = $2; } | ZERO { $$ = zero; } | ICON { $$ = new expr(ICON,0,0); $<pe>$->string = $<s>1; } | FCON { $$ = new expr(FCON,0,0); $<pe>$->string = $<s>1; } | STRING { $$ = new expr(STRING,0,0); $<pe>$->string = $<s>1; } | CCON { $$ = new expr(CCON,0,0); $<pe>$->string = $<s>1; } | THIS { $$ = new expr(THIS,0,0); } ; prim : ID { $$ = $<pn>1; } | TNAME MEM tag { $$ = Ncopy($<pn>3); $<pn>$->n_qualifier = $<pn>1; } | ID MEM tag { $$ = Ncopy($<pn>3); look_for_hidden($<pn>1,$<pn>$); } | OPERATOR oper { $$ = new name(oper_name($2)); $<pn>$->n_oper = $<t>2; } | TNAME MEM OPERATOR oper { $$ = new name(oper_name($4)); $<pn>$->n_oper = $<t>4; $<pn>$->n_qualifier = $<pn>1; } | ID MEM OPERATOR oper { $$ = new name(oper_name($4)); $<pn>$->n_oper = $<t>4; look_for_hidden($<pn>1,$<pn>$); } | OPERATOR c_type { $$ = $2; sig_name($<pn>$); } | TNAME MEM OPERATOR c_type { $$ = $4; sig_name($<pn>$); $<pn>$->n_qualifier = $<pn>1; } | ID MEM OPERATOR c_type { $$ = $4; sig_name($<pn>$); look_for_hidden($<pn>1,$<pn>$); } ; /****************** abstract types (return type Pname) *************/ cast_type : type cast_decl { $$ = Ncast($1,$<pn>2); } ; c_tp : TYPE { $$ = new basetype($<t>1,0); } | TNAME { $$ = new basetype(TYPE,$<pn>1); } ; c_type : c_tp c_decl { $$ = Ncast($1,$<pn>2); } ; new_type : type new_decl { $$ = Ncast($1,$<pn>2); }; arg_type : type arg_decl { $$ = Ndata($1,$<pn>2); } | type arg_decl ASSIGN initializer { $$ = Ndata($1,$<pn>2); $<pn>$->n_initializer = $<pe>4; } ; arg_list : LP arg_type_list RP { $$ = new fct(0,name_unlist($<nl>2),1); } | LP arg_type_list ELLIPSIS RP { $$ = new fct(0,name_unlist($<nl>2),ELLIPSIS); } | LP arg_type_list CM ELLIPSIS RP { $$ = new fct(0,name_unlist($<nl>2),ELLIPSIS); } ; arg_type_list : arg_type_list CM at { if ($3) if ($1) $<nl>1->add($<pn>3); else { error("AD syntax"); $<nl>$ = new nlist($<pn>3); } else error("AD syntax"); } | at %prec CM { if ($1) $<nl>$ = new nlist($<pn>1); } ; at : arg_type | %prec EMPTY { $$ = 0; } ; ptr : MUL %prec NO_ID { $$ = new ptr(PTR,0); } | AND %prec NO_ID { $$ = new ptr(RPTR,0); } | MUL TYPE { TOK t = $<t>2; switch (t) { case VOLATILE: error('w',"\"%k\" not implemented (ignored)",t); $$ = new ptr(PTR,0); break; default: error("syntax error: *%k",t); case CONST: $$ = new ptr(PTR,0,1); } } | AND TYPE { TOK t = $<t>2; switch (t) { case VOLATILE: error('w',"\"%k\" not implemented (ignored)",t); $$ = new ptr(RPTR,0); break; default: error("syntax error: &%k",t); case CONST: $$ = new ptr(RPTR,0,1); } } | MEMPTR %prec NO_ID { Pptr p = new ptr(PTR,0); p->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp); $$ = p; } ; vec : LB e RB { $$ = new vec(0,($<pe>2!=dummy)?$<pe>2:0 ); } /* | NOT term %prec LB { $$ = new vec(0,$<pe>2); } */ | NOT %prec LB { $$ = new vec(0,0); } ; %%