/**
* Expect the current token is the expected token.
- * If not, generate an error, eat the current statement,
- * and goto the error_label label.
- */
-#define expect(expected, error_label) \
- do { \
- if (UNLIKELY(token.kind != (expected))) { \
- parse_error_expected(NULL, (expected), NULL); \
- add_anchor_token(expected); \
- eat_until_anchor(); \
- rem_anchor_token(expected); \
- if (token.kind != (expected)) \
- goto error_label; \
- } \
- next_token(); \
- } while (0)
+ * If not, generate an error and skip until the next anchor.
+ */
+static void expect(token_kind_t const expected)
+{
+ if (UNLIKELY(token.kind != expected)) {
+ parse_error_expected(NULL, expected, NULL);
+ add_anchor_token(expected);
+ eat_until_anchor();
+ rem_anchor_token(expected);
+ if (token.kind != expected)
+ return;
+ }
+ eat(expected);
+}
static symbol_t *expect_identifier(char const *const context, source_position_t *const pos)
{
*anchor = argument;
anchor = &argument->next;
} while (next_if(','));
- expect(')', end_error);
-end_error:
+ expect(')');
return first;
}
{
attribute_t *attribute = allocate_attribute_zero(ATTRIBUTE_GNU_ASM);
eat(T_asm);
-
- expect('(', end_error);
+ expect('(');
attribute->a.arguments = parse_attribute_arguments();
return attribute;
-
-end_error:
- return NULL;
}
static symbol_t *get_symbol_from_token(void)
attribute_t **anchor = &first;
eat(T___attribute__);
- expect('(', end_error);
- expect('(', end_error);
+ expect('(');
+ expect('(');
add_anchor_token(')');
add_anchor_token(',');
rem_anchor_token(',');
rem_anchor_token(')');
- expect(')', end_error);
- expect(')', end_error);
-
-end_error:
+ expect(')');
+ expect(')');
return first;
}
add_anchor_token(']');
designator->array_index = parse_constant_expression();
rem_anchor_token(']');
- expect(']', end_error);
+ expect(']');
break;
case '.':
designator = allocate_ast_zero(sizeof(designator[0]));
return NULL;
break;
default:
- expect('=', end_error);
+ expect('=');
return result;
}
*anchor = designator;
anchor = &designator->next;
}
-end_error:
- return NULL;
}
static initializer_t *initializer_from_string(array_type_t *const type,
env);
rem_anchor_token('}');
- if (type != NULL) {
- ascend_from_subtype(path);
- expect('}', end_error);
- } else {
- expect('}', end_error);
+ expect('}');
+
+ if (!type)
goto error_parse_next;
- }
+
+ ascend_from_subtype(path);
}
} else {
/* must be an expression */
if (token.kind == '}') {
break;
}
- expect(',', end_error);
+ add_anchor_token('}');
+ expect(',');
+ rem_anchor_token('}');
if (token.kind == '}') {
break;
}
max_index = path.max_index;
DEL_ARR_F(path.path);
- expect('}', end_error);
-end_error:;
+ expect('}');
} else {
/* parse_scalar_initializer() also works in this case: we simply
* have an expression without {} around it */
rem_anchor_token(',');
rem_anchor_token('}');
- expect('}', end_error);
-
-end_error:
- ;
+ expect('}');
}
static type_t *parse_enum_specifier(void)
type_t *type;
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
expression_t *expression = NULL;
}
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
type_t *typeof_type = allocate_type_zero(TYPE_TYPEOF);
typeof_type->typeoft.expression = expression;
typeof_type->typeoft.typeof_type = type;
return typeof_type;
-end_error:
- return NULL;
}
typedef enum specifiers_t {
static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
{
- expect('(', end_error);
+ attribute_property_argument_t *const property = allocate_ast_zero(sizeof(*property));
- attribute_property_argument_t *property
- = allocate_ast_zero(sizeof(*property));
+ expect('(');
add_anchor_token(')');
add_anchor_token(',');
}
add_anchor_token(T_IDENTIFIER);
- expect('=', end_error1);
-end_error1:
+ expect('=');
rem_anchor_token(T_IDENTIFIER);
symbol_t *const sym = expect_identifier("while parsing property declspec", NULL);
attribute->a.property = property;
- expect(')', end_error);
-
-end_error:
+ expect(')');
return attribute;
}
{
eat(T__declspec);
- expect('(', end_error);
+ expect('(');
if (token.kind != ')') {
add_anchor_token(')');
rem_anchor_token(')');
}
- expect(')', end_error);
-end_error:
+ expect(')');
return first;
}
parameters_finished:
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
-end_error:
restore_anchor_state(',', saved_comma_state);
}
errorf(&array->base.pos, "static array parameters require a size");
rem_anchor_token(']');
- expect(']', end_error);
-
-end_error:
+ expect(']');
return cons;
}
env->must_be_abstract = true;
}
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
}
break;
}
*anchor = inner_types;
return first;
-end_error:
- return NULL;
}
static type_t *construct_declarator_type(construct_type_t *construct_list,
}
rem_anchor_token(',');
rem_anchor_token(';');
- expect(';', end_error);
+ expect(';');
-end_error:
anonymous_entity = NULL;
}
static void parse_compound_declarators(compound_t *compound,
const declaration_specifiers_t *specifiers)
{
+ add_anchor_token(';');
+ add_anchor_token(',');
do {
entity_t *entity;
}
}
} while (next_if(','));
- expect(';', end_error);
+ rem_anchor_token(',');
+ rem_anchor_token(';');
+ expect(';');
-end_error:
anonymous_entity = NULL;
}
default:
rem_anchor_token('}');
- expect('}', end_error);
-end_error:
+ expect('}');
/* §6.7.2.1:7 */
compound->complete = true;
return;
type_t *type = parse_typename();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
if (token.kind == '{') {
return parse_compound_literal(&pos, type);
}
return cast;
-end_error:
- return create_error_expression();
}
/**
expression->base.type = type;
rem_anchor_token(')');
- expect(')', end_error);
-
-end_error:
+ expect(')');
return expression;
}
expression_t *result = parse_expression();
result->base.parenthesized = true;
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
-end_error:
return result;
}
designator->source_position = *HERE;
designator->array_index = parse_expression();
rem_anchor_token(']');
- expect(']', end_error);
+ expect(']');
if (designator->array_index == NULL) {
return NULL;
}
}
return result;
-end_error:
- return NULL;
}
/**
eat(T___builtin_offsetof);
- expect('(', end_error);
+ expect('(');
+ add_anchor_token(')');
add_anchor_token(',');
type_t *type = parse_typename();
rem_anchor_token(',');
- expect(',', end_error);
- add_anchor_token(')');
+ expect(',');
designator_t *designator = parse_designator();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
expression->offsetofe.type = type;
expression->offsetofe.designator = designator;
DEL_ARR_F(path.path);
return expression;
-end_error:
- return create_error_expression();
}
/**
eat(T___builtin_va_start);
- expect('(', end_error);
+ expect('(');
+ add_anchor_token(')');
add_anchor_token(',');
expression->va_starte.ap = parse_assignment_expression();
rem_anchor_token(',');
- expect(',', end_error);
+ expect(',');
expression_t *const expr = parse_assignment_expression();
if (expr->kind == EXPR_REFERENCE) {
entity_t *const entity = expr->reference.entity;
} else {
expression->va_starte.parameter = &entity->variable;
}
- expect(')', end_error);
- return expression;
+ } else {
+ expression = create_error_expression();
}
- expect(')', end_error);
-end_error:
- return create_error_expression();
+ rem_anchor_token(')');
+ expect(')');
+ return expression;
}
/**
eat(T___builtin_va_arg);
- expect('(', end_error);
+ expect('(');
+ add_anchor_token(')');
+ add_anchor_token(',');
call_argument_t ap;
ap.expression = parse_assignment_expression();
expression->va_arge.ap = ap.expression;
check_call_argument(type_valist, &ap, 1);
- expect(',', end_error);
+ rem_anchor_token(',');
+ expect(',');
expression->base.type = parse_typename();
- expect(')', end_error);
+ rem_anchor_token(')');
+ expect(')');
return expression;
-end_error:
- return create_error_expression();
}
/**
eat(T___builtin_va_copy);
- expect('(', end_error);
+ expect('(');
+ add_anchor_token(')');
+ add_anchor_token(',');
expression_t *dst = parse_assignment_expression();
assign_error_t error = semantic_assign(type_valist, dst);
report_assign_error(error, type_valist, dst, "call argument 1",
&dst->base.source_position);
expression->va_copye.dst = dst;
- expect(',', end_error);
+ rem_anchor_token(',');
+ expect(',');
call_argument_t src;
src.expression = parse_assignment_expression();
check_call_argument(type_valist, &src, 2);
expression->va_copye.src = src.expression;
- expect(')', end_error);
+ rem_anchor_token(')');
+ expect(')');
return expression;
-end_error:
- return create_error_expression();
}
/**
eat(T___builtin_constant_p);
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
expression->builtin_constant.value = parse_assignment_expression();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
expression->base.type = type_int;
return expression;
-end_error:
- return create_error_expression();
}
/**
eat(T___builtin_types_compatible_p);
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
add_anchor_token(',');
expression->builtin_types_compatible.left = parse_typename();
rem_anchor_token(',');
- expect(',', end_error);
+ expect(',');
expression->builtin_types_compatible.right = parse_typename();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
expression->base.type = type_int;
return expression;
-end_error:
- return create_error_expression();
}
/**
expression->base.source_position = *HERE;
next_token();
- expect('(', end_error);
+ expect('(');
+ add_anchor_token(')');
+ add_anchor_token(',');
expression->binary.left = parse_assignment_expression();
- expect(',', end_error);
+ rem_anchor_token(',');
+ expect(',');
expression->binary.right = parse_assignment_expression();
- expect(')', end_error);
+ rem_anchor_token(')');
+ expect(')');
type_t *const orig_type_left = expression->binary.left->base.type;
type_t *const orig_type_right = expression->binary.right->base.type;
}
return expression;
-end_error:
- return create_error_expression();
}
/**
eat(T__assume);
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
expression->unary.value = parse_assignment_expression();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
expression->base.type = type_void;
return expression;
-end_error:
- return create_error_expression();
}
/**
rem_anchor_token(',');
rem_anchor_token(')');
}
- expect(')', end_error);
+ expect(')');
-end_error:
return literal;
}
arr->base.type = res_type;
rem_anchor_token(']');
- expect(']', end_error);
-end_error:
+ expect(']');
return expr;
}
add_anchor_token(')');
orig_type = parse_typename();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
if (token.kind == '{') {
/* It was not sizeof(type) after all. It is sizeof of an expression
what, wrong_type, orig_type);
}
-end_error:
return tp_expression;
}
}
rem_anchor_token(',');
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
if (function_type == NULL)
return result;
handle_builtin_argument_restrictions(call);
}
-end_error:
return result;
}
true_expression = parse_expression();
}
rem_anchor_token(':');
- expect(':', end_error);
-end_error:;
+ expect(':');
expression_t *false_expression =
parse_subexpression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
eat(T___builtin_classify_type);
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
expression_t *expression = parse_expression();
rem_anchor_token(')');
- expect(')', end_error);
+ expect(')');
result->classify_type.type_expression = expression;
return result;
-end_error:
- return create_error_expression();
}
/**
if (next_if('[')) {
result->kind = EXPR_UNARY_DELETE_ARRAY;
- expect(']', end_error);
-end_error:;
+ expect(']');
}
expression_t *const value = parse_subexpression(PREC_CAST);
add_anchor_token(']');
argument->symbol = expect_identifier("while parsing asm argument", NULL);
rem_anchor_token(']');
- expect(']', end_error);
+ expect(']');
if (!argument->symbol)
return NULL;
}
argument->constraints = parse_string_literals();
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
expression_t *expression = parse_expression();
rem_anchor_token(')');
mark_vars_read(expression, NULL);
}
argument->expression = expression;
- expect(')', end_error);
+ expect(')');
set_address_taken(expression, true);
}
return result;
-end_error:
- return NULL;
}
/**
if (next_if(T_volatile))
asm_statement->is_volatile = true;
- expect('(', end_error);
+ expect('(');
add_anchor_token(')');
if (token.kind != T_STRING_LITERAL) {
parse_error_expected("after asm(", T_STRING_LITERAL, NULL);
end_of_asm:
rem_anchor_token(')');
- expect(')', end_error);
- expect(';', end_error);
+ expect(')');
+ expect(';');
-end_error:
if (asm_statement->outputs == NULL) {
/* GCC: An 'asm' instruction without any output operands will be treated
* identically to a volatile 'asm' instruction. */
source_position_t *const pos = &statement->base.source_position;
eat(T_case);
+ add_anchor_token(':');
expression_t *expression = parse_expression();
type_t *expression_type = expression->base.type;
PUSH_PARENT(statement);
- expect(':', end_error);
-end_error:
+ rem_anchor_token(':');
+ expect(':');
if (current_switch != NULL) {
if (! statement->case_label.is_bad) {
PUSH_PARENT(statement);
- expect(':', end_error);
-end_error:
+ expect(':');
if (current_switch != NULL) {
const case_label_statement_t *def_label = current_switch->default_label;
*/
static expression_t *parse_condition(void)
{
- expect('(', end_error0);
+ expect('(');
add_anchor_token(')');
expression_t *const expr = parse_expression();
mark_vars_read(expr, NULL);
rem_anchor_token(')');
- expect(')', end_error1);
-end_error1:
+ expect(')');
return expr;
-end_error0:
- return create_error_expression();
}
/**
statement->do_while.body = parse_loop_body(statement);
rem_anchor_token(T_while);
- expect(T_while, end_error0);
-end_error0:;
+ expect(T_while);
expression_t *const cond = parse_condition();
statement->do_while.condition = cond;
/* §6.8.5:2 The controlling expression of an iteration statement shall
* have scalar type. */
semantic_condition(cond, "condition of 'do-while'-statement");
- expect(';', end_error1);
-end_error1:
+ expect(';');
POP_PARENT();
return statement;
PUSH_PARENT(statement);
PUSH_SCOPE(&statement->fors.scope);
- expect('(', end_error1);
+ expect('(');
add_anchor_token(')');
PUSH_EXTENSION();
warningf(WARN_UNUSED_VALUE, &init->base.source_position, "initialisation of 'for'-statement has no effect");
}
rem_anchor_token(';');
- expect(';', end_error3);
-end_error3:;
+ expect(';');
}
POP_EXTENSION();
mark_vars_read(cond, NULL);
rem_anchor_token(';');
}
- expect(';', end_error2);
-end_error2:
+ expect(';');
if (token.kind != ')') {
expression_t *const step = parse_expression();
statement->fors.step = step;
}
}
rem_anchor_token(')');
- expect(')', end_error1);
-end_error1:
+ expect(')');
statement->fors.body = parse_loop_body(statement);
POP_SCOPE();
}
}
- expect(';', end_error);
-
-end_error:
+ expect(';');
return statement;
}
statement_t *statement = allocate_statement_zero(STATEMENT_CONTINUE);
eat(T_continue);
- expect(';', end_error);
-
-end_error:
+ expect(';');
return statement;
}
statement_t *statement = allocate_statement_zero(STATEMENT_BREAK);
eat(T_break);
- expect(';', end_error);
-
-end_error:
+ expect(';');
return statement;
}
statement_t *statement = allocate_statement_zero(STATEMENT_LEAVE);
eat(T___leave);
- expect(';', end_error);
-
-end_error:
+ expect(';');
return statement;
}
}
statement->returns.value = return_value;
- expect(';', end_error);
-
-end_error:
+ expect(';');
return statement;
}
statement->expression.expression = expr;
mark_vars_read(expr, ENT_ANY);
- expect(';', end_error);
-
-end_error:
+ expect(';');
return statement;
}
environment_push(entity);
}
} while (next_if(','));
- expect(';', end_error);
+ expect(';');
end_error:
statement->declaration.declarations_begin = begin;
statement->declaration.declarations_end = end;
entity_t *old_current_entity = current_entity;
current_entity = entity;
- expect('{', end_error);
+ add_anchor_token('}');
+ expect('{');
parse_externals();
- expect('}', end_error);
+ rem_anchor_token('}');
+ expect('}');
-end_error:
assert(current_entity == entity);
current_entity = old_current_entity;
POP_SCOPE();
*anchor = sub_statement;
anchor = &sub_statement->base.next;
}
- expect('}', end_error);
-end_error:
+ expect('}');
/* look over all statements again to produce no effect warnings */
if (is_warn_on(WARN_UNUSED_VALUE)) {
statement_t *statement = allocate_statement_zero(STATEMENT_ASM);
eat(T_asm);
- expect('(', end_error);
+ add_anchor_token(';');
+ add_anchor_token(')');
+ add_anchor_token(T_STRING_LITERAL);
+ expect('(');
+ rem_anchor_token(T_STRING_LITERAL);
statement->asms.asm_text = parse_string_literals();
statement->base.next = unit->global_asm;
unit->global_asm = statement;
- expect(')', end_error);
- expect(';', end_error);
-
-end_error:;
+ rem_anchor_token(')');
+ expect(')');
+ rem_anchor_token(';');
+ expect(';');
}
static void parse_linkage_specification(void)
if (next_if('{')) {
parse_externals();
- expect('}', end_error);
+ expect('}');
} else {
parse_external();
}
-end_error:
assert(current_linkage == new_linkage);
current_linkage = old_linkage;
}