X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=9cae9630215090267ed71c845eab4b4e4d8645f4;hb=619e8bbd734140dd6562c9f10c43c029eaa3f52d;hp=914f3a61c072d431f2132991f5bc2c65afb1ac94;hpb=eb596cbe81cdddc1b68ed70ee927dc6037d2ef3c;p=cparser diff --git a/parser.c b/parser.c index 914f3a6..9cae963 100644 --- a/parser.c +++ b/parser.c @@ -13,7 +13,7 @@ #include "adt/error.h" #include "adt/array.h" -#define PRINT_TOKENS +//#define PRINT_TOKENS #define MAX_LOOKAHEAD 2 struct environment_entry_t { @@ -27,8 +27,8 @@ static token_t lookahead_buffer[MAX_LOOKAHEAD]; static int lookahead_bufpos; static struct obstack environment_obstack; static environment_entry_t **environment_stack = NULL; -static translation_unit_t *translation_unit = NULL; -static block_statement_t *context = NULL; +static context_t *context = NULL; +static declaration_t *last_declaration = NULL; static statement_t *parse_compound_statement(void); @@ -174,6 +174,21 @@ void eat_until(int token_type) } \ next_token(); +static void set_context(context_t *new_context) +{ + context = new_context; + + declaration_t *declaration = new_context->declarations; + if(declaration != NULL) { + while(1) { + if(declaration->next == NULL) + break; + declaration = declaration->next; + } + } + + last_declaration = declaration; +} /** * pushs an environment_entry on the environment stack and links the @@ -190,11 +205,13 @@ void environment_push(declaration_t *declaration, const void *context) ARR_RESIZE(environment_stack, top + 1); environment_stack[top] = entry; + assert(declaration->source_position.input_name != NULL); + symbol_t *symbol = declaration->symbol; assert(declaration != symbol->declaration); if(symbol->context == context) { - if(context != NULL) { + if(symbol->declaration != NULL) { assert(symbol->declaration != NULL); parser_print_error_prefix_pos(declaration->source_position); fprintf(stderr, "multiple definitions for symbol '%s'.\n", @@ -255,9 +272,11 @@ static expression_t *parse_assignment_expression(void) return parse_expression(); } -static compound_entry_t *parse_compound_type_entries(void); +static void parse_compound_type_entries(void); static void parse_declarator(declaration_t *declaration, storage_class_t storage_class, type_t *type); +static void maybe_push_declaration(declaration_t *declaration); +static void record_declaration(declaration_t *declaration); typedef struct declaration_specifiers_t declaration_specifiers_t; struct declaration_specifiers_t { @@ -273,8 +292,11 @@ static type_t *parse_struct_specifier(void) struct_type->type.type = TYPE_COMPOUND_STRUCT; struct_type->source_position = token.source_position; + int top = environment_top(); + context_t *last_context = context; + set_context(&struct_type->context); + if(token.type == T_IDENTIFIER) { - /* TODO */ next_token(); if(token.type == '{') { parse_compound_type_entries(); @@ -284,9 +306,13 @@ static type_t *parse_struct_specifier(void) } else { parse_error_expected("problem while parsing struct type specifiers", T_IDENTIFIER, '{', 0); - return NULL; + struct_type = NULL; } + assert(context == &struct_type->context); + set_context(last_context); + environment_pop_to(top); + return (type_t*) struct_type; } @@ -298,6 +324,10 @@ static type_t *parse_union_specifier(void) union_type->type.type = TYPE_COMPOUND_UNION; union_type->source_position = token.source_position; + int top = environment_top(); + context_t *last_context = context; + set_context(&union_type->context); + if(token.type == T_IDENTIFIER) { union_type->symbol = token.v.symbol; next_token(); @@ -309,8 +339,13 @@ static type_t *parse_union_specifier(void) } else { parse_error_expected("problem while parsing union type specifiers", T_IDENTIFIER, '{'); + union_type = NULL; } + assert(context == &union_type->context); + set_context(last_context); + environment_pop_to(top); + return (type_t*) union_type; } @@ -433,7 +468,6 @@ typedef enum { case T_enum: \ COMPLEX_SPECIFIERS \ IMAGINARY_SPECIFIERS -/* TODO: T_IDENTIFIER && typename */ #define DECLARATION_START \ STORAGE_CLASSES \ @@ -462,6 +496,7 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers) type_t *type = NULL; unsigned type_qualifiers = 0; unsigned type_specifiers = 0; + int newtype = 0; while(1) { switch(token.type) { @@ -682,6 +717,7 @@ finish_specifiers: atomic_type_t *atype = allocate_type_zero(sizeof(atype[0])); atype->type.type = TYPE_ATOMIC; atype->atype = atomic_type; + newtype = 1; type = (type_t*) atype; } else { @@ -693,15 +729,11 @@ finish_specifiers: type->qualifiers = type_qualifiers; type_t *result = typehash_insert(type); - if(result != (type_t*) type) { + if(newtype && result != (type_t*) type) { obstack_free(type_obst, type); } specifiers->type = result; - - fprintf(stderr, "Specifiers type: "); - print_type(stderr, result); - fprintf(stderr, "\n"); } static @@ -779,10 +811,11 @@ void parse_parameter() specifiers.type = parse_pointer(specifiers.type); if(token.type == '(' || token.type == T_IDENTIFIER) { - declaration_t declaration; - memset(&declaration, 0, sizeof(declaration)); - parse_declarator(&declaration, specifiers.storage_class, + declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); + parse_declarator(declaration, specifiers.storage_class, specifiers.type); + maybe_push_declaration(declaration); + record_declaration(declaration); } } @@ -790,13 +823,19 @@ static void parse_parameters() { if(token.type == T_IDENTIFIER) { - parse_identifier_list(); - return; + symbol_t *symbol = token.v.symbol; + declaration_t *declaration = symbol->declaration; + if(declaration == NULL + || declaration->storage_class != STORAGE_CLASS_TYPEDEF) { + parse_identifier_list(); + return; + } } while(1) { switch(token.type) { case T_DOTDOTDOT: + case T_IDENTIFIER: DECLARATION_START parse_parameter(); break; @@ -814,7 +853,6 @@ void parse_attributes(void) { while(token.type == T___attribute__) { next_token(); - fprintf(stderr, "TODO: __attribute__ not handled yet\n"); expect_void('('); int depth = 1; @@ -848,7 +886,8 @@ void parse_declarator(declaration_t *declaration, storage_class_t storage_class, switch(token.type) { case T_IDENTIFIER: - declaration->symbol = token.v.symbol; + declaration->symbol = token.v.symbol; + declaration->source_position = token.source_position; next_token(); break; case '(': @@ -866,8 +905,16 @@ void parse_declarator(declaration_t *declaration, storage_class_t storage_class, case '(': next_token(); + int top = environment_top(); + context_t *last_context = context; + set_context(&declaration->context); + parse_parameters(); + assert(context == &declaration->context); + set_context(last_context); + environment_pop_to(top); + expect_void(')'); break; case '[': @@ -884,7 +931,7 @@ void parse_declarator(declaration_t *declaration, storage_class_t storage_class, } } - if(token.type == '*' /* TODO: && lookahead == ']' */) { + if(token.type == '*' && la(1)->type == ']') { next_token(); } else if(token.type != ']') { parse_assignment_expression(); @@ -899,11 +946,22 @@ void parse_declarator(declaration_t *declaration, storage_class_t storage_class, declarator_finished: parse_attributes(); +} - fprintf(stderr, "Declarator type: "); - print_type(stderr, type); - fprintf(stderr, "\n"); +static void record_declaration(declaration_t *declaration) +{ + if(last_declaration != NULL) { + last_declaration->next = declaration; + } else { + if(context != NULL) + context->declarations = declaration; + } + last_declaration = declaration; +} +static +void maybe_push_declaration(declaration_t *declaration) +{ symbol_t *symbol = declaration->symbol; if(symbol != NULL) { @@ -919,6 +977,8 @@ void parse_init_declarators(const declaration_specifiers_t *specifiers) parse_declarator(declaration, specifiers->storage_class, specifiers->type); + maybe_push_declaration(declaration); + record_declaration(declaration); if(token.type == '=') { next_token(); if(token.type == '{') { @@ -943,21 +1003,22 @@ static void parse_struct_declarators(const declaration_specifiers_t *specifiers) { while(1) { - declaration_t declaration; - compound_entry_t *entry = allocate_ast_zero(sizeof(entry[0])); - if(token.type == ':') { next_token(); parse_constant_expression(); - /* TODO */ + /* TODO (bitfields) */ } else { - parse_declarator(&declaration, specifiers->storage_class, + declaration_t *declaration + = allocate_ast_zero(sizeof(declaration[0])); + parse_declarator(declaration, specifiers->storage_class, specifiers->type); + maybe_push_declaration(declaration); + record_declaration(declaration); if(token.type == ':') { next_token(); parse_constant_expression(); - /* TODO */ + /* TODO (bitfields) */ } } @@ -968,12 +1029,10 @@ void parse_struct_declarators(const declaration_specifiers_t *specifiers) expect_void(';'); } -static compound_entry_t *parse_compound_type_entries(void) +static void parse_compound_type_entries(void) { eat('{'); - compound_entry_t *entries = NULL; - while(token.type != '}' && token.type != T_EOF) { declaration_specifiers_t specifiers; memset(&specifiers, 0, sizeof(specifiers)); @@ -983,9 +1042,10 @@ static compound_entry_t *parse_compound_type_entries(void) parse_struct_declarators(&specifiers); } + if(token.type == T_EOF) { + parse_error("unexpected error while parsing struct"); + } next_token(); - - return entries; } void parse_declaration(void) @@ -1682,12 +1742,20 @@ statement_t *parse_compound_statement(void) { eat('{'); - int top = environment_top(); + compound_statement_t *compound_statement + = allocate_ast_zero(sizeof(compound_statement[0])); + compound_statement->statement.type = STATEMENT_COMPOUND; + + int top = environment_top(); + context_t *last_context = context; + set_context(&compound_statement->context); while(token.type != '}') { parse_statement(); } + assert(context == &compound_statement->context); + set_context(last_context); environment_pop_to(top); next_token(); @@ -1700,15 +1768,17 @@ translation_unit_t *parse_translation_unit(void) { translation_unit_t *unit = allocate_ast_zero(sizeof(unit[0])); - assert(translation_unit == NULL); assert(context == NULL); - translation_unit = unit; + set_context(&unit->context); while(token.type != T_EOF) { parse_declaration(); } - translation_unit = NULL; + assert(context == &unit->context); + context = NULL; + last_declaration = NULL; + return unit; }