X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=e042b8942f54245163214dbaf1f7b000cb9ad3cd;hb=377cc851b30da15e985e1f2ad998ad984d598133;hp=fdb85bd97252e3856e0f3d8c25a090a88af77dc4;hpb=353985d8d06fcac2f36682820b8ae635c5e6162e;p=cparser diff --git a/parser.c b/parser.c index fdb85bd..e042b89 100644 --- a/parser.c +++ b/parser.c @@ -25,21 +25,27 @@ typedef struct { unsigned short namespace; } stack_entry_t; -static token_t token; -static token_t lookahead_buffer[MAX_LOOKAHEAD]; -static int lookahead_bufpos; -static stack_entry_t *environment_stack = NULL; -static context_t *global_context = NULL; -static context_t *context = NULL; -static declaration_t *last_declaration = NULL; -static struct obstack temp_obst; - -static type_t *type_int = NULL; -static type_t *type_double = NULL; -static type_t *type_const_char = NULL; -static type_t *type_string = NULL; -static type_t *type_void = NULL; -static type_t *type_size_t = NULL; +static token_t token; +static token_t lookahead_buffer[MAX_LOOKAHEAD]; +static int lookahead_bufpos; +static stack_entry_t *environment_stack = NULL; +static context_t *global_context = NULL; +static context_t *context = NULL; +static declaration_t *last_declaration = NULL; +static declaration_t *current_function = NULL; +static struct obstack temp_obst; +static bool found_error; + +static type_t *type_int = NULL; +static type_t *type_uint = NULL; +static type_t *type_long_double = NULL; +static type_t *type_double = NULL; +static type_t *type_float = NULL; +static type_t *type_const_char = NULL; +static type_t *type_string = NULL; +static type_t *type_void = NULL; +static type_t *type_size_t = NULL; +static type_t *type_ptrdiff_t = NULL; static statement_t *parse_compound_statement(void); static statement_t *parse_statement(void); @@ -156,6 +162,7 @@ static inline const token_t *look_ahead(int num) static void error(void) { + found_error = true; #ifdef ABORT_ON_ERROR abort(); #endif @@ -179,8 +186,7 @@ static void parser_print_error_prefix_pos( static void parser_print_error_prefix(void) { - parser_print_prefix_pos(token.source_position); - error(); + parser_print_error_prefix_pos(token.source_position); } static void parse_error(const char *message) @@ -189,7 +195,6 @@ static void parse_error(const char *message) fprintf(stderr, "parse error: %s\n", message); } -__attribute__((unused)) static void parse_warning(const char *message) { parser_print_prefix_pos(token.source_position); @@ -225,6 +230,28 @@ static void parse_error_expected(const char *message, ...) fprintf(stderr, "\n"); } +static void type_error(const char *msg, const source_position_t source_position, + type_t *type) +{ + parser_print_error_prefix_pos(source_position); + fprintf(stderr, "%s, but found type ", msg); + print_type(type); + fputc('\n', stderr); + error(); +} + +static void type_error_incompatible(const char *msg, + const source_position_t source_position, type_t *type1, type_t *type2) +{ + parser_print_error_prefix_pos(source_position); + fprintf(stderr, "%s, incompatible types: ", msg); + print_type(type1); + fprintf(stderr, " - "); + print_type(type2); + fprintf(stderr, ")\n"); + error(); +} + static void eat_block(void) { if(token.type == '{') @@ -460,6 +487,109 @@ static void environment_pop_to(size_t new_top) } +static int get_rank(const type_t *type) +{ + /* The C-standard allows promoting to int or unsigned int (see § 7.2.2 + * and esp. footnote 108). However we can't fold constants (yet), so we + * can't decide wether unsigned int is possible, while int always works. + * (unsigned int would be preferable when possible... for stuff like + * struct { enum { ... } bla : 4; } ) */ + if(type->type == TYPE_ENUM) + return ATOMIC_TYPE_INT; + + assert(type->type == TYPE_ATOMIC); + atomic_type_t *atomic_type = (atomic_type_t*) type; + atomic_type_type_t atype = atomic_type->atype; + return atype; +} + +static type_t *promote_integer(type_t *type) +{ + if(get_rank(type) < ATOMIC_TYPE_INT) + type = type_int; + + return type; +} + +static expression_t *create_cast_expression(expression_t *expression, + type_t *dest_type) +{ + unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0])); + + cast->expression.type = EXPR_UNARY; + cast->type = UNEXPR_CAST; + cast->value = expression; + cast->expression.datatype = dest_type; + + return (expression_t*) cast; +} + +static expression_t *create_implicit_cast(expression_t *expression, + type_t *dest_type) +{ + assert(expression->datatype != NULL); + type_t *source_type = expression->datatype; + + source_type = skip_typeref(source_type); + dest_type = skip_typeref(dest_type); + + if(expression->datatype == dest_type) + return expression; + + if(dest_type->type == TYPE_ATOMIC) { + if(source_type->type != TYPE_ATOMIC) + panic("casting of non-atomic types not implemented yet"); + + if(is_type_floating(dest_type) && !is_type_scalar(source_type)) { + type_error_incompatible("can't cast types", + expression->source_position, + source_type, dest_type); + return expression; + } + + return create_cast_expression(expression, dest_type); + } + if(dest_type->type == TYPE_POINTER) { + if(source_type->type == TYPE_POINTER) { + if(!pointers_compatible(source_type, dest_type)) { + type_error_incompatible("can't implicitely cast types", + expression->source_position, + source_type, dest_type); + } else { + return create_cast_expression(expression, dest_type); + } + } + } + + panic("casting of non-atomic types not implemented yet"); +} + +static void semantic_assign(type_t *orig_type_left, expression_t **right, + const char *context) +{ + type_t *orig_type_right = (*right)->datatype; + type_t *type_left = skip_typeref(orig_type_left); + type_t *type_right = skip_typeref(orig_type_right); + + if(type_left == type_right) { + /* fine */ + } else if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + *right = create_implicit_cast(*right, type_left); + } else if(type_left->type == TYPE_POINTER + && type_right->type == TYPE_POINTER) { + /* TODO */ + } else { + /* TODO: improve error message */ + parser_print_error_prefix(); + fprintf(stderr, "incompatible types in %s\n", context); + parser_print_error_prefix(); + print_type(type_left); + fputs(" <- ", stderr); + print_type(type_right); + fputs("\n", stderr); + } + +} static expression_t *parse_constant_expression(void) { @@ -591,35 +721,42 @@ static designator_t *parse_designation(void) } } -static initializer_t *parse_initializer_list(void); +static initializer_t *parse_initializer_list(type_t *type); -static initializer_t *parse_initializer(void) +static initializer_t *parse_initializer(type_t *type) { designator_t *designator = parse_designation(); initializer_t *result; if(token.type == '{') { - result = parse_initializer_list(); + result = parse_initializer_list(type); } else { result = allocate_ast_zero(sizeof(result[0])); result->type = INITIALIZER_VALUE; result->v.value = parse_assignment_expression(); + + if(type != NULL) { + semantic_assign(type, &result->v.value, "initializer"); + } } result->designator = designator; return result; } -static initializer_t *parse_initializer_list(void) +static initializer_t *parse_initializer_list(type_t *type) { eat('{'); + /* TODO: semantic */ + (void) type; + initializer_t *result = allocate_ast_zero(sizeof(result[0])); result->type = INITIALIZER_LIST; initializer_t *last = NULL; while(1) { - initializer_t *initializer = parse_initializer(); + initializer_t *initializer = parse_initializer(NULL); if(last != NULL) { last->next = initializer; } else { @@ -743,7 +880,7 @@ static void parse_enum_entries(void) if(token.type == '=') { next_token(); - entry->init.initializer = parse_initializer(); + entry->init.initializer = parse_initializer(type_int); } record_declaration(entry); @@ -888,6 +1025,8 @@ static type_t *create_builtin_type(symbol_t *symbol) builtin_type_t *type = allocate_type_zero(sizeof(type[0])); type->type.type = TYPE_BUILTIN; type->symbol = symbol; + /* TODO... */ + type->real_type = type_int; return (type_t*) type; } @@ -1614,7 +1753,7 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers) parser_error_multiple_definition(declaration, ndeclaration); } - ndeclaration->init.initializer = parse_initializer(); + ndeclaration->init.initializer = parse_initializer(declaration->type); } else if(token.type == '{') { if(declaration->type->type != TYPE_FUNCTION) { parser_print_error_prefix(); @@ -1642,9 +1781,14 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers) for( ; parameter != NULL; parameter = parameter->next) { environment_push(parameter); } + declaration_t *old_current_function = current_function; + current_function = declaration; statement_t *statement = parse_compound_statement(); + assert(current_function == declaration); + old_current_function = current_function; + assert(context == &declaration->context); set_context(last_context); environment_pop_to(top); @@ -1817,7 +1961,8 @@ static expression_t *parse_float_const(void) static declaration_t *create_implicit_function(symbol_t *symbol, const source_position_t source_position) { - function_type_t *function_type = allocate_type_zero(sizeof(function_type)); + function_type_t *function_type + = allocate_type_zero(sizeof(function_type[0])); function_type->type.type = TYPE_FUNCTION; function_type->result_type = type_int; @@ -1893,7 +2038,7 @@ static void check_cast_allowed(expression_t *expression, type_t *dest_type) { (void) expression; (void) dest_type; - /* TODO check if cast is allowed and issue warnings/errors */ + /* TODO check if explicit cast is allowed and issue warnings/errors */ } static expression_t *parse_cast(void) @@ -2243,9 +2388,26 @@ static expression_t *parse_call_expression(unsigned precedence, { (void) precedence; call_expression_t *call = allocate_ast_zero(sizeof(call[0])); + call->expression.type = EXPR_CALL; + call->function = expression; - call->expression.type = EXPR_CALL; - call->function = expression; + function_type_t *function_type; + type_t *type = expression->datatype; + if(type->type != TYPE_FUNCTION) { + /* TODO calling pointers to functions is ok */ + parser_print_error_prefix(); + fputs("called object '", stderr); + print_expression(expression); + fputs("' (type ", stderr); + print_type(type); + fputs("is not a function\n", stderr); + + function_type = NULL; + call->expression.datatype = NULL; + } else { + function_type = (function_type_t*) type; + call->expression.datatype = function_type->result_type; + } /* parse arguments */ eat('('); @@ -2271,51 +2433,50 @@ static expression_t *parse_call_expression(unsigned precedence, } expect(')'); - type_t *type = expression->datatype; - if(type != NULL) { - /* we can call pointer to function */ - if(type->type == TYPE_POINTER) { - pointer_type_t *pointer = (pointer_type_t*) type; - type = pointer->points_to; + if(function_type != NULL) { + function_parameter_t *parameter = function_type->parameters; + call_argument_t *argument = call->arguments; + for( ; parameter != NULL && argument != NULL; + parameter = parameter->next, argument = argument->next) { + type_t *expected_type = parameter->type; + /* TODO report context in error messages */ + argument->expression = create_implicit_cast(argument->expression, + expected_type); } - - if(type == NULL || type->type != TYPE_FUNCTION) { + /* too few parameters */ + if(parameter != NULL) { parser_print_error_prefix(); - fprintf(stderr, "expected a function type for call but found " - "type "); - print_type(expression->datatype); - fprintf(stderr, "\n"); - } else { - function_type_t *function_type = (function_type_t*) type; - call->expression.datatype = function_type->result_type; + fprintf(stderr, "too few arguments to function '"); + print_expression(expression); + fprintf(stderr, "'\n"); + } else if(argument != NULL) { + /* too many parameters */ + if(!function_type->variadic + && !function_type->unspecified_parameters) { + parser_print_error_prefix(); + fprintf(stderr, "too many arguments to function '"); + print_expression(expression); + fprintf(stderr, "'\n"); + } else { + /* do default promotion */ + for( ; argument != NULL; argument = argument->next) { + type_t *type = argument->expression->datatype; + + if(is_type_integer(type)) { + type = promote_integer(type); + } else if(type == type_float) { + type = type_double; + } + argument->expression + = create_implicit_cast(argument->expression, type); + } + } } } return (expression_t*) call; } -static void type_error(const char *msg, const source_position_t source_position, - type_t *type) -{ - parser_print_error_prefix_pos(source_position); - fprintf(stderr, "%s, but found type ", msg); - print_type(type); - fputc('\n', stderr); - error(); -} - -static void type_error_incompatible(const char *msg, - const source_position_t source_position, type_t *type1, type_t *type2) -{ - parser_print_error_prefix_pos(source_position); - fprintf(stderr, "%s, incompatible types: ", msg); - print_type(type1); - fprintf(stderr, " - "); - print_type(type2); - fprintf(stderr, ")\n"); - error(); -} - static type_t *get_type_after_conversion(const type_t *type1, const type_t *type2) { @@ -2397,8 +2558,13 @@ static type_t *get_unexpr_arithmetic_type(const expression_t *expression) static type_t *get_unexpr_dereference_type(const expression_t *expression) { - (void) expression; - /* TODO... */ + type_t *expression_type = expression->datatype; + + if(expression_type->type == TYPE_POINTER) { + pointer_type_t *pointer_type = (pointer_type_t*) expression_type; + return pointer_type->points_to; + } + panic("deref TODO..."); return NULL; } @@ -2460,103 +2626,257 @@ CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_PLUSPLUS, UNEXPR_POSTFIX_INCREMENT, CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_MINUSMINUS, UNEXPR_POSTFIX_DECREMENT, get_unexpr_arithmetic_type) -static type_t *get_binexpr_int_type(const expression_t *left, - const expression_t *right) +static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) +{ + /* TODO: handle complex + imaginary types */ + + /* § 6.3.1.8 Usual arithmetic conversions */ + if(type_left == type_long_double || type_right == type_long_double) { + return type_long_double; + } else if(type_left == type_double || type_right == type_double) { + return type_double; + } else if(type_left == type_float || type_right == type_float) { + return type_float; + } + + type_right = promote_integer(type_right); + type_left = promote_integer(type_left); + + if(type_left == type_right) + return type_left; + + bool signed_left = is_type_signed(type_left); + bool signed_right = is_type_signed(type_right); + if(get_rank(type_left) < get_rank(type_right)) { + if(signed_left == signed_right || !signed_right) { + return type_right; + } else { + return type_left; + } + } else { + if(signed_left == signed_right || !signed_left) { + return type_left; + } else { + return type_right; + } + } +} + +static void semantic_binexpr_arithmetic(binary_expression_t *expression) +{ + expression_t *left = expression->left; + expression_t *right = expression->right; + type_t *type_left = skip_typeref(left->datatype); + type_t *type_right = skip_typeref(right->datatype); + + if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) { + /* TODO: improve error message */ + parser_print_error_prefix(); + fprintf(stderr, "operation needs arithmetic types\n"); + return; + } + + type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); + expression->left = create_implicit_cast(left, arithmetic_type); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->expression.datatype = arithmetic_type; +} + +static void semantic_add(binary_expression_t *expression) +{ + expression_t *left = expression->left; + expression_t *right = expression->right; + type_t *orig_type_left = left->datatype; + type_t *orig_type_right = right->datatype; + type_t *type_left = skip_typeref(orig_type_left); + type_t *type_right = skip_typeref(orig_type_right); + + /* § 5.6.5 */ + if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); + expression->left = create_implicit_cast(left, arithmetic_type); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->expression.datatype = arithmetic_type; + return; + } else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) { + expression->expression.datatype = type_left; + } else if(type_right->type == TYPE_POINTER && is_type_integer(type_left)) { + expression->expression.datatype = type_right; + } else { + parser_print_error_prefix(); + fprintf(stderr, "invalid operands to binary + ("); + print_type(orig_type_left); + fprintf(stderr, ", "); + print_type(orig_type_right); + fprintf(stderr, ")\n"); + } +} + +static void semantic_sub(binary_expression_t *expression) +{ + expression_t *left = expression->left; + expression_t *right = expression->right; + type_t *orig_type_left = left->datatype; + type_t *orig_type_right = right->datatype; + type_t *type_left = skip_typeref(orig_type_left); + type_t *type_right = skip_typeref(orig_type_right); + + /* § 5.6.5 */ + if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); + expression->left = create_implicit_cast(left, arithmetic_type); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->expression.datatype = arithmetic_type; + return; + } else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) { + expression->expression.datatype = type_left; + } else if(type_left->type == TYPE_POINTER && + type_right->type == TYPE_POINTER) { + if(!pointers_compatible(type_left, type_right)) { + parser_print_error_prefix(); + fprintf(stderr, "pointers to incompatible objects to binary - ("); + print_type(orig_type_left); + fprintf(stderr, ", "); + print_type(orig_type_right); + fprintf(stderr, ")\n"); + } else { + expression->expression.datatype = type_ptrdiff_t; + } + } else { + parser_print_error_prefix(); + fprintf(stderr, "invalid operands to binary - ("); + print_type(orig_type_left); + fprintf(stderr, ", "); + print_type(orig_type_right); + fprintf(stderr, ")\n"); + } +} + +static void semantic_comparison(binary_expression_t *expression) { - (void) left; - (void) right; - return type_int; + expression_t *left = expression->left; + expression_t *right = expression->right; + type_t *type_left = left->datatype; + type_t *type_right = right->datatype; + + /* TODO non-arithmetic types */ + if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); + expression->left = create_implicit_cast(left, arithmetic_type); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->expression.datatype = arithmetic_type; + } + expression->expression.datatype = type_int; } -static type_t *get_binexpr_arithmetic_type(const expression_t *left, - const expression_t *right) +static void semantic_arithmetic_assign(binary_expression_t *expression) { - (void) right; - return left->datatype; + expression_t *left = expression->left; + expression_t *right = expression->right; + type_t *type_left = left->datatype; + type_t *type_right = right->datatype; + + if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) { + /* TODO: improve error message */ + parser_print_error_prefix(); + fprintf(stderr, "operation needs arithmetic types\n"); + return; + } + + /* combined instructions are tricky. We can't create an implicit cast on + * the left side, because we need the uncasted form for the store. + * The ast2firm pass has to know that left_type must be right_type + * for the arithmeitc operation and create a cast by itself */ + type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->expression.datatype = type_left; } -static type_t *get_binexpr_arithmetic_assign_type(const expression_t *left, - const expression_t *right) +static void semantic_logical_op(binary_expression_t *expression) { - (void) right; /* TODO */ - return left->datatype; -} - -static type_t *get_binexpr_right_type(const expression_t *left, - const expression_t *right) -{ - (void) left; - return right->datatype; -} - -#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, tfunc) \ -static expression_t *parse_##binexpression_type(unsigned precedence, \ - expression_t *left) \ -{ \ - eat(token_type); \ - \ - expression_t *right = parse_sub_expression(precedence); \ - \ - binary_expression_t *binexpr \ - = allocate_ast_zero(sizeof(binexpr[0])); \ - binexpr->expression.type = EXPR_BINARY; \ - binexpr->type = binexpression_type; \ - binexpr->left = left; \ - binexpr->right = right; \ - binexpr->expression.datatype = tfunc(left, right); \ - \ - return (expression_t*) binexpr; \ -} - -CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA, get_binexpr_right_type) -CREATE_BINEXPR_PARSER('*', BINEXPR_MUL, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('/', BINEXPR_DIV, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('%', BINEXPR_MOD, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('+', BINEXPR_ADD, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('-', BINEXPR_SUB, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('<', BINEXPR_LESS, get_binexpr_int_type) -CREATE_BINEXPR_PARSER('>', BINEXPR_GREATER, get_binexpr_int_type) -CREATE_BINEXPR_PARSER('=', BINEXPR_ASSIGN, get_binexpr_right_type) -CREATE_BINEXPR_PARSER(T_EQUALEQUAL, BINEXPR_EQUAL, - get_binexpr_int_type) + expression->expression.datatype = type_int; +} + +static void semantic_binexpr_assign(binary_expression_t *expression) +{ + expression_t *left = expression->left; + type_t *type_left = left->datatype; + + semantic_assign(type_left, &expression->right, "assignment"); + + expression->expression.datatype = type_left; +} + +static void semantic_comma(binary_expression_t *expression) +{ + expression->expression.datatype = expression->right->datatype; +} + +#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, sfunc, lr) \ +static expression_t *parse_##binexpression_type(unsigned precedence, \ + expression_t *left) \ +{ \ + eat(token_type); \ + \ + expression_t *right = parse_sub_expression(precedence + lr); \ + \ + binary_expression_t *binexpr \ + = allocate_ast_zero(sizeof(binexpr[0])); \ + binexpr->expression.type = EXPR_BINARY; \ + binexpr->type = binexpression_type; \ + binexpr->left = left; \ + binexpr->right = right; \ + sfunc(binexpr); \ + \ + return (expression_t*) binexpr; \ +} + +CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA, semantic_comma, 1) +CREATE_BINEXPR_PARSER('*', BINEXPR_MUL, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER('/', BINEXPR_DIV, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER('%', BINEXPR_MOD, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER('+', BINEXPR_ADD, semantic_add, 1) +CREATE_BINEXPR_PARSER('-', BINEXPR_SUB, semantic_sub, 1) +CREATE_BINEXPR_PARSER('<', BINEXPR_LESS, semantic_comparison, 1) +CREATE_BINEXPR_PARSER('>', BINEXPR_GREATER, semantic_comparison, 1) +CREATE_BINEXPR_PARSER('=', BINEXPR_ASSIGN, semantic_binexpr_assign, 0) +CREATE_BINEXPR_PARSER(T_EQUALEQUAL, BINEXPR_EQUAL, semantic_comparison, 1) CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, BINEXPR_NOTEQUAL, - get_binexpr_int_type) -CREATE_BINEXPR_PARSER(T_LESSEQUAL, BINEXPR_LESSEQUAL, - get_binexpr_int_type) + semantic_comparison, 1) +CREATE_BINEXPR_PARSER(T_LESSEQUAL, BINEXPR_LESSEQUAL, semantic_comparison, 1) CREATE_BINEXPR_PARSER(T_GREATEREQUAL, BINEXPR_GREATEREQUAL, - get_binexpr_int_type) -CREATE_BINEXPR_PARSER('&', BINEXPR_BITWISE_AND, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('|', BINEXPR_BITWISE_OR, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER('^', BINEXPR_BITWISE_XOR, get_binexpr_arithmetic_type) -CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND, - get_binexpr_int_type) -CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR, - get_binexpr_int_type) + semantic_comparison, 1) +CREATE_BINEXPR_PARSER('&', BINEXPR_BITWISE_AND, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER('|', BINEXPR_BITWISE_OR, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER('^', BINEXPR_BITWISE_XOR, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND, semantic_logical_op, 1) +CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR, semantic_logical_op, 1) +/* TODO shift has a bit special semantic */ CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT, - get_binexpr_arithmetic_type) + semantic_binexpr_arithmetic, 1) CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT, - get_binexpr_arithmetic_type) + semantic_binexpr_arithmetic, 1) CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, BINEXPR_MUL_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_DIV_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, BINEXPR_MOD_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, BINEXPR_SHIFTLEFT_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, BINEXPR_SHIFTRIGHT_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_ANDEQUAL, BINEXPR_BITWISE_AND_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_PIPEEQUAL, BINEXPR_BITWISE_OR_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_CARETEQUAL, BINEXPR_BITWISE_XOR_ASSIGN, - get_binexpr_arithmetic_assign_type) + semantic_arithmetic_assign, 0) static expression_t *parse_sub_expression(unsigned precedence) { @@ -2899,9 +3219,30 @@ static statement_t *parse_return(void) statement->statement.type = STATEMENT_RETURN; statement->statement.source_position = token.source_position; + + assert(current_function->type->type == TYPE_FUNCTION); + function_type_t *function_type = (function_type_t*) current_function->type; + type_t *return_type = function_type->result_type; + + expression_t *return_value; if(token.type != ';') { - statement->return_value = parse_expression(); + return_value = parse_expression(); + + if(return_type == type_void && return_value->datatype != type_void) { + parse_warning("'return' with a value, in function returning void"); + return_value = NULL; + } else { + semantic_assign(return_type, &return_value, "'return'"); + } + } else { + return_value = NULL; + if(return_type != type_void) { + parse_warning("'return' without value, in function returning " + "non-void"); + } } + statement->return_value = return_value; + expect(';'); return (statement_t*) statement; @@ -3113,8 +3454,10 @@ static translation_unit_t *parse_translation_unit(void) translation_unit_t *parse(void) { environment_stack = NEW_ARR_F(stack_entry_t, 0); + found_error = false; type_set_output(stderr); + ast_set_output(stderr); lookahead_bufpos = 0; for(int i = 0; i < MAX_LOOKAHEAD + 2; ++i) { @@ -3124,6 +3467,9 @@ translation_unit_t *parse(void) DEL_ARR_F(environment_stack); + if(found_error) + return NULL; + return unit; } @@ -3132,12 +3478,16 @@ void init_parser(void) init_expression_parsers(); obstack_init(&temp_obst); - type_int = make_atomic_type(ATOMIC_TYPE_INT, 0); - type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE, 0); - type_size_t = make_atomic_type(ATOMIC_TYPE_UINT, 0); - type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST); - type_void = make_atomic_type(ATOMIC_TYPE_VOID, 0); - type_string = make_pointer_type(type_const_char, 0); + type_int = make_atomic_type(ATOMIC_TYPE_INT, 0); + type_uint = make_atomic_type(ATOMIC_TYPE_UINT, 0); + type_long_double = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE, 0); + type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE, 0); + type_float = make_atomic_type(ATOMIC_TYPE_FLOAT, 0); + type_size_t = make_atomic_type(ATOMIC_TYPE_ULONG, 0); + type_ptrdiff_t = make_atomic_type(ATOMIC_TYPE_LONG, 0); + type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST); + type_void = make_atomic_type(ATOMIC_TYPE_VOID, 0); + type_string = make_pointer_type(type_const_char, 0); } void exit_parser(void)