we can now parse the infamous apfel.c, print ast as C and have it compiled and workin...
authorMatthias Braun <matze@braunis.de>
Fri, 28 Sep 2007 19:39:59 +0000 (19:39 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 28 Sep 2007 19:39:59 +0000 (19:39 +0000)
[r18365]

ast.c
parser.c
type.h

diff --git a/ast.c b/ast.c
index f4ba2a4..5fe9918 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -31,6 +31,8 @@ static void print_const(const const_t *cnst)
 
        if(is_type_integer(cnst->expression.datatype)) {
                fprintf(out, "%d", cnst->v.int_value);
+       } else if(is_type_floating(cnst->expression.datatype)) {
+               fprintf(out, "%Lf", cnst->v.float_value);
        }
 }
 
@@ -195,6 +197,17 @@ static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
        fputs(expression->symbol->string, out);
 }
 
+static void print_conditional(const conditional_expression_t *expression)
+{
+       fputs("(", out);
+       print_expression(expression->condition);
+       fputs(" ? ", out);
+       print_expression(expression->true_expression);
+       fputs(" : ", out);
+       print_expression(expression->false_expression);
+       fputs(")", out);
+}
+
 void print_expression(const expression_t *expression)
 {
        switch(expression->type) {
@@ -230,8 +243,10 @@ void print_expression(const expression_t *expression)
        case EXPR_BUILTIN_SYMBOL:
                print_builtin_symbol((const builtin_symbol_expression_t*) expression);
                break;
-
        case EXPR_CONDITIONAL:
+               print_conditional((const conditional_expression_t*) expression);
+               break;
+
        case EXPR_OFFSETOF:
        case EXPR_STATEMENT:
        case EXPR_SELECT:
@@ -351,9 +366,27 @@ static void print_do_while_statement(const do_while_statement_t *statement)
        fputs(");\n", out);
 }
 
-static void print_for_statemenet(const for_statement_t *statement)
+static void print_for_statement(const for_statement_t *statement)
 {
-       fprintf(out, "for(TODO) ");
+       fputs("for(", out);
+       if(statement->context.declarations != NULL) {
+               assert(statement->initialisation == NULL);
+               print_declaration(statement->context.declarations);
+               if(statement->context.declarations->next != NULL) {
+                       panic("multiple declarations in for statement not supported yet");
+               }
+       } else if(statement->initialisation) {
+               print_expression(statement->initialisation);
+       }
+       fputs("; ", out);
+       if(statement->condition != NULL) {
+               print_expression(statement->condition);
+       }
+       fputs("; ", out);
+       if(statement->step != NULL) {
+               print_expression(statement->step);
+       }
+       fputs(")", out);
        print_statement(statement->body);
 }
 
@@ -400,7 +433,7 @@ void print_statement(const statement_t *statement)
                print_do_while_statement((const do_while_statement_t*) statement);
                break;
        case STATEMENT_FOR:
-               print_for_statemenet((const for_statement_t*) statement);
+               print_for_statement((const for_statement_t*) statement);
                break;
        case STATEMENT_INVALID:
                fprintf(out, "*invalid statement*");
index b97339a..eabb57e 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -30,11 +30,13 @@ static token_t               lookahead_buffer[MAX_LOOKAHEAD];
 static int                   lookahead_bufpos;
 static struct obstack        environment_obstack;
 static environment_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;
@@ -1633,7 +1635,7 @@ 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_int;
+       cnst->expression.datatype = type_double;
        cnst->v.float_value       = token.v.floatvalue;
 
        next_token();
@@ -1641,6 +1643,38 @@ static expression_t *parse_float_const(void)
        return (expression_t*) cnst;
 }
 
+static declaration_t *create_implicit_function(symbol_t *symbol,
+               const source_position_t source_position)
+{
+       method_type_t *method_type = allocate_type_zero(sizeof(method_type));
+
+       method_type->type.type              = TYPE_METHOD;
+       method_type->result_type            = type_int;
+       method_type->unspecified_parameters = true;
+
+       type_t *type = typehash_insert((type_t*) method_type);
+       if(type != (type_t*) method_type) {
+               obstack_free(type_obst, method_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;
+
+       /* we have to violate the environment push/pop rules here and assign
+        * the declaration directly to its symbol and append it to the
+        * global context */
+       assert(symbol->declaration == NULL);
+       symbol->declaration          = declaration;
+       declaration->next            = global_context->declarations;
+       global_context->declarations = declaration;
+
+       return declaration;
+}
+
 static expression_t *parse_reference(void)
 {
        reference_expression_t *ref = allocate_ast_zero(sizeof(ref[0]));
@@ -1648,28 +1682,31 @@ static expression_t *parse_reference(void)
        ref->expression.type = EXPR_REFERENCE;
        ref->symbol          = token.v.symbol;
 
-       declaration_t *declaration = ref->symbol->declaration;
+       declaration_t     *declaration     = ref->symbol->declaration;
+       source_position_t  source_position = token.source_position;
        next_token();
 
        if(declaration == NULL) {
 #ifndef STRICT_C99
-               /* is it an implicitely defined function */
+               /* 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);
-                       /* TODO: do this correctly */
+
+                       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;
                }
-#endif
-
-               parser_print_error_prefix();
-               fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
-       } else {
-               ref->declaration         = declaration;
-               ref->expression.datatype = declaration->type;
        }
 
+       ref->declaration         = declaration;
+       ref->expression.datatype = declaration->type;
 
        return (expression_t*) ref;
 }
@@ -2797,6 +2834,9 @@ static translation_unit_t *parse_translation_unit(void)
 {
        translation_unit_t *unit = allocate_ast_zero(sizeof(unit[0]));
 
+       assert(global_context == NULL);
+       global_context = &unit->context;
+
        assert(context == NULL);
        set_context(&unit->context);
 
@@ -2808,6 +2848,9 @@ static translation_unit_t *parse_translation_unit(void)
        context          = NULL;
        last_declaration = NULL;
 
+       assert(global_context == &unit->context);
+       global_context = NULL;
+
        return unit;
 }
 
@@ -2836,6 +2879,7 @@ void init_parser(void)
        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);
diff --git a/type.h b/type.h
index 23d1019..7f2778e 100644 (file)
--- a/type.h
+++ b/type.h
@@ -37,6 +37,11 @@ void type_set_output(FILE *out);
  */
 bool is_type_integer(const type_t *type);
 
+/**
+ * returns true if type contains floating point numbers
+ */
+bool is_type_floating(const type_t *type);
+
 /**
  * returns true if the type is valid. A type is valid if it contains no
  * unresolved references anymore and is not of TYPE_INVALID.