static struct block *cast_expression(struct block *block) { struct typetree *type; struct token tok; struct symbol *sym; /* This rule needs two lookahead; to see beyond the initial parenthesis if * it is actually a cast or an expression. */ if (peek().token == '(') { tok = peekn(2); switch (tok.token) { case IDENTIFIER: sym = sym_lookup(&ns_ident, tok.strval); if (!sym || sym->symtype != SYM_TYPEDEF) break; case FIRST(type_name): consume('('); type = declaration_specifiers(NULL); if (peek().token != ')') { type = declarator(type, NULL); } consume(')'); block = cast_expression(block); block->expr = eval_cast(block, block->expr, type); return block; default: break; } } return unary_expression(block); }
TOKEN parameter_declaration(void) { SYMBOL s = symalloc(); TOKEN dec = NULL; declaration_specifiers(s); dec = declarator(s); set_token_symbol_type(dec,s); return dec; }
void declaratorlist(void){ declarator(); while(lookahead == ','){ match(','); declarator(); } }
int function_definition(void) { if( declaration_specifiers() ) { declarator(); if( declaration_list() ) { } } else if ( declarator() ) { if( declaration_list() ) { } } else { abort(); } compound_statement(); }
/** 形参列表 <parameter_type_list>::=<type_specifier>{<declarator>} {<TK_COMMA><type_specifier>{<declarator>}}<TK_COMMA><TK_ELLIPSIS> */ void parameter_type_list(){ int func_call; /// 原书将这个变量当做参数 get_token(); while(TK_CLOSEPA != token){ if(!type_specifier()) error("invalid identifier"); declarator(); if(TK_CLOSEPA == token) break; skip(TK_COMMA); if(TK_ELLIPSIS == token){ func_call = KW_CDECL; get_token(); break; } } syntax_state = SNTX_DELAY; skip(TK_CLOSEPA); get_token(); if(TK_BEGIN == token) /// define function syntax_state = SNTX_LF_HT; else syntax_state = SNTX_NUL; syntax_indent(); }
/** @brief 解析外部命令 @param l 存储类型,局部的or全局的 */ void external_declaration(int l){ if(!type_specifier()){ expect("<类型区分符>"); } if(token == TK_SEMICOLON){ get_token(); return; } while(1){ declarator(); if(token == TK_BEGIN){ if(l == SC_LOCAL){ error("不支持函数嵌套定义"); } funcbody(); break; }else{ if(token == TK_ASSIGN){ get_token(); initializer(); } if(token == TK_COMMA){ get_token(); }else{ syntax_state = SNTX_LE_HT; skip(TK_SEMICOLON); break; } } } }
/** 外部声明 <external_declaration>::=<type_specifier>(<TK_SEMICOLON> |<declarator><funcbody> |<declarator>[<TK_ASSIGN><initializer>] {TK_COMMA><declarator>[<TK_ASSIGN><initializer>]}<TK_SEMICOLON> ) DO:parse external statement storage type:local | global */ void external_declaration(int l){ if(!type_specifier()) expect("<Type specifier>"); if(token == TK_SEMICOLON){ get_token(); return; } while(1){ declarator(); if(token == TK_BEGIN){ if(l == SC_LOCAL) error("don't support function nesting define"); funcbody(); break; }else { if(token == TK_ASSIGN){ get_token(); initializer(); } if(token == TK_COMMA) get_token(); else{ syntax_state = SNTX_LF_HT; skip(TK_SEMICOLON); break; } } } }
int parameter_list(ParserState* ps) { if (curris(ps, PLParen)) { enterblk(); while (ps->curr != 0) { VVar id; if (!declarator(ps, &id)) parerr(ps, "invalid parameter syntax"); if (curris(ps, PComma)) { Ast* comma = ps->curr; if (comma->next != 0) { ast_swap(comma, comma->next); ast_rmnext(comma); } } else if (ps->curr != 0) { parerr(ps, "expecting \',\' in parameter list"); } } exitblk(); return 1; } else return 0; }
int init_declarator(void) { declarator(); if( lookaheadT.type == EQUAL ) { match(EQUAL); initializer(); } }
int declaration(char* result) { char token[MAXTOKEN]; char token2[MAXTOKEN]; bool is_const = false; int type = -1; int ret = 0; ret -= try_tokens_until(&type, token, try_declaration, try_declarator, "Missing data type to form a declaration"); if (type == NAME) { if (gettoken(token2) == CONST) { // T const XXX is_const = true; } else { unget_token(); } } else if (type == CONST) { is_const = true; ret -= try_tokens_until(&type, token, try_name, try_declarator, "Missing data type to form a declaration"); } ret += declarator(result); strcat(result, " "); if (is_const) { strcat(result, "const "); } strcat(result, token); return ret; }
static void params(CTy *fty) { int sclass; CTy *t; char *name; SrcPos *pos; fty->Func.isvararg = 0; if(tok->k == ')') return; for(;;) { pos = &tok->pos; t = declspecs(&sclass); t = declarator(t, &name, 0); if(sclass != SCNONE) errorposf(pos, "storage class not allowed in parameter decl"); vecappend(fty->Func.params, newnamety(name, t)); if(tok->k != ',') break; next(); } if(tok->k == TOKELLIPSIS) { fty->Func.isvararg = 1; next(); } }
/*----------------------------------------------------------------------------*/ void c_semantic::free_declarator(c_context & context, c_token token) { if (1 == options.verbose_flag) { printf("## c_semantic::free_declarator()\n\n"); } if (NO_CLASS_STATUS != context.class_specifier_status) { printf ("error c_semantic::free_declarator() NO_CLASS_STATUS != context.class_specifier_status\n\n"); exit(-1); } c_declarator declarator(token, vector_decl_specifier); context.declarator = declarator; /* template <class myType> myType GetMax (myType a, myType b) { return (a>b?a:b); } we are in GetMax line ... */ if ( TEMPLATE_DECLARATION == context.template_status ) { context.declarator.is_template = 1; } }
static CTy * directdeclarator(CTy *basety, char **name) { CTy *ty, *stub; *name = 0; switch(tok->k) { case '(': expect('('); stub = gcmalloc(sizeof(CTy)); *stub = *basety; ty = declarator(stub, name, 0); expect(')'); *stub = *declaratortail(basety); return ty; case TOKIDENT: if(name) *name = tok->v; next(); return declaratortail(basety); default: if(!name) errorposf(&tok->pos, "expected ident or ( but got %s", tokktostr(tok->k)); return declaratortail(basety); } errorf("unreachable"); return 0; }
static void param_declarator(node_t ** ty, struct token **id) { if (token->id == '*') { node_t *pty = ptr_decl(); prepend_type(ty, pty); } if (token->id == '(') { if (first_decl(lookahead())) { abstract_declarator(ty); } else { node_t *type1 = *ty; node_t *rtype = NULL; expect('('); param_declarator(&rtype, id); expect(')'); if (token->id == '(' || token->id == '[') { node_t *faty; cc_assert(id); if (*id) { faty = func_or_array(false, NULL); } else { faty = func_or_array(true, NULL); } attach_type(&faty, type1); attach_type(&rtype, faty); } *ty = rtype; } } else if (token->id == '[') { abstract_declarator(ty); } else if (token->id == ID) { declarator(ty, id, NULL); } }
/* Declarator is what introduces names into the program. */ static CTy * declarator(CTy *basety, char **name, Node **init) { CTy *t; while (tok->k == TOKCONST || tok->k == TOKVOLATILE) next(); switch(tok->k) { case '*': next(); basety = mkptr(basety); t = declarator(basety, name, init); return t; default: t = directdeclarator(basety, name); if(tok->k == '=') { if(!init) errorposf(&tok->pos, "unexpected initializer"); next(); *init = declinit(); } else { if(init) *init = 0; } return t; } }
static int variable_decl(ParserState* ps) { Ast* rvar = ps->curr; if (stepifis(ps, RVar)) { int count = 0; while (count == 0 || curris(ps, PComma)) { if (stepifis(ps, PComma)) free(ast_rmnext(rvar)); VVar id; if (declarator(ps, &id)) { ast_next_to_last_child(rvar); } else { parerr(ps, "invalid declarator"); break; } count++; } if (!stepifis(ps, PSemi)) { parerr(ps, "expecting ',' or ';'"); } return 1; } else return 0; }
static Node * decl() { Node *n, *init; char *name; CTy *type, *basety; SrcPos *pos; Sym *sym; Vec *syms; int sclass; pos = &tok->pos; syms = vec(); basety = declspecs(&sclass); while(tok->k != ';' && tok->k != TOKEOF) { type = declarator(basety, &name, &init); switch(sclass){ case SCNONE: if(isglobal()) { sclass = SCGLOBAL; } else { sclass = SCAUTO; } break; case SCTYPEDEF: if(init) errorposf(pos, "typedef cannot have an initializer"); break; } if(!name) errorposf(pos, "decl needs to specify a name"); sym = definesym(pos, sclass, name, type, init); vecappend(syms, sym); if(isglobal() && tok->k == '{') { if(init) errorposf(pos, "function declaration has an initializer"); if(type->t != CFUNC) errorposf(pos, "expected a function"); curfunc = mknode(NFUNC, pos); curfunc->type = type; curfunc->Func.name = name; curfunc->Func.params = vec(); curfunc->Func.stkslots = vec(); fbody(); definesym(pos, sclass, name, type, curfunc); curfunc = 0; goto done; } if(tok->k == ',') next(); else break; } expect(';'); done: n = mknode(NDECL, pos); n->Decl.syms = syms; return n; }
int struct_declarator(void) { if( declarator() ) { } if( lookaheadT.type == COLON ) { match(COLON); constant_expression(); } }
static void fields(node_t * sym) { int follow[] = {INT, CONST, '}', IF, 0}; node_t *sty = SYM_TYPE(sym); if (!first_decl(token)) { error("expect type name or qualifiers"); return; } struct vector *v = vec_new(); do { node_t *basety = specifiers(NULL, NULL); for (;;) { node_t *field = new_field(); if (token->id == ':') { bitfield(field); FIELD_TYPE(field) = basety; } else { node_t *ty = NULL; struct token *id = NULL; declarator(&ty, &id, NULL); attach_type(&ty, basety); if (token->id == ':') bitfield(field); FIELD_TYPE(field) = ty; if (id) { for (int i = 0; i < vec_len(v); i++) { node_t *f = vec_at(v, i); if (FIELD_NAME(f) && !strcmp(FIELD_NAME(f), id->name)) { errorf(id->src, "redefinition of '%s'", id->name); break; } } FIELD_NAME(field) = id->name; AST_SRC(field) = id->src; } } vec_push(v, field); if (token->id != ',') break; expect(','); ensure_field(field, vec_len(v), false); } match(';', follow); ensure_field(vec_tail(v), vec_len(v), isstruct(sty) && !first_decl(token)); } while (first_decl(token)); TYPE_FIELDS(sty) = (node_t **) vtoa(v); set_typesize(sty); }
/** 结构声明 <struct_declaration>::= <type_specifier><declarator>{<TK_COMMA><declarator>} <TK_SEMICOLON> */ void struct_declaration(){ type_specifier(); while(1){ declarator(); if(token == TK_SEMICOLON) break; skip(TK_COMMA); } syntax_state = SNTX_LF_HT; skip(TK_SEMICOLON); }
/* Parse function and array declarators. Some trickery is needed to handle * declarations like `void (*foo)(int)`, where the inner *foo has to be * traversed first, and prepended on the outer type `* (int) -> void` * afterwards making it `* (int) -> void`. * The type returned from declarator has to be either array, function or * pointer, thus only need to check for type->next to find inner tail. */ static struct typetree *direct_declarator( struct typetree *base, const char **symbol) { struct typetree *type = base; struct typetree *head, *tail = NULL; struct token ident; switch (peek().token) { case IDENTIFIER: ident = consume(IDENTIFIER); if (!symbol) { error("Unexpected identifier in abstract declarator."); exit(1); } *symbol = ident.strval; break; case '(': consume('('); type = head = tail = declarator(NULL, symbol); while (tail->next) { tail = (struct typetree *) tail->next; } consume(')'); break; default: break; } while (peek().token == '[' || peek().token == '(') { switch (peek().token) { case '[': type = direct_declarator_array(base); break; case '(': consume('('); type = parameter_list(base); consume(')'); break; default: assert(0); } if (tail) { tail->next = type; type = head; } base = type; } return type; }
/*----------------------------------------------------------------------------*/ void c_semantic::identifier_typedef(c_context & context, c_token token) { if (1 == options.verbose_flag) { printf("## void c_semantic::identifier_typedef(c_token token) token.text[%s]\n\n",token.text.c_str()); } /* ## it must search in the stack stack 0 class A{}; stack 1 int A; typedef class A t_A; typedef vector < c_decl_specifier > t_vector_decl_specifier; */ if ( 0 != context.class_name_declaration.size() ) { c_symbol symbol(token); symbol.is_typedef = 1; symbol.typedef_points_to = context.class_name_declaration; symbol.type = TYPEDEF_NAME; if ( 1 == context.is_template_instantiation ) { symbol.is_template_instantiation = context.is_template_instantiation; symbol.vector_template_argument = context.vector_template_argument; symbol.map_template_argument = context.map_template_argument; } ts.insert(symbol); } if (NO_CLASS_STATUS == context.class_specifier_status) { c_declarator declarator(token, vector_decl_specifier); declarator.is_typedef = 1; if ( 1 == context.is_template_instantiation ) { declarator.is_template_instantiation = context.is_template_instantiation; declarator.vector_template_argument = context.vector_template_argument; declarator.map_template_argument = context.map_template_argument; } context.declarator = declarator; } }
/* Parse call to builtin symbol __builtin_va_arg, which is the result of calling * va_arg(arg, T). Return type depends on second input argument. */ static struct block *parse__builtin_va_arg(struct block *block) { struct typetree *type; consume('('); block = assignment_expression(block); consume(','); type = declaration_specifiers(NULL); if (peek().token != ')') { type = declarator(type, NULL); } consume(')'); block->expr = eval__builtin_va_arg(block, block->expr, type); return block; }
TOKEN init_declarator(SYMBOL s) { TOKEN decl = declarator(s); TOKEN tok = peek_token(); if(tok == NULL) { return NULL; } TOKEN initial_value = NULL; if(true == token_matches_operator(tok, ASSIGNMENT)) { initial_value = NULL;//initializer(); } return decl; }
// Parse a concept definition. // // concept-declaration: // 'concept' identifier '<' template-parameter-list '>' concept-definition // // TODO: I'm not sure that I like this syntax. Maybe we should make // concepts look like any other template: // // template<typename T> concept C = ... // // Note that this would allow for non-template concepts as well: // // concept C = X && Y && Z; // // The benefit to doing this is that C would now be usable as a constraint // in non-function templates. // // FIXME: Make this happen. Decl& Parser::concept_declaration() { Token tok = require(tk::concept_tok); Name& n = declarator(); // Enter_template_parameter_scope pscope(cxt); match(tk::lt_tok); Decl_list ps = template_parameter_list(); match(tk::gt_tok); // Point of declaration. Enter the associated context prior // to defininging the concept. Decl& con = on_concept_declaration(tok, n, ps); // Enter_scope cscope(cxt, cxt.make_concept_scope(con)); concept_definition(con); return con; }
int direct_declarator(void) { if( lookaheadT.type == ID ) { match(ID); } else if( lookaheadT.type == LPAREN ) { match(LPAREN); declarator(); match(RPAREN); } else if( direct_declarator() ) { if( lookaheadT.type == LBRACKET ) { match(LBRACKET); if( constant_expression() ) { } match(RBRACKET); } else if( lookaheadT.type == LPAREN ) { match(LPAREN); if( parameter_type_list() ) { } else if ( identifier_list() ) { } match(RPAREN); } } }
/* FOLLOW(parameter-list) = { ')' }, peek to return empty list; even though K&R * require at least specifier: (void) * Set parameter-type-list = parameter-list, including the , ... */ static struct typetree *parameter_list(const struct typetree *base) { struct typetree *func = type_init(T_FUNCTION); func->next = base; while (peek().token != ')') { const char *name = NULL; struct typetree *type; type = declaration_specifiers(NULL); type = declarator(type, &name); if (is_void(type)) { if (nmembers(func)) { error("Incomplete type in parameter list."); } break; } type_add_member(func, name, type); if (peek().token != ',') { break; } consume(','); if (peek().token == ')') { error("Unexpected trailing comma in parameter list."); exit(1); } else if (peek().token == DOTS) { consume(DOTS); assert(!is_vararg(func)); type_add_member(func, "...", NULL); assert(is_vararg(func)); break; } } return func; }
static void declarator(node_t ** ty, struct token **id, int *params) { int follow[] = { ',', '=', IF, 0 }; cc_assert(ty && id); if (token->id == '*') { node_t *pty = ptr_decl(); prepend_type(ty, pty); } if (token->id == ID) { *id = token; expect(ID); if (token->id == '[' || token->id == '(') { node_t *faty = func_or_array(false, params); prepend_type(ty, faty); } } else if (token->id == '(') { node_t *type1 = *ty; node_t *rtype = NULL; expect('('); declarator(&rtype, id, params); match(')', follow); if (token->id == '[' || token->id == '(') { node_t *faty = func_or_array(false, params); attach_type(&faty, type1); attach_type(&rtype, faty); } else { attach_type(&rtype, type1); } *ty = rtype; } else { error("expect identifier or '('"); } }
int direct_declarator(char* result) { char token[MAXTOKEN]; int type = -1; int ret = 0; ret -= try_tokens_until(&type, token, try_direct_declarator, try_func_array, "Missing declarator's name"); if (type == '(') { ret += declarator(result); ret -= try_tokens_until(&type, token, try_right_paran, try_func_array, "Missing ')' to close a declarator"); } else if (type == NAME) { strcat(result, token); strcat(result, ":"); } while (true) { type = gettoken(token); if (type == '[') { strcat(result, " array"); ret -= try_tokens_until(&type, token, try_array, try_func_array, "Missing ']' to close an array"); if (type == NUMBER) { strcat(result, "["); strcat(result, token); strcat(result, "]"); ret -= try_tokens_until(&type, token, try_right_bracket, try_func_array, "Missing ']' to close an array"); } if (ret == 0) { strcat(result, " of"); } } else if (type == '(') { strcat(result, " function"); bool has_param = false; while (true) { ret -= try_tokens_until(&type, token, try_func_param, try_func_array, "Missing ')' to close a function"); if (try_declaration(type)) { if (!has_param) { strcat(result, " with parameter ["); has_param = true; } unget_token(); ret += declaration(result); ret -= try_tokens_until(&type, token, try_func_comma, try_func_array_dcl, "Missing ')' to close a function"); if (type == ',') { strcat(result, ", "); continue; } else if (try_declaration(type)) { continue; } else { // Fall through to break } } break; } if (ret == 0) { if (has_param) { strcat(result, "]"); } strcat(result, " returning"); } } else { // Don't try to do error recovery here. Simply ends a // direct declarator and leaves the remaining tokens // to the outside. unget_token(); break; } } return ret; }
int parameter_declaration(void) { declaration_specifiers(); if( declarator() ) { } else if( abstract_declarator() ) { } }