#endif
}
+#define eat(token_kind) (assert(token.kind == (token_kind)), next_token())
+
static inline bool next_if(token_kind_t const type)
{
if (token.kind == type) {
- next_token();
+ eat(type);
return true;
} else {
return false;
next_if('}');
}
-#define eat(token_kind) (assert(token.kind == (token_kind)), next_token())
-
/**
* Report a parse error because an expected token was not found.
*/
assert(token.kind == T_STRING_LITERAL);
string_t result = token.string.string;
- next_token();
+ eat(T_STRING_LITERAL);
while (token.kind == T_STRING_LITERAL) {
warn_string_concat(HERE);
result = concat_strings(&result, &token.string.string);
- next_token();
+ eat(T_STRING_LITERAL);
}
return result;
&& (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
argument->kind = ATTRIBUTE_ARGUMENT_SYMBOL;
argument->v.symbol = token.base.symbol;
- next_token();
+ eat(T_IDENTIFIER);
} else {
/* must be an expression */
expression_t *expression = parse_assignment_expression();
case '[':
designator = allocate_ast_zero(sizeof(designator[0]));
designator->source_position = *HERE;
- next_token();
+ eat('[');
add_anchor_token(']');
designator->array_index = parse_constant_expression();
rem_anchor_token(']');
case '.':
designator = allocate_ast_zero(sizeof(designator[0]));
designator->source_position = *HERE;
- next_token();
+ eat('.');
designator->symbol = expect_identifier("while parsing designator", NULL);
if (!designator->symbol)
return NULL;
/* the compound has a name, check if we have seen it already */
symbol = token.base.symbol;
entity = get_tag(symbol, kind);
- next_token();
+ eat(T_IDENTIFIER);
if (entity != NULL) {
if (entity->base.parent_scope != current_scope &&
if (token.kind == '}') {
errorf(HERE, "empty enum not allowed");
- next_token();
+ eat('}');
return;
}
case T_IDENTIFIER:
symbol = token.base.symbol;
entity = get_tag(symbol, ENTITY_ENUM);
- next_token();
+ eat(T_IDENTIFIER);
if (entity != NULL) {
if (entity->base.parent_scope != current_scope &&
specifiers->storage_class = class; \
if (specifiers->thread_local) \
goto check_thread_storage_class; \
- next_token(); \
+ eat(token); \
break;
MATCH_STORAGE_CLASS(T_typedef, STORAGE_CLASS_TYPEDEF)
#define MATCH_TYPE_QUALIFIER(token, qualifier) \
case token: \
qualifiers |= qualifier; \
- next_token(); \
+ eat(token); \
break
MATCH_TYPE_QUALIFIER(T_const, TYPE_QUALIFIER_CONST);
} else { \
type_specifiers |= specifier; \
} \
- next_token(); \
+ eat(token); \
break
MATCH_SPECIFIER(T__Bool, SPECIFIER_BOOL, "_Bool");
MATCH_SPECIFIER(T_wchar_t, SPECIFIER_WCHAR_T, "wchar_t");
case T_inline:
- next_token();
+ eat(T_inline);
specifiers->is_inline = true;
break;
#if 0
case T__forceinline:
- next_token();
+ eat(T__forceinline);
specifiers->modifiers |= DM_FORCEINLINE;
break;
#endif
} else {
type_specifiers |= SPECIFIER_LONG;
}
- next_token();
+ eat(T_long);
break;
#define CHECK_DOUBLE_TYPE() \
case T___builtin_va_list:
CHECK_DOUBLE_TYPE();
type = duplicate_type(type_valist);
- next_token();
+ eat(T___builtin_va_list);
break;
case T_IDENTIFIER: {
case '&':
case '*':
errorf(HERE, "discarding stray %K in declaration specifier", &token);
- next_token();
+ eat(T_IDENTIFIER);
continue;
default:
type = allocate_type_zero(TYPE_TYPEDEF);
type->typedeft.typedefe = &entity->typedefe;
- next_token();
+ eat(T_IDENTIFIER);
saw_error = true;
continue;
}
}
}
- next_token();
+ eat(T_IDENTIFIER);
type = typedef_type;
break;
}
do {
entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.base.symbol, HERE);
/* a K&R parameter has no type, yet */
- next_token();
+ eat(T_IDENTIFIER);
if (scope != NULL)
append_entity(scope, entity);
do {
switch (token.kind) {
case T_DOTDOTDOT:
- next_token();
+ eat(T_DOTDOTDOT);
type->variadic = true;
goto parameters_finished;
expression_t *size = NULL;
if (token.kind == '*' && look_ahead(1)->kind == ']') {
array->is_variable = true;
- next_token();
+ eat('*');
} else if (token.kind != ']') {
size = parse_assignment_expression();
env->symbol = token.base.symbol;
env->source_position = *HERE;
}
- next_token();
+ eat(T_IDENTIFIER);
break;
case '(': {
case '[':
case T___attribute__: /* FIXME __attribute__ might also introduce a parameter of a function declarator. */
/* Paranthesized declarator. */
- next_token();
+ eat('(');
add_anchor_token(')');
inner_types = parse_inner_declarator(env);
if (inner_types != NULL) {
literal->literal.value.begin = value ? "true" : "false";
literal->literal.value.size = value ? 4 : 5;
- next_token();
+ eat(value ? T_true : T_false);
return literal;
}
}
}
- next_token();
+ eat(T_CHARACTER_CONSTANT);
return literal;
}
warningf(WARN_MULTICHAR, HERE, "multi-character character constant");
}
- next_token();
+ eat(T_WIDE_CHARACTER_CONSTANT);
return literal;
}
expression_t *expression;
if (token.kind == '(' && is_declaration_specifier(look_ahead(1))) {
source_position_t const pos = *HERE;
- next_token();
+ eat('(');
add_anchor_token(')');
orig_type = parse_typename();
rem_anchor_token(')');
* statement after a label. label:; is commonly used to have a label
* before a closing brace. */
inner_stmt = create_empty_statement();
- next_token();
+ eat(';');
break;
}
/* FALLTHROUGH */
case ';':
if (!strict_mode) {
warningf(WARN_STRAY_SEMICOLON, HERE, "stray ';' outside of function");
- next_token();
+ eat(';');
return;
}
/* FALLTHROUGH */