+ return 0;
+ }
+}
+
+static expression_t *parse_sizeof(unsigned precedence)
+{
+ eat(T_sizeof);
+
+ sizeof_expression_t *sizeof_expression
+ = allocate_ast_zero(sizeof(sizeof_expression[0]));
+ sizeof_expression->expression.type = EXPR_SIZEOF;
+ sizeof_expression->expression.datatype = type_size_t;
+
+ if(token.type == '(' && is_declaration_specifier(look_ahead(1), true)) {
+ next_token();
+ sizeof_expression->type = parse_typename();
+ expect(')');
+ } else {
+ expression_t *expression = parse_sub_expression(precedence);
+ sizeof_expression->type = expression->datatype;
+ sizeof_expression->size_expression = expression;
+ }
+
+ return (expression_t*) sizeof_expression;
+}
+
+static expression_t *parse_select_expression(unsigned precedence,
+ expression_t *compound)
+{
+ (void) precedence;
+ assert(token.type == '.' || token.type == T_MINUSGREATER);
+
+ bool is_pointer = (token.type == T_MINUSGREATER);
+ next_token();
+
+ select_expression_t *select = allocate_ast_zero(sizeof(select[0]));
+
+ select->expression.type = EXPR_SELECT;
+ select->compound = compound;
+
+ if(token.type != T_IDENTIFIER) {
+ parse_error_expected("while parsing select", T_IDENTIFIER, 0);
+ return (expression_t*) select;
+ }
+ symbol_t *symbol = token.v.symbol;
+ select->symbol = symbol;
+ next_token();
+
+ type_t *orig_type = compound->datatype;
+ if(orig_type == NULL)
+ return make_invalid_expression();
+
+ type_t *type = skip_typeref(orig_type);
+
+ type_t *type_left = type;
+ if(is_pointer) {
+ if(type->type != TYPE_POINTER) {
+ parser_print_error_prefix();
+ fprintf(stderr, "left hand side of '->' is not a pointer, but ");
+ print_type_quoted(orig_type);
+ fputc('\n', stderr);
+ return make_invalid_expression();
+ }
+ pointer_type_t *pointer_type = (pointer_type_t*) type;
+ type_left = pointer_type->points_to;
+ }
+ type_left = skip_typeref(type_left);
+
+ if(type_left->type != TYPE_COMPOUND_STRUCT
+ && type_left->type != TYPE_COMPOUND_UNION) {
+ parser_print_error_prefix();
+ fprintf(stderr, "request for member '%s' in something not a struct or "
+ "union, but ", symbol->string);
+ print_type_quoted(type_left);
+ fputc('\n', stderr);
+ return make_invalid_expression();
+ }
+
+ compound_type_t *compound_type = (compound_type_t*) type_left;
+ declaration_t *declaration = compound_type->declaration;
+
+ if(!declaration->init.is_defined) {
+ parser_print_error_prefix();
+ fprintf(stderr, "request for member '%s' of incomplete type ",
+ symbol->string);
+ print_type_quoted(type_left);
+ fputc('\n', stderr);
+ return make_invalid_expression();
+ }
+
+ declaration_t *iter = declaration->context.declarations;
+ for( ; iter != NULL; iter = iter->next) {
+ if(iter->symbol == symbol) {
+ break;
+ }
+ }
+ if(iter == NULL) {
+ parser_print_error_prefix();
+ print_type_quoted(type_left);
+ fprintf(stderr, " has no member named '%s'\n", symbol->string);
+ return make_invalid_expression();
+ }
+
+ select->compound_entry = iter;
+ select->expression.datatype = iter->type;
+ return (expression_t*) select;
+}
+
+static expression_t *parse_call_expression(unsigned precedence,
+ expression_t *expression)
+{
+ (void) precedence;
+ call_expression_t *call = allocate_ast_zero(sizeof(call[0]));
+ call->expression.type = EXPR_CALL;
+ call->function = expression;
+
+ function_type_t *function_type;
+ type_t *orig_type = expression->datatype;
+ type_t *type = skip_typeref(orig_type);
+
+ if(type->type == TYPE_POINTER) {
+ pointer_type_t *pointer_type = (pointer_type_t*) type;
+
+ type = skip_typeref(pointer_type->points_to);
+ }
+ if (type->type == TYPE_FUNCTION) {
+ function_type = (function_type_t*) type;
+ call->expression.datatype = function_type->result_type;
+ } else {
+ parser_print_error_prefix();
+ fputs("called object '", stderr);
+ print_expression(expression);
+ fputs("' (type ", stderr);
+ print_type_quoted(orig_type);
+ fputs(") is not a function\n", stderr);
+
+ function_type = NULL;
+ call->expression.datatype = NULL;
+ }
+
+ /* parse arguments */
+ eat('(');
+
+ if(token.type != ')') {
+ call_argument_t *last_argument = NULL;
+
+ while(true) {
+ call_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
+
+ argument->expression = parse_assignment_expression();
+ if(last_argument == NULL) {
+ call->arguments = argument;
+ } else {
+ last_argument->next = argument;
+ }
+ last_argument = argument;
+
+ if(token.type != ',')
+ break;
+ next_token();
+ }
+ }
+ expect(')');
+
+ 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);
+ }
+ /* too few parameters */
+ if(parameter != NULL) {
+ parser_print_error_prefix();
+ 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(type == NULL)
+ continue;
+
+ 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 type_t *semantic_arithmetic(type_t *type_left, type_t *type_right);
+
+static expression_t *parse_conditional_expression(unsigned precedence,
+ expression_t *expression)
+{
+ eat('?');
+
+ conditional_expression_t *conditional
+ = allocate_ast_zero(sizeof(conditional[0]));
+ conditional->expression.type = EXPR_CONDITIONAL;
+ conditional->condition = expression;
+
+ /* 6.5.15.2 */
+ type_t *condition_type_orig = conditional->condition->datatype;
+ if(condition_type_orig != NULL) {
+ type_t *condition_type = skip_typeref(condition_type_orig);
+ if(condition_type != NULL && !is_type_scalar(condition_type)) {
+ type_error("expected a scalar type", expression->source_position,
+ condition_type_orig);
+ }
+ }
+
+ expression_t *const t_expr = parse_expression();
+ conditional->true_expression = t_expr;
+ expect(':');
+ expression_t *const f_expr = parse_sub_expression(precedence);
+ conditional->false_expression = f_expr;
+
+ type_t *const true_type = t_expr->datatype;
+ if(true_type == NULL)
+ return (expression_t*) conditional;
+ type_t *const false_type = f_expr->datatype;
+ if(false_type == NULL)
+ return (expression_t*) conditional;
+
+ type_t *const skipped_true_type = skip_typeref(true_type);
+ type_t *const skipped_false_type = skip_typeref(false_type);
+
+ /* 6.5.15.3 */
+ if (skipped_true_type == skipped_false_type) {
+ conditional->expression.datatype = skipped_true_type;
+ } else if (is_type_arithmetic(skipped_true_type) &&
+ is_type_arithmetic(skipped_false_type)) {
+ type_t *const result = semantic_arithmetic(skipped_true_type,
+ skipped_false_type);
+ conditional->true_expression = create_implicit_cast(t_expr, result);
+ conditional->false_expression = create_implicit_cast(f_expr, result);
+ conditional->expression.datatype = result;
+ } else if (skipped_true_type->type == TYPE_POINTER &&
+ skipped_false_type->type == TYPE_POINTER &&
+ true /* TODO compatible points_to types */) {
+ /* TODO */
+ } else if(/* (is_null_ptr_const(skipped_true_type) &&
+ skipped_false_type->type == TYPE_POINTER)
+ || (is_null_ptr_const(skipped_false_type) &&
+ skipped_true_type->type == TYPE_POINTER) TODO*/ false) {
+ /* TODO */
+ } else if(/* 1 is pointer to object type, other is void* */ false) {
+ /* TODO */
+ } else {
+ type_error_incompatible("while parsing conditional",
+ expression->source_position, true_type,
+ skipped_false_type);
+ }
+
+ return (expression_t*) conditional;
+}
+
+static expression_t *parse_extension(unsigned precedence)
+{
+ eat(T___extension__);
+
+ /* TODO enable extensions */
+
+ return parse_sub_expression(precedence);
+}
+
+static expression_t *parse_builtin_classify_type(const unsigned precedence)
+{
+ eat(T___builtin_classify_type);
+
+ classify_type_expression_t *const classify_type_expr =
+ allocate_ast_zero(sizeof(classify_type_expr[0]));
+ classify_type_expr->expression.type = EXPR_CLASSIFY_TYPE;
+ classify_type_expr->expression.datatype = type_int;
+
+ expect('(');
+ expression_t *const expression = parse_sub_expression(precedence);
+ expect(')');
+ classify_type_expr->type_expression = expression;
+
+ return (expression_t*)classify_type_expr;
+}
+
+static void semantic_incdec(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if(!is_type_arithmetic(type) && type->type != TYPE_POINTER) {
+ /* TODO: improve error message */
+ parser_print_error_prefix();
+ fprintf(stderr, "operation needs an arithmetic or pointer type\n");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_arithmetic(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if(!is_type_arithmetic(type)) {
+ /* TODO: improve error message */
+ parser_print_error_prefix();
+ fprintf(stderr, "operation needs an arithmetic type\n");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_scalar(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_scalar(type)) {
+ parse_error("operand of ! must be of scalar type\n");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_integer(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_integer(type)) {
+ parse_error("operand of ~ must be of integer type\n");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_dereference(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ switch (type->type) {
+ case TYPE_ARRAY: {
+ array_type_t *const array_type = (array_type_t*)type;
+ expression->expression.datatype = array_type->element_type;
+ break;
+ }
+
+ case TYPE_POINTER: {
+ pointer_type_t *pointer_type = (pointer_type_t*)type;
+ expression->expression.datatype = pointer_type->points_to;
+ break;
+ }
+
+ default:
+ parser_print_error_prefix();
+ fputs("'Unary *' needs pointer or arrray type, but type ", stderr);
+ print_type_quoted(orig_type);
+ fputs(" given.\n", stderr);
+ return;