📄 cp-spew.c
字号:
/* consume_token(); */ /* already eaten by frob_identifier?... */ return yychar;}/* token[0] == AGGR (struct/union/enum) * thus, token[1] is either a TYPENAME or a TYPENAME_DEFN * if token[2] == '{' or ':' then it's TYPENAME_DEFN */static intdo_aggr (){ int yc1, yc2; scan_tokens (2); yc1 = nth_token (1)->yychar; if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME) return 0; yc2 = nth_token (2)->yychar; if (yc2 == '{' || yc2 == ':') { switch (yc1) { case TYPENAME: nth_token (1)->yychar = TYPENAME_DEFN; break; case PTYPENAME: nth_token (1)->yychar = PTYPENAME_DEFN; break; case IDENTIFIER: nth_token (1)->yychar = IDENTIFIER_DEFN; break; default: my_friendly_abort (102); } } return 0;} static struct tokenfrob_identifier (){ /* we could have a type, if it is followed by :: (if so, suck it all up); */ /* we could have a ptypename; */ /* we could have a normal identifier. */ tree t1; struct token rt; scan_tokens(1); rt = *nth_token(0);#if 0 if (nth_token(1)->yychar == '<') { t1 = hack_ptype(); /* suck up the whole thing */ if (t1) { rt.yylval.ttype = t1; rt.yychar = TYPENAME; *nth_token(0) = rt; } /* else fall out bottom */ } #endif if (nth_token(1)->yychar == SCOPE) {#if 0 t1 = hack_more_ids(0); if (t1 && TREE_CODE(t1) == SCOPE_REF)#else t1 = hack_more_ids(0, nth_token (0)->yylval.ttype); if (t1)#endif { rt.yylval.ttype = t1; rt.yychar = SCOPED_TYPENAME ; return rt; } else { /* deal with types (enums?) in classes... */ struct token *tok; tree ta, tb; scan_tokens(3); /* Have to check for a type conversion operator to a nested type. */ if (nth_token (2)->yychar == OPERATOR) tok = nth_token (3); else tok = nth_token(2); if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME) { ta = build_parse_node (SCOPE_REF, nth_token(0)->yylval.ttype, tok->yylval.ttype); tb = resolve_scope_to_name (NULL_TREE, ta); if (tb != NULL_TREE) { if (nth_token (2)->yychar == OPERATOR) { /* Have to keep these tokens around so we can finish parsing the declaration. What do we do for int foo::operator bar::baz (); where bar is a nested class in foo? */ nth_token (3)->yychar = TYPENAME; nth_token (3)->yylval.ttype = tb; } else { consume_token (); /* base type */ consume_token (); /* SCOPE */ consume_token (); /* member type */ rt.yychar = TYPENAME; rt.yylval.ttype = tb; rt.end_of_file = tok->end_of_file; return rt; } } } /* else fall out bottom */ } } consume_token(); return rt;}/* When this function is called, nth_token(0) is the current token we are scanning. This means that the next token we'll scan is nth_token (1). Usually the next token we'll scan is nth_token (0) (and the current token is in [yylval,yychar]). */treearbitrate_lookup (name, exp_decl, type_decl) tree name, exp_decl, type_decl;{ int ch; scan_tokens (3); ch = nth_token (1)->yychar; switch (ch) { case '(': case LEFT_RIGHT: /* If we guessed wrong here, `build_functional_cast' can fix it. */ return type_decl; case '=': if (global_bindings_p ()) /* Probably a default parameter. */ return type_decl; /* Probably not an initialization. */ return exp_decl; case '[': /* This needs special help because an expression inside the brackets means nothing. */ { int i; for (i = 0; i < 42; i++) { int ith_yychar; scan_tokens (3+i); ith_yychar = nth_token (2+i)->yychar; /* If we hit an undefined identifier, assume the decl in arbitration is its type specifier. */ if (ith_yychar == IDENTIFIER && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0) return type_decl; else if (ith_yychar == ']') { /* There are only a few things we expect after a ']' in a declarator. */ i += 1; scan_tokens (4+i); ith_yychar = nth_token (2+i)->yychar; /* These are inconclusive. */ if (ith_yychar == LEFT_RIGHT || ith_yychar == '(' || ith_yychar == '[' || ith_yychar == ',') continue; /* stmt or decl? We'll probably never know. */ else if (ith_yychar == ';') goto warn_ambiguous; if (ith_yychar == '=') { if (nth_token (3+i)->yychar == '{') return type_decl; continue; } /* Whatever it is, it looks like we're processing an expr. */ return exp_decl; } } goto warn_ambiguous; } case ',': case ';': case '&': case '<': case '*': case ']': case ')': case '>': /* see if the next token looks like it wants to be part of a declaration list or an expression list. */ { int i; /* Some heuristics: if we are inside a function definition, prefer the local declaration. */ if (! global_bindings_p ()) { if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl) return exp_decl; if (IDENTIFIER_LOCAL_VALUE (name) != type_decl && IDENTIFIER_CLASS_VALUE (name) == exp_decl) return exp_decl; } /* If these symbols follow in a list, we know it's a list of expressions. */ if (follows_identifier[nth_token (2)->yychar]) return exp_decl; /* If we see a id&, or id&) the we are probably in an argument list. */ if (ch=='&' && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')')) return type_decl; /* Look for the first identifier or other distinguishing token we find in the next several tokens. */ for (i = 0; i < 42; i++) { int ith_yychar; scan_tokens (3+i); ith_yychar = nth_token (2+i)->yychar; if (ith_yychar == IDENTIFIER) { tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1); if (as_type && TREE_CODE (as_type) != TYPE_DECL) return exp_decl; /* An undeclared identifier or a typename means we're probably looking at a typename. */ return type_decl; } else if (ith_yychar == EMPTY || follows_identifier[ith_yychar]) return exp_decl; else if (follows_typename[ith_yychar]) return type_decl; /* stmt or decl? We'll probably never know. */ else if (ith_yychar == ';') goto warn_ambiguous; } goto warn_ambiguous; } default: if (follows_identifier[ch]) return exp_decl; if (follows_typename[ch]) return type_decl; /* Fall through... */ warn_ambiguous: warning ("name `%s' could be type or expression; compiler assuming type", IDENTIFIER_POINTER (DECL_NAME (type_decl))); return type_decl; }}/* now returns decl_node */#if 0static treehack_ptype(){ /* when we get here, we know that [0] is a ptype and [1] is '<'. * now we loop over simple parameters. */ struct token this_param; int n = 2; tree tplist = 0; tree tc; scan_tokens(n+1); while((this_param = *nth_token(n)).yychar != '>') { /* if it is a type, add it to the list */ tree thistype; switch(this_param.yychar) { case IDENTIFIER: case TYPENAME: case TYPESPEC: break; default: return 0; } thistype = this_param.yylval.ttype; thistype = lookup_name(thistype, 1); thistype = TREE_TYPE (thistype); if (tplist) tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype)); else tplist = build_tree_list(NULL_TREE, thistype); /* then suck up the comma */ n++; scan_tokens(n+1); this_param = *nth_token(n); if (this_param.yychar == ',') { n++; scan_tokens(n+1); continue; } if (this_param.yychar == '>') break; return 0; } /* once we're done, lookup_template_class -> identifier */ tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist); /* then lookup_name on that to get a type, if there is one */ tc = lookup_name (tc, 1); if (tc) { int i; /* don't actually eat the trailing '>'... we can replace it! */ for (i=0; i<n; i++) consume_token(); /* IDENTIFIER_TYPE_VALUE (DECL_NAME (tc)) = */ return DECL_NAME (tc); } return NULL_TREE;}#endif#if 0static treehack_more_ids (n) int n;{ /* * The recursion should probably do consume_tokens(), since once we've started * down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just * get as much as we can, make SCOPE_REF's out of it, and return it. */ struct token this_iter, this2_iter; int tmp_y; scan_tokens(n+1); this_iter = *nth_token(n); tmp_y = nth_token(n)->yychar; if (tmp_y == IDENTIFIER || tmp_y == TYPENAME) { scan_tokens(n+2+2); if (nth_token(n+1)->yychar == SCOPE) { if (nth_token(n+1+2)->yychar == SCOPE) { tree hmi; consume_token(); /* last IDENTIFIER (this_iter) */ consume_token(); /* last SCOPE */ this2_iter = *nth_token(n); hmi = hack_more_ids (n); if (hmi) return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi); consume_token(); /* last IDENTIFIER (this2_iter) */ return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, this2_iter.yylval.ttype); } else { /* consume_token(); */ /* last IDENTIFIER */ /* leave whatever else we got */ /* return this_iter.yylval.ttype; */ return NULL_TREE; } } } return NULL_TREE; /* @@ may need to backtrack */}#else/* niklas@appli.se says: I didn't understand how the code above was intended * to work, so I rewrote it (also changed the interface a bit). This code * dives down an IDENTIFIER/TYPENAME SCOPE ... chain as long as the parsed * type prefix constitutes recognizable (by resolve_scope_to_name) types. * Interface changed like this: * 1. Takes an extra argument containing the name of the the type recognized * so far. * 2. Now returns the name of the type instead of a SCOPE_REF. */static treehack_more_ids(n, outer) int n; tree outer;{ int ch; tree type, val; scan_tokens (n + 2); if (nth_token (n + 1)->yychar != SCOPE || ((ch = nth_token (n + 2)->yychar) != IDENTIFIER && ch != TYPENAME)) return NULL_TREE; val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype); type = resolve_scope_to_name (NULL_TREE, val); if (type == NULL_TREE) return NULL_TREE; consume_token (); consume_token (); val = hack_more_ids (n, type); if (! val) consume_token (); return val ? val : type;}#endif#if 0static struct tokenhack_scope (){ /* we've got a :: - what follows is either a global var or a type. */ /* hmm, template names can be in the global scope too... */ tree t1; struct token rt; scan_tokens(1); if (nth_token(1)->yychar == IDENTIFIER) { /* @@ this is probably not right, but doesn't get hit yet */ t1 = build_parse_node (SCOPE_REF, NULL_TREE, /* to get "global" scope */ hack_more_ids(0)); /* do some prefetching */ rt.yylval.ttype = t1; rt.yychar = /*SCOPED_*/TYPENAME; return rt; } else { rt = *nth_token(0); consume_token(); return rt; }}#endif /* * Generations: * * PINST: PTYPE { saved_arg_count = arg_count($1) } * '<' { arg_c = 0; } PARGS '>' * ; * PARG: TYPE * | VALUE * ; * (of course the arg counting doesn't work for recursion... Do it right.) * PARGS: PARG { assert(arg_c == saved_arg_count); } * | PARG ',' PARGS { arg_c++; } * ; * ATYPE: PINST * | TYPEID * ; * TYPE: ATYPE * | ATYPE { basetype = $1; } '::' TYPEKIDS * ; * TYPEKIDS: TYPE { assert ($1 is a member of basetype); } * | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); } * ; * * * state0: ; ATYPE * TYPE '<': ac = args($0), base = CALL state1, state3 * TYPE '::': base=$0, state3 * else return TYPE * state1: ; begin PARGS * if(ac < list length) punt * PARG ",": add to list, state1 * PARG ">": add to list, return * else unravel * state3: ; begin TYPEKIDS * TYPE: */ #ifdef SPEW_DEBUG /* debug_yychar takes a yychar (token number) value and prints its name. */static intdebug_yychar (yy) int yy;{ /* In cp-parse.y: */ extern char *debug_yytranslate (); int i; if(yy<256) { fprintf (stderr, "<%d: %c >\n", yy, yy); return 0; } fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy)); return 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -