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. */
} \
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); \
*/
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)
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.
*/
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;
}
/**
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;
}
/**
expect('(');
- statement_t *rem = current_loop;
int top = environment_top();
context_t *last_context = context;
set_context(&statement->context);
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;
}
/**
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(';');
*/
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;
}
/**
*/
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;
}
/**