X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=d5d2c5e59bb6132f38612e243289c69b77553412;hb=e8b00fcb80ff3fdcfab757444e94663f1d56c743;hp=914f3a61c072d431f2132991f5bc2c65afb1ac94;hpb=eb596cbe81cdddc1b68ed70ee927dc6037d2ef3c;p=cparser diff --git a/parser.c b/parser.c index 914f3a6..d5d2c5e 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,12 @@ 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); + storage_class_t storage_class, type_t *type, + int may_omit_identifier); +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 +293,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 +307,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 +325,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 +340,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 +469,6 @@ typedef enum { case T_enum: \ COMPLEX_SPECIFIERS \ IMAGINARY_SPECIFIERS -/* TODO: T_IDENTIFIER && typename */ #define DECLARATION_START \ STORAGE_CLASSES \ @@ -462,6 +497,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 +718,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 +730,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 @@ -724,12 +757,22 @@ unsigned parse_type_qualifiers() } static -type_t *parse_pointer(type_t *type) +int parse_pointers(void) { + int result = 0; + while(token.type == '*') { - /* pointer */ next_token(); + result++; + } + return result; +} + +static +type_t *make_pointers(type_t *type, int count) +{ + for(int i = 0; i < count; ++i) { pointer_type_t *pointer_type = allocate_type_zero(sizeof(pointer_type[0])); pointer_type->type.type = TYPE_POINTER; @@ -749,7 +792,7 @@ type_t *parse_pointer(type_t *type) } static -void parse_identifier_list() +void parse_identifier_list(void) { while(1) { if(token.type != T_IDENTIFIER) { @@ -765,41 +808,76 @@ void parse_identifier_list() } static -void parse_parameter() +declaration_t *parse_parameter(void) { - if(token.type == T_DOTDOTDOT) { - next_token(); - return; - } - declaration_specifiers_t specifiers; memset(&specifiers, 0, sizeof(specifiers)); parse_declaration_specifiers(&specifiers); - 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, - specifiers.type); + declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); + parse_declarator(declaration, specifiers.storage_class, + specifiers.type, 1); + +#if 0 + if(declaration->symbol != NULL) { + maybe_push_declaration(declaration); + record_declaration(declaration); } +#endif + + return declaration; } static -void parse_parameters() +void parse_parameters(method_type_t *type) { if(token.type == T_IDENTIFIER) { - parse_identifier_list(); + symbol_t *symbol = token.v.symbol; + declaration_t *declaration = symbol->declaration; + if(declaration == NULL + || declaration->storage_class != STORAGE_CLASS_TYPEDEF) { + parse_identifier_list(); + return; + } + } + + if(token.type == ')') { + type->unspecified_parameters = 1; + return; + } + if(token.type == T_void && la(1)->type == ')') { + next_token(); return; } + declaration_t *declaration; + method_parameter_type_t *parameter_type; + method_parameter_type_t *last_parameter_type = NULL; + while(1) { switch(token.type) { case T_DOTDOTDOT: + next_token(); + type->variadic = 1; + return; + + case T_IDENTIFIER: DECLARATION_START - parse_parameter(); + declaration = parse_parameter(); + + parameter_type = allocate_type_zero(sizeof(parameter_type[0])); + parameter_type->type = declaration->type; + parameter_type->symbol = declaration->symbol; + + if(last_parameter_type != NULL) { + last_parameter_type->next = parameter_type; + } else { + type->parameter_types = parameter_type; + } + last_parameter_type = parameter_type; break; + default: return; } @@ -814,7 +892,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; @@ -838,25 +915,156 @@ void parse_attributes(void) } } +typedef struct declarator_part declarator_part; +struct declarator_part { + int pointers; + method_type_t *method_type; + declarator_part *inner; +}; + +static struct obstack temp_obst; + +static +declarator_part *parse_inner_declarator(declaration_t *declaration) +{ + declarator_part *part = obstack_alloc(&temp_obst, sizeof(part[0])); + memset(part, 0, sizeof(part[0])); + + part->pointers = parse_pointers(); + + switch(token.type) { + case T_IDENTIFIER: + declaration->symbol = token.v.symbol; + declaration->source_position = token.source_position; + next_token(); + break; + case '(': + next_token(); + part->inner = parse_inner_declarator(declaration); + expect(')'); + break; + default: + parse_error_expected("problem while parsing declarator", T_IDENTIFIER, + '(', 0); + } + + while(1) { + switch(token.type) { + case '(': + next_token(); + +#if 0 + int top = environment_top(); + context_t *last_context = context; + set_context(&declaration->context); +#endif + + method_type_t *method_type + = allocate_type_zero(sizeof(method_type[0])); + method_type->type.type = TYPE_METHOD; + + parse_parameters(method_type); + +#if 0 + assert(context == &declaration->context); + set_context(last_context); + environment_pop_to(top); +#endif + + part->method_type = method_type; + + expect(')'); + break; + case '[': + next_token(); + + if(token.type == T_static) { + next_token(); + } + + unsigned type_qualifiers = parse_type_qualifiers(); + if(type_qualifiers != 0) { + if(token.type == T_static) { + next_token(); + } + } + + /* TODO */ + + if(token.type == '*' && la(1)->type == ']') { + next_token(); + } else if(token.type != ']') { + parse_assignment_expression(); + } + + expect(']'); + break; + default: + goto declarator_finished; + } + } + +declarator_finished: + parse_attributes(); + + return part; +} + +static +type_t *construct_declarator_type(declarator_part *part, type_t *type) +{ + do { + type = make_pointers(type, part->pointers); + + method_type_t *method_type = part->method_type; + if(method_type != NULL) { + method_type->result_type = type; + + type = (type_t*) method_type; + } + + part = part->inner; + } while(part != NULL); + + return type; +} + +static +void parse_declarator(declaration_t *declaration, storage_class_t storage_class, + type_t *type, int may_omit_identifier) +{ + (void) may_omit_identifier; + declarator_part *part = parse_inner_declarator(declaration); + + declaration->type = construct_declarator_type(part, type); + declaration->storage_class = storage_class; + obstack_free(&temp_obst, part); +} + +#if 0 static void parse_declarator(declaration_t *declaration, storage_class_t storage_class, - type_t *type) + type_t *type, int may_omit_identifier) { - type = parse_pointer(type); + ir_type *outer_type = parse_pointers(type); + declaration->storage_class = storage_class; - declaration->type = type; + declaration->type = outer_type; 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 '(': next_token(); - parse_declarator(declaration, storage_class, type); + parse_declarator(declaration, storage_class, type, 0); expect_void(')'); break; default: + if(may_omit_identifier) + goto declarator_finished; parse_error_expected("problem while parsing declarator", T_IDENTIFIER, '(', 0); } @@ -866,7 +1074,23 @@ void parse_declarator(declaration_t *declaration, storage_class_t storage_class, case '(': next_token(); - parse_parameters(); + int top = environment_top(); + context_t *last_context = context; + set_context(&declaration->context); + + method_type_t *method_type + = allocate_type_zero(sizeof(method_type[0])); + method_type->type.type = TYPE_METHOD; + method_type->result_type = outer_type; + + parse_parameters(method_type); + + assert(context == &declaration->context); + set_context(last_context); + environment_pop_to(top); + + replace_type(&declaration->type, outer_type, + method_type); expect_void(')'); break; @@ -884,7 +1108,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 +1123,23 @@ void parse_declarator(declaration_t *declaration, storage_class_t storage_class, declarator_finished: parse_attributes(); +} +#endif - 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) { @@ -918,7 +1154,9 @@ void parse_init_declarators(const declaration_specifiers_t *specifiers) declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0])); parse_declarator(declaration, specifiers->storage_class, - specifiers->type); + specifiers->type, 0); + maybe_push_declaration(declaration); + record_declaration(declaration); if(token.type == '=') { next_token(); if(token.type == '{') { @@ -928,7 +1166,8 @@ void parse_init_declarators(const declaration_specifiers_t *specifiers) parse_assignment_expression(); } } else if(token.type == '{') { - parse_compound_statement(); + statement_t *statement = parse_compound_statement(); + declaration->statement = statement; return; } @@ -943,21 +1182,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, - specifiers->type); + declaration_t *declaration + = allocate_ast_zero(sizeof(declaration[0])); + parse_declarator(declaration, specifiers->storage_class, + specifiers->type, 0); + maybe_push_declaration(declaration); + record_declaration(declaration); if(token.type == ':') { next_token(); parse_constant_expression(); - /* TODO */ + /* TODO (bitfields) */ } } @@ -968,12 +1208,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 +1221,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) @@ -1008,7 +1247,8 @@ type_t *parse_typename(void) /* TODO not correct storage class elements are not allowed here */ parse_declaration_specifiers(&specifiers); - specifiers.type = parse_pointer(specifiers.type); + int pointers = parse_pointers(); + specifiers.type = make_pointers(specifiers.type, pointers); return specifiers.type; } @@ -1682,17 +1922,25 @@ 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(); - return NULL; + return (statement_t*) compound_statement; } static @@ -1700,15 +1948,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; } @@ -1732,8 +1982,10 @@ translation_unit_t *parse(void) void init_parser(void) { init_expression_parsers(); + obstack_init(&temp_obst); } void exit_parser(void) { + obstack_free(&temp_obst, NULL); }