// parse init declarator util meeting a ';' static struct init_declarator_list *parse_init_declarator_list(struct parser *parser) { // need check for empty init_declarator_list here union token tok = lexer_next_token(parser->lexer); if (tok.tok_tag == TOK_SEMICOLON) { return NULL; } lexer_put_back(parser->lexer, tok); return parse_init_declarator_list_with_la(parser, parse_declarator(parser)); }
static struct direct_declarator *parse_direct_declarator(struct parser *parser) { struct direct_declarator *dd = direct_declarator_init(); union token tok = lexer_next_token(parser->lexer); if (tok.tok_tag == TOK_IDENTIFIER) { dd->id = tok.id.s; } else if (tok.tok_tag == TOK_LPAREN) { union token nxtok = lexer_next_token(parser->lexer); if (nxtok.tok_tag == TOK_RPAREN || initiate_declaration_specifiers(nxtok)) { lexer_put_back(parser->lexer, nxtok); lexer_put_back(parser->lexer, tok); goto parse_suffix; } lexer_put_back(parser->lexer, nxtok); dd->declarator = parse_declarator(parser); expect(parser->lexer, TOK_RPAREN); } else { // pass thru lexer_put_back(parser->lexer, tok); } parse_suffix: while (1) { tok = lexer_next_token(parser->lexer); if (tok.tok_tag == TOK_LBRACKET) { tok = lexer_next_token(parser->lexer); struct direct_declarator_suffix *suff = mallocz(sizeof(*suff)); if (tok.tok_tag == TOK_RBRACKET) { suff->empty_bracket = 1; } else { lexer_put_back(parser->lexer, tok); struct constant_expression *expr = parse_constant_expression(parser); expect(parser->lexer, TOK_RBRACKET); suff->const_expr = expr; } dynarr_add(dd->suff_list, suff); } else if (tok.tok_tag == TOK_LPAREN) { tok = lexer_next_token(parser->lexer); struct direct_declarator_suffix *suff = mallocz(sizeof(*suff)); if (tok.tok_tag == TOK_RPAREN) { suff->empty_paren = 1; } else { lexer_put_back(parser->lexer, tok); struct parameter_type_list *param_type_list = parse_parameter_type_list(parser); expect(parser->lexer, TOK_RPAREN); suff->param_type_list = param_type_list; } dynarr_add(dd->suff_list, suff); } else { lexer_put_back(parser->lexer, tok); break; } } return dd; }
struct type_name *parse_type_name(struct parser *parser) { struct specifier_qualifier_list *sqlist = parse_specifier_qualifier_list(parser); union token tok = lexer_next_token(parser->lexer); struct declarator *declarator = NULL; lexer_put_back(parser->lexer, tok); if (initiate_abstract_declarator(tok)) { declarator = parse_declarator(parser); if (!is_abstract_declarator(declarator)) { panic("require abstract declarator"); } } return type_name_init(sqlist, declarator); }
int main(void) { char input_buffer[MAX_STRING]; char type[MAX_SUBSTRING]; char declarator[MAX_SUBSTRING]; char identifier[MAX_SUBSTRING]; while (get_string(input_buffer)) { type[0] = identifier[0] = declarator[0] = '\0'; parse_type(type, input_buffer); parse_declarator(identifier, declarator, input_buffer); printf("Declare %s as %s %s\n", identifier, declarator, type); } return 0; }
// assume no EOF found; static struct external_declaration *parse_external_decl(struct parser *parser) { struct declaration_specifiers *decl_specifiers = parse_declaration_specifiers(parser); struct external_declaration *external_decl = external_declaration_init(decl_specifiers); struct declarator *declarator = NULL; // compound statement case struct compound_statement *compound_stmt = NULL; // declaration case struct init_declarator_list *init_declarator_list = NULL; // check for empty init_declarator_list case, similar to what we do in // parse_init_declarator_list union token tok = lexer_next_token(parser->lexer); if (tok.tok_tag == TOK_SEMICOLON) { } else { lexer_put_back(parser->lexer, tok); declarator = parse_declarator(parser); tok = lexer_next_token(parser->lexer); if (tok.tok_tag == TOK_LBRACE) { lexer_push_typedef_tab(parser->lexer); register_func_parameters_for_typedef(parser, declarator); lexer_put_back(parser->lexer, tok); compound_stmt = parse_compound_statement(parser); lexer_pop_typedef_tab(parser->lexer); // set external decl external_decl->func_def_declarator = declarator; external_decl->compound_stmt = compound_stmt; } else { lexer_put_back(parser->lexer, tok); init_declarator_list = parse_init_declarator_list_with_la(parser, declarator); // set external decl external_decl->init_declarator_list = init_declarator_list; register_potential_typedefs(parser, decl_specifiers, init_declarator_list); } } return external_decl; }
struct struct_declarator *parse_struct_declarator(struct parser *parser) { struct declarator *declarator = NULL; struct constant_expression *const_expr = NULL; union token tok = lexer_next_token(parser->lexer); if (tok.tok_tag != TOK_COLON) { lexer_put_back(parser->lexer, tok); declarator = parse_declarator(parser); tok = lexer_next_token(parser->lexer); } if (tok.tok_tag == TOK_COLON) { const_expr = parse_constant_expression(parser); } else { lexer_put_back(parser->lexer, tok); } return struct_declarator_init(declarator, const_expr); }
// TODO support abstract_declarator static struct parameter_declaration *parse_parameter_declaration(struct parser *parser) { int old_disable_typedef = lexer_push_config(parser->lexer, disable_typedef, 0); struct declaration_specifiers *decl_specifiers = parse_declaration_specifiers(parser); // to support item *item, which item is a type name // we need disable typedef after we get decl specifiers // // To support the case that the declarator recursively contains type (func ptr as // parameter), we enable typedef at the beginning (void) lexer_push_config(parser->lexer, disable_typedef, 1); union token tok = lexer_next_token(parser->lexer); struct declarator *declarator = NULL; if (initiate_declarator(tok)) { lexer_put_back(parser->lexer, tok); declarator = parse_declarator(parser); } else { lexer_put_back(parser->lexer, tok); } lexer_pop_config(parser->lexer, disable_typedef, old_disable_typedef); return parameter_declaration_init(decl_specifiers, declarator); }
static struct init_declarator *parse_init_declarator(struct parser *parser) { struct declarator *declarator = parse_declarator(parser); return parse_init_declarator_with_la(parser, declarator); }