X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=7d9b3347762a90999398158718d0e5bf4fbc0460;hb=65dfc72272eeb6beba7d3a53ebd9a46488000c81;hp=7fd54f44869ae23af61fcda3ca8a34ba0b35d611;hpb=356aba533706e40254ebb601f8cad4ed6d82e665;p=cparser diff --git a/parser.c b/parser.c index 7fd54f4..7d9b334 100644 --- a/parser.c +++ b/parser.c @@ -50,7 +50,8 @@ static declaration_t *last_declaration = NULL; static declaration_t *current_function = NULL; static switch_statement_t *current_switch = NULL; static statement_t *current_loop = NULL; -static goto_statement_t *goto_list = NULL; +static goto_statement_t *goto_first = NULL; +static goto_statement_t *goto_last = NULL; static struct obstack temp_obst; /** The current source position. */ @@ -462,14 +463,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); \ @@ -2700,19 +2693,24 @@ static void parse_kr_declaration_list(declaration_t *declaration) */ static void check_for_missing_labels(void) { - const goto_statement_t *goto_statement, *next; - - for (goto_statement = goto_list; + bool first_err = true; + for (const goto_statement_t *goto_statement = goto_first; goto_statement != NULL; - goto_statement = next) { + goto_statement = goto_statement->next) { const declaration_t *label = goto_statement->label; if (label->source_position.input_name == NULL) { + if (first_err) { + first_err = false; + diagnosticf("%s: In function '%Y':\n", + current_function->source_position.input_name, + current_function->symbol); + } errorf(goto_statement->statement.source_position, "label '%Y' used but not defined", label->symbol); } } - goto_list = NULL; + goto_first = goto_last = NULL; } static void parse_external_declaration(void) @@ -5067,6 +5065,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. */ @@ -5078,18 +5085,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; } /** @@ -5103,19 +5105,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; } /** @@ -5131,7 +5128,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); @@ -5141,31 +5137,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; } /** @@ -5193,8 +5185,11 @@ static statement_t *parse_goto(void) statement->label = label; /* remember the goto's in a list for later checking */ - statement->next = goto_list; - goto_list = statement; + if (goto_last == NULL) { + goto_first = goto_last = statement; + } else { + goto_last->next = statement; + } expect(';'); @@ -5206,19 +5201,20 @@ 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_base_t *statement; if (current_loop == NULL) { errorf(HERE, "continue statement not within loop"); - return NULL; + statement = NULL; + } else { + statement = allocate_ast_zero(sizeof(statement[0])); + statement->kind = STATEMENT_CONTINUE; + statement->source_position = token.source_position; } - return statement; + eat(T_continue); + expect(';'); + + return (statement_t*)statement; } /** @@ -5226,18 +5222,20 @@ 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_base_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_ast_zero(sizeof(statement[0])); + statement->kind = STATEMENT_BREAK; + statement->source_position = token.source_position; } - return statement; + + eat(T_break); + expect(';'); + + return (statement_t*)statement; } /**