+static void parse_compound_type_entries(void)
+{
+ eat('{');
+
+ while(token.type != '}' && token.type != T_EOF) {
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+
+ parse_struct_declarators(&specifiers);
+ }
+ if(token.type == T_EOF) {
+ parse_error("unexpected error while parsing struct");
+ }
+ next_token();
+}
+
+static void parse_declaration(void)
+{
+ source_position_t source_position = token.source_position;
+
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+
+ if(token.type == ';') {
+ next_token();
+
+ declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+
+ declaration->type = specifiers.type;
+ declaration->storage_class = specifiers.storage_class;
+ declaration->source_position = source_position;
+ record_declaration(declaration);
+ return;
+ }
+ parse_init_declarators(&specifiers);
+}
+
+static type_t *parse_typename(void)
+{
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+ if(specifiers.storage_class != STORAGE_CLASS_NONE) {
+ /* TODO: improve error message, user does probably not know what a
+ * storage class is...
+ */
+ parse_error("typename may not have a storage class");
+ }
+
+ type_t *result = parse_abstract_declarator(specifiers.type);
+
+ return result;
+}
+
+
+
+
+typedef expression_t* (*parse_expression_function) (unsigned precedence);
+typedef expression_t* (*parse_expression_infix_function) (unsigned precedence,
+ expression_t *left);
+
+typedef struct expression_parser_function_t expression_parser_function_t;
+struct expression_parser_function_t {
+ unsigned precedence;
+ parse_expression_function parser;
+ unsigned infix_precedence;
+ parse_expression_infix_function infix_parser;
+};
+
+expression_parser_function_t expression_parsers[T_LAST_TOKEN];
+
+static expression_t *expected_expression_error(void)
+{
+ parser_print_error_prefix();
+ fprintf(stderr, "expected expression, got token ");
+ print_token(stderr, & token);
+ fprintf(stderr, "\n");
+
+ expression_t *expression = allocate_ast_zero(sizeof(expression[0]));
+ expression->type = EXPR_INVALID;
+ next_token();
+
+ return expression;
+}
+
+static expression_t *parse_string_const(void)
+{
+ string_literal_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
+
+ cnst->expression.type = EXPR_STRING_LITERAL;
+ cnst->expression.datatype = type_string;
+ cnst->value = parse_string_literals();
+
+ return (expression_t*) cnst;
+}
+
+static expression_t *parse_int_const(void)
+{
+ const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
+
+ cnst->expression.type = EXPR_CONST;
+ cnst->expression.datatype = type_int;
+ cnst->v.int_value = token.v.intvalue;
+
+ next_token();
+
+ return (expression_t*) cnst;
+}
+
+static expression_t *parse_float_const(void)
+{
+ const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
+
+ cnst->expression.type = EXPR_CONST;
+ cnst->expression.datatype = type_double;
+ cnst->v.float_value = token.v.floatvalue;
+
+ next_token();
+
+ return (expression_t*) cnst;
+}
+
+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->type.type = TYPE_FUNCTION;
+ function_type->result_type = type_int;
+ function_type->unspecified_parameters = true;
+
+ type_t *type = typehash_insert((type_t*) function_type);
+ if(type != (type_t*) function_type) {
+ free_type(function_type);
+ }
+
+ declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+
+ declaration->storage_class = STORAGE_CLASS_EXTERN;
+ declaration->type = type;
+ declaration->symbol = symbol;
+ declaration->source_position = source_position;
+
+ /* prepend the implicit definition to the global context
+ * this is safe since the symbol wasn't declared as anything else yet
+ */
+ assert(symbol->declaration == NULL);
+
+ context_t *last_context = context;
+ context = global_context;
+
+ environment_push(declaration);
+ declaration->context_next = context->declarations;
+ context->declarations = declaration;
+
+ context = last_context;
+
+ return declaration;
+}
+
+static expression_t *parse_reference(void)
+{
+ reference_expression_t *ref = allocate_ast_zero(sizeof(ref[0]));
+
+ ref->expression.type = EXPR_REFERENCE;
+ ref->symbol = token.v.symbol;
+
+ declaration_t *declaration = get_declaration(ref->symbol, NAMESPACE_NORMAL);
+
+ source_position_t source_position = token.source_position;
+ next_token();
+
+ if(declaration == NULL) {
+#ifndef STRICT_C99
+ /* an implicitely defined function */
+ if(token.type == '(') {
+ parser_print_prefix_pos(token.source_position);
+ fprintf(stderr, "warning: implicit declaration of function '%s'\n",
+ ref->symbol->string);
+
+ declaration = create_implicit_function(ref->symbol,
+ source_position);
+ } else
+#endif
+ {
+ parser_print_error_prefix();
+ fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
+ return (expression_t*) ref;
+ }
+ }
+
+ ref->declaration = declaration;
+ ref->expression.datatype = declaration->type;
+
+ return (expression_t*) ref;
+}
+
+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 */
+}
+
+static expression_t *parse_cast(void)
+{
+ unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
+
+ cast->expression.type = EXPR_UNARY;
+ cast->type = UNEXPR_CAST;
+ cast->expression.source_position = token.source_position;
+
+ type_t *type = parse_typename();
+
+ expect(')');
+ expression_t *value = parse_sub_expression(20);
+
+ check_cast_allowed(value, type);
+
+ cast->expression.datatype = type;
+ cast->value = value;
+
+ return (expression_t*) cast;
+}
+
+static expression_t *parse_statement_expression(void)