X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=inline;f=parser.c;h=1550ee7e707e835a336affbcd75b92ed78273710;hb=d1a006c8b9421a33ebf262fe1e5537ae5a41e605;hp=b78d49b65249f75d113add76cccfd45694e46d13;hpb=bf31a06b276a73ea4dbe0b2099b60f43bda797ad;p=cparser diff --git a/parser.c b/parser.c index b78d49b..1550ee7 100644 --- a/parser.c +++ b/parser.c @@ -136,6 +136,11 @@ static void *allocate_ast_zero(size_t size) return res; } +static declaration_t *allocate_declaration_zero(void) +{ + return allocate_ast_zero(sizeof(*allocate_declaration_zero())); +} + /** * Returns the size of a statement node. * @@ -463,14 +468,6 @@ static void eat_paren(void) } \ next_token(); -#define expect_fail(expected) \ - if(UNLIKELY(token.type != (expected))) { \ - parse_error_expected(NULL, (expected), 0); \ - eat_statement(); \ - goto fail; \ - } \ - next_token(); - #define expect_block(expected) \ if(UNLIKELY(token.type != (expected))) { \ parse_error_expected(NULL, (expected), 0); \ @@ -830,8 +827,8 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right, incompatible_assign_types: /* TODO: improve error message */ - errorf(HERE, "incompatible types in %s", context); - errorf(HERE, "'%T' <- '%T'", orig_type_left, orig_type_right); + errorf(HERE, "incompatible types in %s: '%T' <- '%T'", + context, orig_type_left, orig_type_right); } static expression_t *parse_constant_expression(void) @@ -856,7 +853,7 @@ static type_t *make_global_typedef(const char *name, type_t *type) { symbol_t *const symbol = symbol_table_insert(name); - declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); + declaration_t *const declaration = allocate_declaration_zero(); declaration->namespc = NAMESPACE_NORMAL; declaration->storage_class = STORAGE_CLASS_TYPEDEF; declaration->type = type; @@ -871,15 +868,15 @@ static type_t *make_global_typedef(const char *name, type_t *type) return typedef_type; } -static const char *parse_string_literals(void) +static string_t parse_string_literals(void) { assert(token.type == T_STRING_LITERAL); - const char *result = token.v.string; + string_t result = token.v.string; next_token(); - while(token.type == T_STRING_LITERAL) { - result = concat_strings(result, token.v.string); + while (token.type == T_STRING_LITERAL) { + result = concat_strings(&result, &token.v.string); next_token(); } @@ -982,13 +979,13 @@ static designator_t *parse_designation(void) #endif static initializer_t *initializer_from_string(array_type_t *type, - const char *string) + const string_t *const string) { /* TODO: check len vs. size of array type */ (void) type; initializer_t *initializer = allocate_initializer_zero(INITIALIZER_STRING); - initializer->string.string = string; + initializer->string.string = *string; return initializer; } @@ -1022,7 +1019,7 @@ static initializer_t *initializer_from_expression(type_t *type, case EXPR_STRING_LITERAL: if (element_type->atomic.akind == ATOMIC_TYPE_CHAR) { return initializer_from_string(array_type, - expression->string.value); + &expression->string.value); } case EXPR_WIDE_STRING_LITERAL: { @@ -1267,9 +1264,15 @@ static initializer_t *parse_initializer(type_t *type) if(token.type != '{') { expression_t *expression = parse_assignment_expression(); + if (expression->base.datatype == NULL) { + /* something bad happens, don't produce further errors */ + return NULL; + } initializer_t *initializer = initializer_from_expression(type, expression); if(initializer == NULL) { - errorf(HERE, "initializer expression '%E', type '%T' is incompatible with type '%T'", expression, expression->base.datatype, type); + errorf(HERE, + "initializer expression '%E' of type '%T' is incompatible with type '%T'", + expression, expression->base.datatype, type); } return initializer; } @@ -1333,13 +1336,9 @@ static declaration_t *parse_compound_type_specifier(bool is_struct) } if(declaration == NULL) { - declaration = allocate_ast_zero(sizeof(declaration[0])); - - if(is_struct) { - declaration->namespc = NAMESPACE_STRUCT; - } else { - declaration->namespc = NAMESPACE_UNION; - } + declaration = allocate_declaration_zero(); + declaration->namespc = + (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION); declaration->source_position = token.source_position; declaration->symbol = symbol; declaration->parent_context = context; @@ -1373,7 +1372,7 @@ static declaration_t *parse_compound_type_specifier(bool is_struct) return declaration; } -static void parse_enum_entries(enum_type_t *const enum_type) +static void parse_enum_entries(type_t *const enum_type) { eat('{'); @@ -1384,15 +1383,15 @@ static void parse_enum_entries(enum_type_t *const enum_type) } do { - declaration_t *entry = allocate_ast_zero(sizeof(entry[0])); - if(token.type != T_IDENTIFIER) { parse_error_expected("while parsing enum entry", T_IDENTIFIER, 0); eat_block(); return; } + + declaration_t *const entry = allocate_declaration_zero(); entry->storage_class = STORAGE_CLASS_ENUM_ENTRY; - entry->type = (type_t*) enum_type; + entry->type = enum_type; entry->symbol = token.v.symbol; entry->source_position = token.source_position; next_token(); @@ -1436,9 +1435,8 @@ static type_t *parse_enum_specifier(void) } if(declaration == NULL) { - declaration = allocate_ast_zero(sizeof(declaration[0])); - - declaration->namespc = NAMESPACE_ENUM; + declaration = allocate_declaration_zero(); + declaration->namespc = NAMESPACE_ENUM; declaration->source_position = token.source_position; declaration->symbol = symbol; declaration->parent_context = context; @@ -1457,7 +1455,7 @@ static type_t *parse_enum_specifier(void) append_declaration(declaration); declaration->init.is_defined = 1; - parse_enum_entries(&type->enumt); + parse_enum_entries(type); parse_attributes(); } @@ -1880,8 +1878,7 @@ static declaration_t *parse_identifier_list(void) declaration_t *declarations = NULL; declaration_t *last_declaration = NULL; do { - declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); - + declaration_t *const declaration = allocate_declaration_zero(); declaration->source_position = token.source_position; declaration->symbol = token.v.symbol; next_token(); @@ -2278,7 +2275,7 @@ static declaration_t *parse_declarator( const declaration_specifiers_t *specifiers, bool may_be_abstract) { type_t *type = specifiers->type; - declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); + declaration_t *const declaration = allocate_declaration_zero(); declaration->storage_class = specifiers->storage_class; declaration->modifiers = specifiers->decl_modifiers; declaration->is_inline = specifiers->is_inline; @@ -2479,7 +2476,7 @@ static void parse_init_declarator_rest(declaration_t *declaration) case INITIALIZER_STRING: { initializer_string_t *const string = &initializer->string; - cnst->conste.v.int_value = strlen(string->string) + 1; + cnst->conste.v.int_value = string->string.size; break; } @@ -2513,8 +2510,7 @@ static void parse_anonymous_declaration_rest( { eat(';'); - declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); - + declaration_t *const declaration = allocate_declaration_zero(); declaration->type = specifiers->type; declaration->storage_class = specifiers->storage_class; declaration->source_position = specifiers->source_position; @@ -2850,15 +2846,12 @@ static void parse_struct_declarators(const declaration_specifiers_t *specifiers) type_t *type = make_bitfield_type(base_type, size); - declaration = allocate_ast_zero(sizeof(declaration[0])); - + declaration = allocate_declaration_zero(); declaration->namespc = NAMESPACE_NORMAL; declaration->storage_class = STORAGE_CLASS_NONE; declaration->source_position = token.source_position; declaration->modifiers = specifiers->decl_modifiers; declaration->type = type; - - record_declaration(declaration); } else { declaration = parse_declarator(specifiers,/*may_be_abstract=*/true); @@ -2940,10 +2933,15 @@ static expression_t *create_invalid_expression(void) return expression; } +/** + * Prints an error message if an expression was expected but not read + */ static expression_t *expected_expression_error(void) { - errorf(HERE, "expected expression, got token '%K'", &token); - + /* skip the error message if the error token was read */ + if (token.type != T_ERROR) { + errorf(HERE, "expected expression, got token '%K'", &token); + } next_token(); return create_invalid_expression(); @@ -3013,8 +3011,7 @@ static declaration_t *create_implicit_function(symbol_t *symbol, free_type(ntype); } - declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); - + declaration_t *const declaration = allocate_declaration_zero(); declaration->storage_class = STORAGE_CLASS_EXTERN; declaration->type = type; declaration->symbol = symbol; @@ -3294,7 +3291,6 @@ static expression_t *parse_function_keyword(void) expression->expression.kind = EXPR_FUNCTION; expression->expression.datatype = type_string; - expression->value = current_function->symbol->string; return (expression_t*) expression; } @@ -3313,7 +3309,6 @@ static expression_t *parse_pretty_function_keyword(void) expression->expression.kind = EXPR_PRETTY_FUNCTION; expression->expression.datatype = type_string; - expression->value = current_function->symbol->string; return (expression_t*) expression; } @@ -4975,7 +4970,7 @@ static declaration_t *get_label(symbol_t *symbol) } /* otherwise we need to create a new one */ - declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); + declaration_t *const declaration = allocate_declaration_zero(); declaration->namespc = NAMESPACE_LABEL; declaration->symbol = symbol; @@ -5073,6 +5068,15 @@ static statement_t *parse_switch(void) return (statement_t*) statement; } +static statement_t *parse_loop_body(statement_t *const loop) +{ + statement_t *const rem = current_loop; + current_loop = loop; + statement_t *const body = parse_statement(); + current_loop = rem; + return body; +} + /** * Parse a while statement. */ @@ -5084,18 +5088,13 @@ static statement_t *parse_while(void) statement->statement.kind = STATEMENT_WHILE; statement->statement.source_position = token.source_position; - statement_t *rem = current_loop; - expect_fail('('); + expect('('); statement->condition = parse_expression(); - expect_fail(')'); + expect(')'); - statement->body = parse_statement(); - current_loop = rem; + statement->body = parse_loop_body((statement_t*)statement); return (statement_t*) statement; -fail: - current_loop = rem; - return NULL; } /** @@ -5109,19 +5108,14 @@ static statement_t *parse_do(void) statement->statement.kind = STATEMENT_DO_WHILE; statement->statement.source_position = token.source_position; - statement_t *rem = current_loop; - statement->body = parse_statement(); - expect_fail(T_while); - expect_fail('('); + statement->body = parse_loop_body((statement_t*)statement); + expect(T_while); + expect('('); statement->condition = parse_expression(); - expect_fail(')'); - current_loop = rem; + expect(')'); expect(';'); return (statement_t*) statement; -fail: - current_loop = rem; - return NULL; } /** @@ -5137,7 +5131,6 @@ static statement_t *parse_for(void) expect('('); - statement_t *rem = current_loop; int top = environment_top(); context_t *last_context = context; set_context(&statement->context); @@ -5147,31 +5140,27 @@ static statement_t *parse_for(void) parse_declaration(record_declaration); } else { statement->initialisation = parse_expression(); - expect_fail(';'); + expect(';'); } } else { - expect_fail(';'); + expect(';'); } if(token.type != ';') { statement->condition = parse_expression(); } - expect_fail(';'); + expect(';'); if(token.type != ')') { statement->step = parse_expression(); } - expect_fail(')'); - statement->body = parse_statement(); + expect(')'); + statement->body = parse_loop_body((statement_t*)statement); assert(context == &statement->context); set_context(last_context); environment_pop_to(top); - current_loop = rem; return (statement_t*) statement; -fail: - current_loop = rem; - return NULL; } /** @@ -5215,18 +5204,19 @@ static statement_t *parse_goto(void) */ static statement_t *parse_continue(void) { - eat(T_continue); - expect(';'); - - statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->kind = STATEMENT_CONTINUE; - statement->base.source_position = token.source_position; - + statement_t *statement; if (current_loop == NULL) { errorf(HERE, "continue statement not within loop"); - return NULL; + statement = NULL; + } else { + statement = allocate_statement_zero(STATEMENT_CONTINUE); + + statement->base.source_position = token.source_position; } + eat(T_continue); + expect(';'); + return statement; } @@ -5235,17 +5225,19 @@ static statement_t *parse_continue(void) */ static statement_t *parse_break(void) { - eat(T_break); - expect(';'); - - statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->kind = STATEMENT_BREAK; - statement->base.source_position = token.source_position; - + statement_t *statement; if (current_switch == NULL && current_loop == NULL) { errorf(HERE, "break statement not within loop or switch"); - return NULL; + statement = NULL; + } else { + statement = allocate_statement_zero(STATEMENT_BREAK); + + statement->base.source_position = token.source_position; } + + eat(T_break); + expect(';'); + return statement; }