X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=88ad6280a4bc68748e222b94290ee482540051cb;hb=3c84e06d01aaed7971067d7cc1924f6e20bcd0ba;hp=d81e20f287fbfcca97bea497c8b4e02ab4476831;hpb=d9c2f28d8ca23867f292a952b0543807d35e672f;p=cparser diff --git a/parser.c b/parser.c index d81e20f..88ad628 100644 --- a/parser.c +++ b/parser.c @@ -569,6 +569,16 @@ static inline void next_token(void) #endif } +static inline bool next_if(int const type) +{ + if (token.type == type) { + next_token(); + return true; + } else { + return false; + } +} + /** * Return the next token with a given lookahead. */ @@ -702,8 +712,7 @@ static void eat_until_anchor(void) static void eat_block(void) { eat_until_matching_token('{'); - if (token.type == '}') - next_token(); + next_if('}'); } #define eat(token_type) (assert(token.type == (token_type)), next_token()) @@ -747,8 +756,7 @@ static void type_error_incompatible(const char *msg, parse_error_expected(NULL, (expected), NULL); \ add_anchor_token(expected); \ eat_until_anchor(); \ - if (token.type == expected) \ - next_token(); \ + next_if((expected)); \ rem_anchor_token(expected); \ goto error_label; \ } \ @@ -1242,12 +1250,9 @@ static attribute_t *allocate_attribute_zero(attribute_kind_t kind) */ static attribute_argument_t *parse_attribute_arguments(void) { - if (token.type == ')') - return NULL; - - attribute_argument_t *first = NULL; - attribute_argument_t *last = NULL; - while (true) { + attribute_argument_t *first = NULL; + attribute_argument_t **anchor = &first; + if (token.type != ')') do { attribute_argument_t *argument = allocate_ast_zero(sizeof(*argument)); /* is it an identifier */ @@ -1266,20 +1271,10 @@ static attribute_argument_t *parse_attribute_arguments(void) } /* append argument */ - if (last == NULL) { - first = argument; - } else { - last->next = argument; - } - last = argument; - - if (token.type == ',') { - next_token(); - continue; - } - expect(')', end_error); - break; - } + *anchor = argument; + anchor = &argument->next; + } while (next_if(',')); + expect(')', end_error); return first; @@ -1373,10 +1368,8 @@ static attribute_t *parse_attribute_gnu_single(void) attribute_t *attribute = allocate_attribute_zero(kind); /* parse arguments */ - if (token.type == '(') { - next_token(); + if (next_if('(')) attribute->a.arguments = parse_attribute_arguments(); - } return attribute; @@ -1386,37 +1379,22 @@ end_error: static attribute_t *parse_attribute_gnu(void) { - attribute_t *first = NULL; - attribute_t *last = NULL; + attribute_t *first = NULL; + attribute_t **anchor = &first; eat(T___attribute__); expect('(', end_error); expect('(', end_error); - if (token.type == ')') { - next_token(); - expect(')', end_error); - return first; - } - - while (true) { + if (token.type != ')') do { attribute_t *attribute = parse_attribute_gnu_single(); if (attribute == NULL) goto end_error; - if (last == NULL) { - first = attribute; - } else { - last->next = attribute; - } - last = attribute; - - if (token.type == ')') { - next_token(); - break; - } - expect(',', end_error); - } + *anchor = attribute; + anchor = &attribute->next; + } while (next_if(',')); + expect(')', end_error); expect(')', end_error); end_error: @@ -1426,12 +1404,10 @@ end_error: /** Parse attributes. */ static attribute_t *parse_attributes(attribute_t *first) { - attribute_t *last = first; - while (true) { - if (last != NULL) { - while (last->next != NULL) - last = last->next; - } + attribute_t **anchor = &first; + for (;;) { + while (*anchor != NULL) + anchor = &(*anchor)->next; attribute_t *attribute; switch (token.type) { @@ -1475,12 +1451,8 @@ static attribute_t *parse_attributes(attribute_t *first) return first; } - if (last == NULL) { - first = attribute; - } else { - last->next = attribute; - } - last = attribute; + *anchor = attribute; + anchor = &attribute->next; } } @@ -1721,10 +1693,10 @@ unary: static designator_t *parse_designation(void) { - designator_t *result = NULL; - designator_t *last = NULL; + designator_t *result = NULL; + designator_t **anchor = &result; - while (true) { + for (;;) { designator_t *designator; switch (token.type) { case '[': @@ -1754,12 +1726,8 @@ static designator_t *parse_designation(void) } assert(designator != NULL); - if (last != NULL) { - last->next = designator; - } else { - result = designator; - } - last = designator; + *anchor = designator; + anchor = &designator->next; } end_error: return NULL; @@ -1864,13 +1832,12 @@ static initializer_t *parse_scalar_initializer(type_t *type, { /* there might be extra {} hierarchies */ int braces = 0; - if (token.type == '{') { + if (next_if('{')) { if (warning.other) warningf(HERE, "extra curly braces around scalar initializer"); do { ++braces; - next_token(); - } while (token.type == '{'); + } while (next_if('{')); } expression_t *expression = parse_assignment_expression(); @@ -1893,9 +1860,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, bool additional_warning_displayed = false; while (braces > 0) { - if (token.type == ',') { - next_token(); - } + next_if(','); if (token.type != '}') { if (!additional_warning_displayed && warning.other) { warningf(HERE, "additional elements in scalar initializer"); @@ -2193,8 +2158,7 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) */ static void skip_initializers(void) { - if (token.type == '{') - next_token(); + next_if('{'); while (token.type != '}') { if (token.type == T_EOF) @@ -2327,9 +2291,7 @@ finish_designator: && outer_type != NULL) { sub = initializer_from_expression(outer_type, expression); if (sub != NULL) { - if (token.type == ',') { - next_token(); - } + next_if(','); if (token.type != '}' && warning.other) { warningf(HERE, "excessive elements in initializer for type '%T'", orig_type); @@ -2625,8 +2587,7 @@ static void parse_enum_entries(type_t *const enum_type) entity->base.source_position = token.source_position; next_token(); - if (token.type == '=') { - next_token(); + if (next_if('=')) { expression_t *value = parse_constant_expression(); value = create_implicit_cast(value, enum_type); @@ -2636,11 +2597,7 @@ static void parse_enum_entries(type_t *const enum_type) } record_entity(entity, false); - - if (token.type != ',') - break; - next_token(); - } while (token.type != '}'); + } while (next_if(',') && token.type != '}'); rem_anchor_token('}'); expect('}', end_error); @@ -2651,33 +2608,38 @@ end_error: static type_t *parse_enum_specifier(void) { - entity_t *entity; - symbol_t *symbol; + entity_t *entity; + symbol_t *symbol; eat(T_enum); - if (token.type == T_IDENTIFIER) { - symbol = token.v.symbol; - next_token(); + switch (token.type) { + case T_IDENTIFIER: + symbol = token.v.symbol; + next_token(); - entity = get_tag(symbol, ENTITY_ENUM); - if (entity != NULL) { - if (entity->base.parent_scope != current_scope && - (token.type == '{' || token.type == ';')) { - /* we're in an inner scope and have a definition. Shadow - * existing definition in outer scope */ - entity = NULL; - } else if (entity->enume.complete && token.type == '{') { - errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)", - symbol, &entity->base.source_position); + entity = get_tag(symbol, ENTITY_ENUM); + if (entity != NULL) { + if (entity->base.parent_scope != current_scope && + (token.type == '{' || token.type == ';')) { + /* we're in an inner scope and have a definition. Shadow + * existing definition in outer scope */ + entity = NULL; + } else if (entity->enume.complete && token.type == '{') { + errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)", + symbol, &entity->base.source_position); + } } - } - } else if (token.type != '{') { - parse_error_expected("while parsing enum type specifier", - T_IDENTIFIER, '{', NULL); - return NULL; - } else { - entity = NULL; - symbol = NULL; + break; + + case '{': + entity = NULL; + symbol = NULL; + break; + + default: + parse_error_expected("while parsing enum type specifier", + T_IDENTIFIER, '{', NULL); + return NULL; } if (entity == NULL) { @@ -2739,9 +2701,8 @@ static type_t *parse_typeof(void) bool old_gcc_extension = in_gcc_extension; in_type_prop = true; - while (token.type == T___extension__) { + while (next_if(T___extension__)) { /* This can be a prefix to a typename or an expression. */ - next_token(); in_gcc_extension = true; } switch (token.type) { @@ -2828,7 +2789,7 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute) attribute_property_argument_t *property = allocate_ast_zero(sizeof(*property)); - while (true) { + do { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing property declspec", T_IDENTIFIER, NULL); @@ -2858,10 +2819,7 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute) property->get_symbol = token.v.symbol; } next_token(); - if (token.type == ')') - break; - expect(',', end_error); - } + } while (next_if(',')); attribute->a.property = property; @@ -2874,9 +2832,8 @@ end_error: static attribute_t *parse_microsoft_extended_decl_modifier_single(void) { attribute_kind_t kind = ATTRIBUTE_UNKNOWN; - if (token.type == T_restrict) { + if (next_if(T_restrict)) { kind = ATTRIBUTE_MS_RESTRICT; - next_token(); } else if (token.type == T_IDENTIFIER) { const char *name = token.v.symbol->string; next_token(); @@ -2904,10 +2861,8 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) } /* parse arguments */ - if (token.type == '(') { - next_token(); + if (next_if('(')) attribute->a.arguments = parse_attribute_arguments(); - } return attribute; } @@ -2918,37 +2873,24 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first) expect('(', end_error); - if (token.type == ')') { - next_token(); + if (next_if(')')) return NULL; - } add_anchor_token(')'); - attribute_t *last = first; - while (true) { - if (last != NULL) { - while (last->next != NULL) - last = last->next; - } + attribute_t **anchor = &first; + do { + while (*anchor != NULL) + anchor = &(*anchor)->next; attribute_t *attribute = parse_microsoft_extended_decl_modifier_single(); if (attribute == NULL) goto end_error; - if (last == NULL) { - first = attribute; - } else { - last->next = attribute; - } - last = attribute; - - if (token.type == ')') { - break; - } - expect(',', end_error); - } + *anchor = attribute; + anchor = &attribute->next; + } while (next_if(',')); rem_anchor_token(')'); expect(')', end_error); @@ -3450,12 +3392,7 @@ static void parse_identifier_list(scope_t *scope) if (scope != NULL) append_entity(scope, entity); - - if (token.type != ',') { - break; - } - next_token(); - } while (token.type == T_IDENTIFIER); + } while (next_if(',') && token.type == T_IDENTIFIER); } static entity_t *parse_parameter(void) @@ -3536,7 +3473,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope) if (has_parameters()) { function_parameter_t **anchor = &type->parameters; - for (;;) { + do { switch (token.type) { case T_DOTDOTDOT: next_token(); @@ -3572,11 +3509,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope) default: goto parameters_finished; } - if (token.type != ',') { - goto parameters_finished; - } - next_token(); - } + } while (next_if(',')); } @@ -3670,18 +3603,12 @@ static construct_type_t *parse_array_declarator(void) memset(array, 0, sizeof(*array)); cons->kind = CONSTRUCT_ARRAY; - if (token.type == T_static) { + if (next_if(T_static)) array->is_static = true; - next_token(); - } type_qualifiers_t type_qualifiers = parse_type_qualifiers(); - if (type_qualifiers != 0) { - if (token.type == T_static) { + if (type_qualifiers != 0 && next_if(T_static)) array->is_static = true; - next_token(); - } - } array->type_qualifiers = type_qualifiers; if (token.type == '*' && look_ahead(1)->type == ']') { @@ -4036,15 +3963,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, attribute_t *attributes = parse_attributes(env.attributes); /* append (shared) specifier attribute behind attributes of this - declarator */ - if (attributes != NULL) { - attribute_t *last = attributes; - while (last->next != NULL) - last = last->next; - last->next = specifiers->attributes; - } else { - attributes = specifiers->attributes; - } + * declarator */ + attribute_t **anchor = &attributes; + while (*anchor != NULL) + anchor = &(*anchor)->next; + *anchor = specifiers->attributes; entity_t *entity; if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) { @@ -4722,9 +4645,8 @@ static void parse_declaration_rest(entity_t *ndeclaration, check_variable_type_complete(entity); - if (token.type != ',') + if (!next_if(',')) break; - eat(','); add_anchor_token('='); ndeclaration = parse_declarator(specifiers, flags); @@ -5313,9 +5235,8 @@ static void check_reachable(statement_t *const stmt) break; } - case STATEMENT_CONTINUE: { - statement_t *parent = stmt; - for (;;) { + case STATEMENT_CONTINUE: + for (statement_t *parent = stmt;;) { parent = parent->base.parent; if (parent == NULL) /* continue not within loop */ return; @@ -5329,11 +5250,9 @@ static void check_reachable(statement_t *const stmt) default: break; } } - } - case STATEMENT_BREAK: { - statement_t *parent = stmt; - for (;;) { + case STATEMENT_BREAK: + for (statement_t *parent = stmt;;) { parent = parent->base.parent; if (parent == NULL) /* break not within loop/switch */ return; @@ -5352,7 +5271,6 @@ static void check_reachable(statement_t *const stmt) } found_break_parent: break; - } case STATEMENT_GOTO: if (stmt->gotos.expression) { @@ -5993,7 +5911,7 @@ static expression_t *find_create_select(const source_position_t *pos, static void parse_compound_declarators(compound_t *compound, const declaration_specifiers_t *specifiers) { - while (true) { + do { entity_t *entity; if (token.type == ':') { @@ -6006,15 +5924,11 @@ static void parse_compound_declarators(compound_t *compound, type_t *type = make_bitfield_type(base_type, size, &source_position, NULL); - attribute_t *attributes = parse_attributes(NULL); - if (attributes != NULL) { - attribute_t *last = attributes; - while (last->next != NULL) - last = last->next; - last->next = specifiers->attributes; - } else { - attributes = specifiers->attributes; - } + attribute_t *attributes = parse_attributes(NULL); + attribute_t **anchor = &attributes; + while (*anchor != NULL) + anchor = &(*anchor)->next; + *anchor = specifiers->attributes; entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER); entity->base.namespc = NAMESPACE_NORMAL; @@ -6082,11 +5996,7 @@ static void parse_compound_declarators(compound_t *compound, append_entity(&compound->members, entity); } } - - if (token.type != ',') - break; - next_token(); - } + } while (next_if(',')); expect(';', end_error); end_error: @@ -6517,13 +6427,12 @@ static entity_t *lookup_entity(const scope_t *scope, symbol_t *symbol, static entity_t *parse_qualified_identifier(void) { /* namespace containing the symbol */ - symbol_t *symbol; - const scope_t *lookup_scope = NULL; + symbol_t *symbol; + source_position_t pos; + const scope_t *lookup_scope = NULL; - if (token.type == T_COLONCOLON) { - next_token(); + if (next_if(T_COLONCOLON)) lookup_scope = &unit->scope; - } entity_t *entity; while (true) { @@ -6532,14 +6441,14 @@ static entity_t *parse_qualified_identifier(void) return create_error_entity(sym_anonymous, ENTITY_VARIABLE); } symbol = token.v.symbol; + pos = *HERE; next_token(); /* lookup entity */ entity = lookup_entity(lookup_scope, symbol, NAMESPACE_NORMAL); - if (token.type != T_COLONCOLON) + if (!next_if(T_COLONCOLON)) break; - next_token(); switch (entity->kind) { case ENTITY_NAMESPACE: @@ -6551,7 +6460,7 @@ static entity_t *parse_qualified_identifier(void) lookup_scope = &entity->compound.members; break; default: - errorf(HERE, "'%Y' must be a namespace, class, struct or union (but is a %s)", + errorf(&pos, "'%Y' must be a namespace, class, struct or union (but is a %s)", symbol, get_entity_kind_name(entity->kind)); goto end_error; } @@ -6561,14 +6470,14 @@ static entity_t *parse_qualified_identifier(void) if (!strict_mode && token.type == '(') { /* an implicitly declared function */ if (warning.error_implicit_function_declaration) { - errorf(HERE, "implicit declaration of function '%Y'", symbol); + errorf(&pos, "implicit declaration of function '%Y'", symbol); } else if (warning.implicit_function_declaration) { - warningf(HERE, "implicit declaration of function '%Y'", symbol); + warningf(&pos, "implicit declaration of function '%Y'", symbol); } - entity = create_implicit_function(symbol, HERE); + entity = create_implicit_function(symbol, &pos); } else { - errorf(HERE, "unknown identifier '%Y' found.", symbol); + errorf(&pos, "unknown identifier '%Y' found.", symbol); entity = create_error_entity(symbol, ENTITY_VARIABLE); } } @@ -6577,12 +6486,7 @@ static entity_t *parse_qualified_identifier(void) end_error: /* skip further qualifications */ - while (token.type == T_IDENTIFIER) { - next_token(); - if (token.type != T_COLONCOLON) - break; - next_token(); - } + while (next_if(T_IDENTIFIER) && next_if(T_COLONCOLON)) {} return create_error_entity(sym_anonymous, ENTITY_VARIABLE); } @@ -6885,8 +6789,7 @@ static designator_t *parse_designator(void) designator_t *last_designator = result; while (true) { - if (token.type == '.') { - next_token(); + if (next_if('.')) { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing member designator", T_IDENTIFIER, NULL); @@ -6901,8 +6804,7 @@ static designator_t *parse_designator(void) last_designator = designator; continue; } - if (token.type == '[') { - next_token(); + if (next_if('[')) { add_anchor_token(']'); designator_t *designator = allocate_ast_zero(sizeof(result[0])); designator->source_position = *HERE; @@ -7265,14 +7167,9 @@ static expression_t *parse_noop_expression(void) add_anchor_token(')'); add_anchor_token(','); - if (token.type != ')') { - while (true) { - (void)parse_assignment_expression(); - if (token.type != ',') - break; - next_token(); - } - } + if (token.type != ')') do { + (void)parse_assignment_expression(); + } while (next_if(',')); } rem_anchor_token(','); rem_anchor_token(')'); @@ -7672,17 +7569,13 @@ static expression_t *parse_call_expression(expression_t *expression) if (token.type != ')') { call_argument_t **anchor = &call->arguments; - for (;;) { + do { call_argument_t *argument = allocate_ast_zero(sizeof(*argument)); argument->expression = parse_assignment_expression(); *anchor = argument; anchor = &argument->next; - - if (token.type != ',') - break; - next_token(); - } + } while (next_if(',')); } rem_anchor_token(','); rem_anchor_token(')'); @@ -7998,8 +7891,7 @@ static expression_t *parse_delete(void) eat(T_delete); - if (token.type == '[') { - next_token(); + if (next_if('[')) { result->kind = EXPR_UNARY_DELETE_ARRAY; expect(']', end_error); end_error:; @@ -8107,14 +7999,14 @@ static bool is_lvalue(const expression_t *expression) return true; default: { - type_t *type = skip_typeref(expression->base.type); - return - /* ISO/IEC 14882:1998(E) §3.10:3 */ - is_type_reference(type) || - /* Claim it is an lvalue, if the type is invalid. There was a parse - * error before, which maybe prevented properly recognizing it as - * lvalue. */ - !is_type_valid(type); + type_t *type = skip_typeref(expression->base.type); + return + /* ISO/IEC 14882:1998(E) §3.10:3 */ + is_type_reference(type) || + /* Claim it is an lvalue, if the type is invalid. There was a parse + * error before, which maybe prevented properly recognizing it as + * lvalue. */ + !is_type_valid(type); } } } @@ -9276,8 +9168,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out) asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0])); memset(argument, 0, sizeof(argument[0])); - if (token.type == '[') { - eat('['); + if (next_if('[')) { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing asm argument", T_IDENTIFIER, NULL); @@ -9356,9 +9247,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out) *anchor = argument; anchor = &argument->next; - if (token.type != ',') + if (!next_if(',')) break; - eat(','); } return result; @@ -9371,23 +9261,18 @@ end_error: */ static asm_clobber_t *parse_asm_clobbers(void) { - asm_clobber_t *result = NULL; - asm_clobber_t *last = NULL; + asm_clobber_t *result = NULL; + asm_clobber_t **anchor = &result; while (token.type == T_STRING_LITERAL) { asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0])); clobber->clobber = parse_string_literals(); - if (last != NULL) { - last->next = clobber; - } else { - result = clobber; - } - last = clobber; + *anchor = clobber; + anchor = &clobber->next; - if (token.type != ',') + if (!next_if(',')) break; - eat(','); } return result; @@ -9403,36 +9288,31 @@ static statement_t *parse_asm_statement(void) eat(T_asm); - if (token.type == T_volatile) { - next_token(); + if (next_if(T_volatile)) asm_statement->is_volatile = true; - } expect('(', end_error); add_anchor_token(')'); add_anchor_token(':'); asm_statement->asm_text = parse_string_literals(); - if (token.type != ':') { + if (!next_if(':')) { rem_anchor_token(':'); goto end_of_asm; } - eat(':'); asm_statement->outputs = parse_asm_arguments(true); - if (token.type != ':') { + if (!next_if(':')) { rem_anchor_token(':'); goto end_of_asm; } - eat(':'); asm_statement->inputs = parse_asm_arguments(false); - if (token.type != ':') { + if (!next_if(':')) { rem_anchor_token(':'); goto end_of_asm; } rem_anchor_token(':'); - eat(':'); asm_statement->clobbers = parse_asm_clobbers(); @@ -9479,8 +9359,7 @@ static statement_t *parse_case_statement(void) } if (GNU_MODE) { - if (token.type == T_DOTDOTDOT) { - next_token(); + if (next_if(T_DOTDOTDOT)) { expression_t *const end_range = parse_expression(); statement->case_label.end_range = end_range; if (!is_constant_expression(end_range)) { @@ -9683,8 +9562,7 @@ end_error: statement->ifs.true_statement = true_stmt; rem_anchor_token(T_else); - if (token.type == T_else) { - next_token(); + if (next_if(T_else)) { statement->ifs.false_statement = parse_statement(); } else if (warning.parentheses && true_stmt->kind == STATEMENT_IF && @@ -9887,13 +9765,11 @@ static statement_t *parse_for(void) scope_t *old_scope = scope_push(&statement->fors.scope); bool old_gcc_extension = in_gcc_extension; - while (token.type == T___extension__) { - next_token(); + while (next_if(T___extension__)) { in_gcc_extension = true; } - if (token.type == ';') { - next_token(); + if (next_if(';')) { } else if (is_declaration_specifier(&token, false)) { parse_declaration(record_entity, DECL_FLAGS_NONE); } else { @@ -9961,8 +9837,7 @@ static statement_t *parse_goto(void) statement_t *statement = allocate_statement_zero(STATEMENT_GOTO); eat(T_goto); - if (GNU_MODE && token.type == '*') { - next_token(); + if (GNU_MODE && next_if('*')) { expression_t *expression = parse_expression(); mark_vars_read(expression, NULL); @@ -10245,8 +10120,7 @@ static statement_t *parse_ms_try_statment(void) POP_PARENT; - if (token.type == T___except) { - eat(T___except); + if (next_if(T___except)) { expect('(', end_error); add_anchor_token(')'); expression_t *const expr = parse_expression(); @@ -10263,8 +10137,7 @@ static statement_t *parse_ms_try_statment(void) rem_anchor_token(')'); expect(')', end_error); statement->ms_try.final_statement = parse_compound_statement(false); - } else if (token.type == T__finally) { - eat(T___finally); + } else if (next_if(T__finally)) { statement->ms_try.final_statement = parse_compound_statement(false); } else { parse_error_expected("while parsing __try statement", T___except, T___finally, NULL); @@ -10293,7 +10166,7 @@ static statement_t *parse_local_label_declaration(void) entity_t *begin = NULL, *end = NULL; - while (true) { + do { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing local label declaration", T_IDENTIFIER, NULL); @@ -10321,11 +10194,7 @@ static statement_t *parse_local_label_declaration(void) environment_push(entity); } next_token(); - - if (token.type != ',') - break; - next_token(); - } + } while (next_if(',')); eat(';'); end_error: statement->declaration.declarations_begin = begin; @@ -10432,9 +10301,7 @@ expression_statment: case T___extension__: /* This can be a prefix to a declaration or an expression statement. * We simply eat it now and parse the rest with tail recursion. */ - do { - next_token(); - } while (token.type == T___extension__); + while (next_if(T___extension__)) {} bool old_gcc_extension = in_gcc_extension; in_gcc_extension = true; statement = intern_parse_statement(); @@ -10831,8 +10698,7 @@ static void parse_linkage_specification(void) } current_linkage = new_linkage; - if (token.type == '{') { - next_token(); + if (next_if('{')) { parse_externals(); expect('}', end_error); } else {