- countless bugfixes
authorMatthias Braun <matze@braunis.de>
Sun, 16 Sep 2007 13:36:11 +0000 (13:36 +0000)
committerMatthias Braun <matze@braunis.de>
Sun, 16 Sep 2007 13:36:11 +0000 (13:36 +0000)
- implement octal and hexadecimal escape sequences
- implemented more gcc extensions

[r18353]

12 files changed:
ast.c
ast.h
ast_t.h
lexer.c
lexer.h
parser.c
tokens.inc
type.c
type.h
type_hash.c
type_t.h
write_fluffy.c

diff --git a/ast.c b/ast.c
index f2bc587..5971255 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -6,6 +6,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <ctype.h>
 
 #include "adt/error.h"
 
@@ -15,6 +16,7 @@ static FILE *out;
 static int   indent;
 
 static void print_statement(const statement_t *statement);
+static void print_declaration(const declaration_t *declaration);
 
 static void print_indent(void)
 {
@@ -22,21 +24,39 @@ static void print_indent(void)
                fprintf(out, "\t");
 }
 
-static
-void print_const(const const_t *cnst)
+static void print_const(const const_t *cnst)
 {
        fprintf(out, "%d", cnst->value);
 }
 
-static
-void print_string_literal(const string_literal_t *string_literal)
+static void print_string_literal(const string_literal_t *string_literal)
 {
-       /* TODO escape " and non-printable chars */
-       fprintf(out, "\"%s\"", string_literal->value);
+       fputc('"', out);
+       for(const char *c = string_literal->value; *c != '\0'; ++c) {
+               switch(*c) {
+               case '\"':  fputs("\\\"", out); break;
+               case '\\':  fputs("\\\\", out); break;
+               case '\a':  fputs("\\a", out); break;
+               case '\b':  fputs("\\b", out); break;
+               case '\f':  fputs("\\f", out); break;
+               case '\n':  fputs("\\n", out); break;
+               case '\r':  fputs("\\r", out); break;
+               case '\t':  fputs("\\t", out); break;
+               case '\v':  fputs("\\v", out); break;
+               case '\?':  fputs("\\?", out); break;
+               default:
+                       if(!isprint(*c)) {
+                               fprintf(out, "\\x%x", *c);
+                               break;
+                       }
+                       fputc(*c, out);
+                       break;
+               }
+       }
+       fputc('"', out);
 }
 
-static
-void print_call_expression(const call_expression_t *call)
+static void print_call_expression(const call_expression_t *call)
 {
        print_expression(call->method);
        fprintf(out, "(");
@@ -55,58 +75,116 @@ void print_call_expression(const call_expression_t *call)
        fprintf(out, ")");
 }
 
-static
-void print_binary_expression(const binary_expression_t *binexpr)
+static void print_binary_expression(const binary_expression_t *binexpr)
 {
        fprintf(out, "(");
        print_expression(binexpr->left);
        fprintf(out, " ");
        switch(binexpr->type) {
-       case BINEXPR_INVALID:
-               fprintf(out, "INVOP");
-               break;
-       case BINEXPR_ASSIGN:
-               fprintf(out, "<-");
-               break;
-       case BINEXPR_ADD:
-               fprintf(out, "+");
-               break;
-       case BINEXPR_SUB:
-               fprintf(out, "-");
-               break;
-       case BINEXPR_NOTEQUAL:
-               fprintf(out, "/=");
-               break;
-       case BINEXPR_EQUAL:
-               fprintf(out, "=");
-               break;
-       case BINEXPR_LESS:
-               fprintf(out, "<");
-               break;
-       case BINEXPR_LESSEQUAL:
-               fprintf(out, "<=");
-               break;
-       case BINEXPR_GREATER:
-               fprintf(out, ">");
-               break;
-       case BINEXPR_GREATEREQUAL:
-               fprintf(out, ">=");
-               break;
-       default:
-               /* TODO: add missing ops */
-               fprintf(out, "op%d", binexpr->type);
-               break;
+       case BINEXPR_INVALID:            fputs("INVOP", out); break;
+       case BINEXPR_COMMA:              fputs(",", out);     break;
+       case BINEXPR_ASSIGN:             fputs("=", out);     break;
+       case BINEXPR_ADD:                fputs("+", out);     break;
+       case BINEXPR_SUB:                fputs("-", out);     break;
+       case BINEXPR_MUL:                fputs("*", out);     break;
+       case BINEXPR_MOD:                fputs("%", out);     break;
+       case BINEXPR_DIV:                fputs("/", out);     break;
+       case BINEXPR_BITWISE_OR:         fputs("|", out);     break;
+       case BINEXPR_BITWISE_AND:        fputs("&", out);     break;
+       case BINEXPR_BITWISE_XOR:        fputs("^", out);     break;
+       case BINEXPR_LOGICAL_OR:         fputs("||", out);    break;
+       case BINEXPR_LOGICAL_AND:        fputs("&&", out);    break;
+       case BINEXPR_NOTEQUAL:           fputs("!=", out);    break;
+       case BINEXPR_EQUAL:              fputs("==", out);    break;
+       case BINEXPR_LESS:               fputs("<", out);     break;
+       case BINEXPR_LESSEQUAL:          fputs("<=", out);    break;
+       case BINEXPR_GREATER:            fputs(">", out);     break;
+       case BINEXPR_GREATEREQUAL:       fputs(">=", out);    break;
+       case BINEXPR_SHIFTLEFT:          fputs("<<", out);    break;
+       case BINEXPR_SHIFTRIGHT:         fputs(">>", out);    break;
+
+       case BINEXPR_ADD_ASSIGN:         fputs("+=", out);    break;
+       case BINEXPR_SUB_ASSIGN:         fputs("-=", out);    break;
+       case BINEXPR_MUL_ASSIGN:         fputs("*=", out);    break;
+       case BINEXPR_MOD_ASSIGN:         fputs("%=", out);    break;
+       case BINEXPR_DIV_ASSIGN:         fputs("/=", out);    break;
+       case BINEXPR_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
+       case BINEXPR_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
+       case BINEXPR_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
+       case BINEXPR_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
+       case BINEXPR_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
        }
        fprintf(out, " ");
        print_expression(binexpr->right);
        fprintf(out, ")");
 }
 
+static void print_unary_expression(const unary_expression_t *unexpr)
+{
+       switch(unexpr->type) {
+       case UNEXPR_NEGATE:           fputs("-", out);  break;
+       case UNEXPR_PLUS:             fputs("+", out);  break;
+       case UNEXPR_NOT:              fputs("!", out);  break;
+       case UNEXPR_BITWISE_NEGATE:   fputs("~", out);  break;
+       case UNEXPR_PREFIX_INCREMENT: fputs("++", out); break;
+       case UNEXPR_PREFIX_DECREMENT: fputs("--", out); break;
+       case UNEXPR_DEREFERENCE:      fputs("*", out);  break;
+       case UNEXPR_TAKE_ADDRESS:     fputs("&", out);  break;
+
+       case UNEXPR_POSTFIX_INCREMENT:
+               fputs("(", out);
+               print_expression(unexpr->value);
+               fputs(")", out);
+               fputs("++", out);
+               return;
+       case UNEXPR_POSTFIX_DECREMENT:
+               fputs("(", out);
+               print_expression(unexpr->value);
+               fputs(")", out);
+               fputs("--", out);
+               return;
+       case UNEXPR_CAST:
+               fputs("(", out);
+               print_type(unexpr->expression.datatype);
+               fputs(")", out);
+               break;
+       case UNEXPR_INVALID:
+               fprintf(out, "unop%d", unexpr->type);
+               break;
+       }
+       fputs("(", out);
+       print_expression(unexpr->value);
+       fputs(")", out);
+}
+
 static void print_reference_expression(const reference_expression_t *ref)
 {
        fprintf(out, "%s", ref->declaration->symbol->string);
 }
 
+static void print_array_expression(const array_access_expression_t *expression)
+{
+       fputs("(", out);
+       print_expression(expression->array_ref);
+       fputs(")[", out);
+       print_expression(expression->index);
+       fputs("]", out);
+}
+
+static void print_sizeof_expression(const sizeof_expression_t *expression)
+{
+       fputs("sizeof", out);
+       if(expression->size_expression != NULL) {
+               fputc('(', out);
+               print_expression(expression->size_expression);
+               fputc(')', out);
+       } else {
+               fputc('(', out);
+               print_type(expression->type);
+               fputc(')', out);
+       }
+}
+
 void print_expression(const expression_t *expression)
 {
        switch(expression->type) {
@@ -116,6 +194,8 @@ void print_expression(const expression_t *expression)
        case EXPR_CONST:
                print_const((const const_t*) expression);
                break;
+       case EXPR_FUNCTION:
+       case EXPR_PRETTY_FUNCTION:
        case EXPR_STRING_LITERAL:
                print_string_literal((const string_literal_t*) expression);
                break;
@@ -128,18 +208,25 @@ void print_expression(const expression_t *expression)
        case EXPR_REFERENCE:
                print_reference_expression((const reference_expression_t*) expression);
                break;
-       case EXPR_UNARY:
-       case EXPR_SELECT:
        case EXPR_ARRAY_ACCESS:
+               print_array_expression((const array_access_expression_t*) expression);
+               break;
+       case EXPR_UNARY:
+               print_unary_expression((const unary_expression_t*) expression);
+               break;
        case EXPR_SIZEOF:
+               print_sizeof_expression((const sizeof_expression_t*) expression);
+               break;
+
+       case EXPR_STATEMENT:
+       case EXPR_SELECT:
                /* TODO */
                fprintf(out, "some expression of type %d", expression->type);
                break;
        }
 }
 
-static
-void print_compound_statement(const compound_statement_t *block)
+static void print_compound_statement(const compound_statement_t *block)
 {
        fputs("{\n", out);
        indent++;
@@ -156,8 +243,7 @@ void print_compound_statement(const compound_statement_t *block)
        fputs("}\n", out);
 }
 
-static
-void print_return_statement(const return_statement_t *statement)
+static void print_return_statement(const return_statement_t *statement)
 {
        fprintf(out, "return ");
        if(statement->return_value != NULL)
@@ -165,14 +251,13 @@ void print_return_statement(const return_statement_t *statement)
        fputs(";\n", out);
 }
 
-static
-void print_expression_statement(const expression_statement_t *statement)
+static void print_expression_statement(const expression_statement_t *statement)
 {
        print_expression(statement->expression);
+       fputs(";\n", out);
 }
 
-static
-void print_goto_statement(const goto_statement_t *statement)
+static void print_goto_statement(const goto_statement_t *statement)
 {
        fprintf(out, "goto ");
        if(statement->label != NULL) {
@@ -183,34 +268,78 @@ void print_goto_statement(const goto_statement_t *statement)
        fputs(";\n", out);
 }
 
-static
-void print_label_statement(const label_statement_t *statement)
+static void print_label_statement(const label_statement_t *statement)
 {
        fprintf(out, "%s:\n", statement->symbol->string);
 }
 
-static
-void print_if_statement(const if_statement_t *statement)
+static void print_if_statement(const if_statement_t *statement)
 {
-       fprintf(out, "if(");
+       fputs("if(", out);
        print_expression(statement->condition);
-       fprintf(out, ") ");
+       fputs(") ", out);
        if(statement->true_statement != NULL) {
                print_statement(statement->true_statement);
        }
 
        if(statement->false_statement != NULL) {
                print_indent();
-               fprintf(out, "else ");
+               fputs("else ", out);
                print_statement(statement->false_statement);
        }
 }
 
-static
-void print_declaration_statement(const declaration_statement_t *statement)
+static void print_switch_statement(const switch_statement_t *statement)
+{
+       fputs("switch(", out);
+       print_expression(statement->expression);
+       fputs(") ", out);
+       print_statement(statement->body);
+}
+
+static void print_case_label(const case_label_statement_t *statement)
 {
-       (void) statement;
-       fprintf(out, "*declaration statement*");
+       if(statement->expression == NULL) {
+               fputs("default:\n", out);
+       } else {
+               fputs("case ", out);
+               print_expression(statement->expression);
+               fputs(":\n", out);
+       }
+}
+
+static void print_declaration_statement(
+               const declaration_statement_t *statement)
+{
+       declaration_t *declaration = statement->declarations_begin;
+       for( ; declaration != statement->declarations_end->next;
+              declaration = declaration->next) {
+               print_declaration(declaration);
+       }
+}
+
+static void print_while_statement(const while_statement_t *statement)
+{
+       fputs("while(", out);
+       print_expression(statement->condition);
+       fputs(") ", out);
+       print_statement(statement->body);
+}
+
+static void print_do_while_statement(const do_while_statement_t *statement)
+{
+       fputs("do ", out);
+       print_statement(statement->body);
+       print_indent();
+       fputs("while(", out);
+       print_expression(statement->condition);
+       fputs(");\n", out);
+}
+
+static void print_for_statemenet(const for_statement_t *statement)
+{
+       fprintf(out, "for(TODO) ");
+       print_statement(statement->body);
 }
 
 void print_statement(const statement_t *statement)
@@ -231,54 +360,43 @@ void print_statement(const statement_t *statement)
        case STATEMENT_GOTO:
                print_goto_statement((const goto_statement_t*) statement);
                break;
+       case STATEMENT_CONTINUE:
+               fputs("continue;\n", out);
+               break;
+       case STATEMENT_BREAK:
+               fputs("break;\n", out);
+               break;
        case STATEMENT_IF:
                print_if_statement((const if_statement_t*) statement);
                break;
+       case STATEMENT_SWITCH:
+               print_switch_statement((const switch_statement_t*) statement);
+               break;
+       case STATEMENT_CASE_LABEL:
+               print_case_label((const case_label_statement_t*) statement);
+               break;
        case STATEMENT_DECLARATION:
                print_declaration_statement((const declaration_statement_t*) statement);
                break;
+       case STATEMENT_WHILE:
+               print_while_statement((const while_statement_t*) statement);
+               break;
+       case STATEMENT_DO_WHILE:
+               print_do_while_statement((const do_while_statement_t*) statement);
+               break;
+       case STATEMENT_FOR:
+               print_for_statemenet((const for_statement_t*) statement);
+               break;
        case STATEMENT_INVALID:
-       default:
                fprintf(out, "*invalid statement*");
                break;
-
-       }
-}
-
-#if 0
-static
-void print_method_parameters(const method_parameter_t *parameters,
-                             const method_type_t *method_type)
-{
-       fprintf(out, "(");
-
-       int                            first          = 1;
-       const method_parameter_t      *parameter      = parameters;
-       const method_parameter_type_t *parameter_type
-               = method_type->parameter_types;
-       while(parameter != NULL && parameter_type != NULL) {
-               if(!first) {
-                       fprintf(out, ", ");
-               } else {
-                       first = 0;
-               }
-
-               print_type(parameter_type->type);
-               fprintf(out, " %s", parameter->symbol->string);
-
-               parameter      = parameter->next;
-               parameter_type = parameter_type->next;
        }
-       assert(parameter == NULL && parameter_type == NULL);
-
-       fprintf(out, ")");
 }
-#endif
 
-static
-void print_storage_class(storage_class_t storage_class)
+static void print_storage_class(storage_class_t storage_class)
 {
        switch(storage_class) {
+       case STORAGE_CLASS_ENUM_ENTRY:
        case STORAGE_CLASS_NONE:
                break;
        case STORAGE_CLASS_TYPEDEF:  fputs("typedef ", out); break;
@@ -289,14 +407,18 @@ void print_storage_class(storage_class_t storage_class)
        }
 }
 
-static
-void print_declaration(const declaration_t *declaration)
+static void print_declaration(const declaration_t *declaration)
 {
        print_storage_class(declaration->storage_class);
-       print_type(declaration->type, declaration->symbol);
+       print_type_ext(declaration->type, declaration->symbol,
+                      &declaration->context);
        if(declaration->statement != NULL) {
                fputs("\n", out);
                print_statement(declaration->statement);
+       } else if(declaration->initializer != NULL) {
+               fputs(" = ", out);
+               print_expression(declaration->initializer);
+               fprintf(out, ";\n");
        } else {
                fprintf(out, ";\n");
        }
diff --git a/ast.h b/ast.h
index aee5067..acbdade 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -21,6 +21,7 @@ typedef struct sizeof_expression_t        sizeof_expression_t;
 typedef struct conditional_expression_t   conditional_expression_t;
 typedef struct expression_list_element_t  expression_list_element_t;
 typedef struct comma_expression_t         comma_expression_t;
+typedef struct statement_expression_t     statement_expression_t;
 
 typedef struct declaration_t              declaration_t;
 
@@ -28,10 +29,15 @@ typedef struct statement_t                statement_t;
 typedef struct compound_statement_t       compound_statement_t;
 typedef struct return_statement_t         return_statement_t;
 typedef struct if_statement_t             if_statement_t;
+typedef struct switch_statement_t         switch_statement_t;
 typedef struct declaration_statement_t    declaration_statement_t;
 typedef struct expression_statement_t     expression_statement_t;
 typedef struct goto_statement_t           goto_statement_t;
 typedef struct label_statement_t          label_statement_t;
+typedef struct case_label_statement_t     case_label_statement_t;
+typedef struct while_statement_t          while_statement_t;
+typedef struct do_while_statement_t       do_while_statement_t;
+typedef struct for_statement_t            for_statement_t;
 
 typedef struct translation_unit_t         translation_unit_t;
 typedef struct method_t                   method_t;
diff --git a/ast_t.h b/ast_t.h
index 92a8c88..fb67708 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -20,13 +20,17 @@ typedef enum {
        EXPR_SELECT,
        EXPR_ARRAY_ACCESS,
        EXPR_SIZEOF,
+
+       EXPR_FUNCTION,
+       EXPR_PRETTY_FUNCTION,
+       EXPR_STATEMENT
 } expresion_type_t;
 
 struct context_t {
        declaration_t   *declarations;
        compound_type_t *structs;
        compound_type_t *unions;
-       compound_type_t *enums;
+       enum_type_t     *enums;
 };
 
 struct expression_t {
@@ -113,7 +117,8 @@ typedef enum {
        BINEXPR_SHIFTRIGHT_ASSIGN,
        BINEXPR_BITWISE_AND_ASSIGN,
        BINEXPR_BITWISE_XOR_ASSIGN,
-       BINEXPR_BITWISE_OR_ASSIGN
+       BINEXPR_BITWISE_OR_ASSIGN,
+       BINEXPR_COMMA
 } binary_expression_type_t;
 
 struct binary_expression_t {
@@ -140,6 +145,7 @@ struct array_access_expression_t {
 struct sizeof_expression_t {
        expression_t  expression;
        type_t       *type;
+       expression_t *size_expression;
 };
 
 struct conditional_expression_t {
@@ -149,14 +155,9 @@ struct conditional_expression_t {
        expression_t *false_expression;
 };
 
-struct expression_list_element_t {
-       expression_t *expression;
-       expression_t *next;
-};
-
-struct comma_expression_t {
-       expression_t               expression;
-       expression_list_element_t *expressions;
+struct statement_expression_t {
+       expression_t  expression;
+       statement_t  *statement;
 };
 
 typedef enum {
@@ -165,7 +166,8 @@ typedef enum {
        STORAGE_CLASS_EXTERN,
        STORAGE_CLASS_STATIC,
        STORAGE_CLASS_AUTO,
-       STORAGE_CLASS_REGISTER
+       STORAGE_CLASS_REGISTER,
+       STORAGE_CLASS_ENUM_ENTRY
 } storage_class_t;
 
 struct declaration_t {
@@ -186,10 +188,16 @@ typedef enum {
        STATEMENT_RETURN,
        STATEMENT_DECLARATION,
        STATEMENT_IF,
+       STATEMENT_SWITCH,
        STATEMENT_EXPRESSION,
        STATEMENT_CONTINUE,
+       STATEMENT_BREAK,
        STATEMENT_GOTO,
-       STATEMENT_LABEL
+       STATEMENT_LABEL,
+       STATEMENT_CASE_LABEL,
+       STATEMENT_WHILE,
+       STATEMENT_DO_WHILE,
+       STATEMENT_FOR
 } statement_type_t;
 
 struct statement_t {
@@ -211,7 +219,8 @@ struct compound_statement_t {
 
 struct declaration_statement_t {
        statement_t    statement;
-       declaration_t  declaration;
+       declaration_t *declarations_begin;
+       declaration_t *declarations_end;
 
        int            value_number; /**< filled in by semantic phase */
        int            refs;
@@ -224,12 +233,23 @@ struct if_statement_t {
        statement_t  *false_statement;
 };
 
+struct switch_statement_t {
+       statement_t   statement;
+       expression_t *expression;
+       statement_t  *body;
+};
+
 struct goto_statement_t {
        statement_t        statement;
        symbol_t          *label_symbol;
        label_statement_t *label;
 };
 
+struct case_label_statement_t {
+       statement_t   statement;
+       expression_t *expression;
+};
+
 struct label_statement_t {
        statement_t        statement;
        symbol_t          *symbol;
@@ -240,6 +260,27 @@ struct expression_statement_t {
        expression_t *expression;
 };
 
+struct while_statement_t {
+       statement_t   statement;
+       expression_t *condition;
+       statement_t  *body;
+};
+
+struct do_while_statement_t {
+       statement_t   statement;
+       expression_t *condition;
+       statement_t  *body;
+};
+
+struct for_statement_t {
+       statement_t   statement;
+       expression_t  *initialisation;
+       expression_t  *condition;
+       expression_t  *step;
+       statement_t   *body;
+       context_t      context;
+};
+
 struct translation_unit_t {
        context_t context;
 };
diff --git a/lexer.c b/lexer.c
index 7732c9d..f23cb11 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -27,7 +27,7 @@ static strset_t    stringset;
 static
 void error_prefix_at(const char *input_name, unsigned linenr)
 {
-       fprintf(stderr, "%s:%d: Error: ", input_name, linenr);
+       fprintf(stderr, "%s:%u: Error: ", input_name, linenr);
 }
 
 static
@@ -272,7 +272,7 @@ void parse_number_hex(void)
        }
 
        int value = 0;
-       for(;;) {
+       while(1) {
                if (isdigit(c)) {
                        value = 16 * value + c - '0';
                } else if ('A' <= c && c <= 'F') {
@@ -295,7 +295,7 @@ void parse_number_oct(void)
        next_char();
 
        int value = 0;
-       for(;;) {
+       while(1) {
                if ('0' <= c && c <= '7') {
                        value = 8 * value + c - '0';
                } else {
@@ -346,10 +346,61 @@ void parse_number(void)
        } else {
                parse_number_dec(0);
        }
+       if(c == 'U' || c == 'U') {
+               /* TODO do something with the suffixes... */
+               next_char();
+               if(c == 'L' || c == 'l') {
+                       next_char();
+                       if(c == 'L' || c == 'l') {
+                               next_char();
+                       }
+               }
+       } else if(c == 'l' || c == 'L') {
+               next_char();
+               if(c == 'l' || c == 'L') {
+                       next_char();
+                       if(c == 'u' || c == 'U') {
+                               next_char();
+                       }
+               } else if(c == 'u' || c == 'U') {
+                       next_char();
+               }
+       }
 }
 
-static
-int parse_escape_sequence(void)
+static int parse_octal_sequence(void)
+{
+       int value = 0;
+       while(1) {
+               if(c < '0' || c > '7')
+                       break;
+               value = 8 * value + c - '0';
+               next_char();
+       }
+
+       return value;
+}
+
+static int parse_hex_sequence(void)
+{
+       int value = 0;
+       while(1) {
+               if (c >= '0' && c <= '9') {
+                       value = 16 * value + c - '0';
+               } else if ('A' <= c && c <= 'F') {
+                       value = 16 * value + c - 'A' + 10;
+               } else if ('a' <= c && c <= 'f') {
+                       value = 16 * value + c - 'a' + 10;
+               } else {
+                       break;
+               }
+               next_char();
+       }
+
+       return value;
+}
+
+static int parse_escape_sequence(void)
 {
        while(1) {
                int ec = c;
@@ -368,9 +419,8 @@ int parse_escape_sequence(void)
                case 'r': return '\r';
                case 't': return '\t';
                case 'v': return '\v';
-               case 'x': /* TODO parse hex number ... */
-                       parse_error("hex escape sequences not implemented yet");
-                       return EOF;
+               case 'x':
+                       return parse_hex_sequence();
                case '0':
                case '1':
                case '2':
@@ -379,9 +429,7 @@ int parse_escape_sequence(void)
                case '5':
                case '6':
                case '7':
-                       /* TODO parse octal number ... */
-                       parse_error("octal escape sequences not implemented yet");
-                       return EOF;
+                       return parse_octal_sequence();
                case '?':
                        if(c != '?') {
                                return '?';
@@ -506,6 +554,7 @@ void parse_character_constant(void)
        while(1) {
                switch(c) {
                SKIP_TRIGRAPHS(,
+                       next_char();
                        found_char = '?';
                        break;
                )
@@ -513,7 +562,7 @@ void parse_character_constant(void)
                case '\\':
                        next_char();
                        EAT_NEWLINE(break;)
-                       found_char = '\\';
+                       found_char = parse_escape_sequence();
                        break;
 
                MATCH_NEWLINE(
@@ -870,6 +919,7 @@ void lexer_next_preprocessing_token(void)
                        ELSE('+')
                case '-':
                        MAYBE_PROLOG
+                       MAYBE('>', T_MINUSGREATER)
                        MAYBE('-', T_MINUSMINUS)
                        MAYBE('=', T_MINUSEQUAL)
                        ELSE('-')
@@ -912,6 +962,7 @@ void lexer_next_preprocessing_token(void)
                        MAYBE_PROLOG
                        MAYBE(':', T_LESSCOLON)
                        MAYBE('%', T_LESSPERCENT)
+                       MAYBE('=', T_LESSEQUAL)
                                case '<':
                                        MAYBE_PROLOG
                                        MAYBE('=', T_LESSLESSEQUAL)
@@ -919,6 +970,7 @@ void lexer_next_preprocessing_token(void)
                        ELSE('<')
                case '>':
                        MAYBE_PROLOG
+                       MAYBE('=', T_GREATEREQUAL)
                                case '>':
                                        MAYBE_PROLOG
                                        MAYBE('=', T_GREATERGREATEREQUAL)
diff --git a/lexer.h b/lexer.h
index 3a3ea1f..34d965d 100644 (file)
--- a/lexer.h
+++ b/lexer.h
@@ -4,7 +4,7 @@
 #include "symbol_table_t.h"
 #include "token_t.h"
 
-token_t lexer_token;
+extern token_t lexer_token;
 
 void lexer_next_token(void);
 
index 31d692b..c99734f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -272,13 +272,13 @@ declaration_t *environment_push(declaration_t *declaration, const void *context)
                                parser_print_error_prefix_pos(declaration->source_position);
                                fprintf(stderr, "definition of symbol '%s' with type ",
                                        declaration->symbol->string);
-                               print_type(declaration->type, NULL);
+                               print_type(declaration->type);
                                fputc('\n', stderr);
                                parser_print_error_prefix_pos(
                                                previous_declaration->source_position);
                                fprintf(stderr, "is incompatible with previous declaration "
                                        "of type ");
-                               print_type(previous_declaration->type, NULL);
+                               print_type(previous_declaration->type);
                                fputc('\n', stderr);
                        }
                        return previous_declaration;
@@ -328,14 +328,14 @@ void environment_pop_to(size_t new_top)
 
 static expression_t *parse_constant_expression(void)
 {
-       /* TODO: not correct yet */
-       return parse_expression();
+       /* start parsing at precedence 7 (conditional expression) */
+       return parse_sub_expression(7);
 }
 
 static expression_t *parse_assignment_expression(void)
 {
-       /* TODO: not correct yet */
-       return parse_expression();
+       /* start parsing at precedence 2 (assignment expression) */
+       return parse_sub_expression(2);
 }
 
 static void parse_compound_type_entries(void);
@@ -386,10 +386,10 @@ static type_t *parse_compound_type_specifier(int is_struct)
                }
        } else if(token.type != '{') {
                if(is_struct) {
-                       parse_error_expected("problem while parsing struct type specifiers",
+                       parse_error_expected("problem while parsing struct type specifier",
                                             T_IDENTIFIER, '{', 0);
                } else {
-                       parse_error_expected("problem while parsing union type specifiers",
+                       parse_error_expected("problem while parsing union type specifier",
                                             T_IDENTIFIER, '{', 0);
                }
 
@@ -431,73 +431,103 @@ static type_t *parse_compound_type_specifier(int is_struct)
        return (type_t*) compound_type;
 }
 
-static enum_entry_t *parse_enum_type_entries(void)
+static void parse_enum_entries(void)
 {
        eat('{');
 
        if(token.type == '}') {
                next_token();
                parse_error("empty enum not allowed");
-               return NULL;
+               return;
        }
 
-       enum_entry_t *result     = NULL;
-       enum_entry_t *last_entry = NULL;
        do {
-               enum_entry_t *entry = allocate_ast_zero(sizeof(entry[0]));
+               declaration_t *entry = allocate_ast_zero(sizeof(entry[0]));
+
                if(token.type != T_IDENTIFIER) {
                        parse_error_expected("problem while parsing enum entry",
                                             T_IDENTIFIER, 0);
                        eat_block();
-                       return result;
+                       return;
                }
-               entry->symbol = token.v.symbol;
+               entry->storage_class   = STORAGE_CLASS_ENUM_ENTRY;
+               entry->symbol          = token.v.symbol;
+               entry->source_position = token.source_position;
                next_token();
 
                if(token.type == '=') {
                        next_token();
-                       entry->value = parse_constant_expression();
+                       entry->initializer = parse_constant_expression();
                }
 
-               if(last_entry != NULL) {
-                       last_entry->next = entry;
-               } else {
-                       result = entry;
-               }
-               last_entry = entry;
+               record_declaration(entry);
 
                if(token.type != ',')
                        break;
                next_token();
        } while(token.type != '}');
 
-       expect('}');
-       return result;
+       expect_void('}');
+}
+
+static enum_type_t *find_enum_type(enum_type_t *types, const symbol_t *symbol)
+{
+       enum_type_t *type = types;
+       for( ; type != NULL; type = type->next) {
+               if(type->symbol == symbol)
+                       return type;
+       }
+
+       return NULL;
 }
 
 static type_t *parse_enum_specifier(void)
 {
        eat(T_enum);
 
-       enum_type_t *enum_type     = allocate_type_zero(sizeof(enum_type[0]));
-       enum_type->type.type       = TYPE_ENUM;
-       enum_type->source_position = token.source_position;
-
-       /* TODO: rewrite to the same style as struct/union above to handle
-        * type identities correctly
-        */
+       symbol_t    *symbol    = NULL;
+       enum_type_t *enum_type = NULL;
 
        if(token.type == T_IDENTIFIER) {
-               enum_type->symbol = token.v.symbol;
+               symbol = token.v.symbol;
                next_token();
-               if(token.type == '{') {
-                       enum_type->entries = parse_enum_type_entries();
+
+               if(context != NULL) {
+                       enum_type = find_enum_type(context->enums, symbol);
                }
-       } else if(token.type == '{') {
-               enum_type->entries = parse_enum_type_entries();
-       } else {
-               parse_error_expected("problem while parsing enum type specifiers",
-                                    T_IDENTIFIER, '{');
+       } else if(token.type != '{') {
+               parse_error_expected("problem while parsing enum type specifier",
+                                    T_IDENTIFIER, '{', 0);
+               return NULL;
+       }
+
+       if(enum_type == NULL) {
+               enum_type                  = allocate_type_zero(sizeof(enum_type[0]));
+               enum_type->type.type       = TYPE_ENUM;
+               enum_type->source_position = token.source_position;
+               enum_type->symbol          = symbol;
+       }
+
+       if(token.type == '{') {
+               if(enum_type->defined) {
+                       parser_print_error_prefix();
+                       fprintf(stderr, "multiple definitions of enum %s\n",
+                               symbol->string);
+                       enum_type->entries_begin = NULL;
+                       enum_type->entries_end   = NULL;
+               }
+               enum_type->defined = 1;
+
+               declaration_t *before = last_declaration;
+
+               parse_enum_entries();
+
+               if(before == NULL) {
+                       enum_type->entries_begin = context->declarations;
+               } else {
+                       enum_type->entries_begin = before->next;
+               }
+               enum_type->entries_end = last_declaration;
        }
 
        return (type_t*) enum_type;
@@ -600,8 +630,7 @@ typedef enum {
        case T_const:           \
        case T_restrict:        \
        case T_volatile:        \
-       case T_inline:          \
-       case T___extension__:
+       case T_inline:
 
 #ifdef PROVIDE_COMPLEX
 #define COMPLEX_SPECIFIERS  \
@@ -1043,6 +1072,7 @@ declaration_t *parse_parameters(method_type_t *type)
                        return declarations;
 
                case T_IDENTIFIER:
+               case T___extension__:
                DECLARATION_START
                        declaration = parse_parameter();
 
@@ -1278,7 +1308,7 @@ void parse_init_declarators(const declaration_specifiers_t *specifiers)
                        if(declaration->type->type != TYPE_METHOD) {
                                parser_print_error_prefix();
                                fprintf(stderr, "Declarator ");
-                               print_type(declaration->type, declaration->symbol);
+                               print_type_ext(declaration->type, declaration->symbol, NULL);
                                fprintf(stderr, " is not a method type.\n");
                        }
 
@@ -1488,6 +1518,19 @@ expression_t *parse_cast(void)
        return (expression_t*) cast;
 }
 
+static
+expression_t *parse_statement_expression(void)
+{
+       statement_expression_t *expression
+               = allocate_ast_zero(sizeof(expression[0]));
+       expression->expression.type = EXPR_STATEMENT;
+       expression->statement       = parse_compound_statement();
+
+       expect(')');
+
+       return (expression_t*) expression;
+}
+
 static
 expression_t *parse_brace_expression(void)
 {
@@ -1495,13 +1538,17 @@ expression_t *parse_brace_expression(void)
 
        declaration_t *declaration;
        switch(token.type) {
+       case '{':
+               /* gcc extension: a stement expression */
+               return parse_statement_expression();
+
        TYPE_QUALIFIERS
        TYPE_SPECIFIERS
                return parse_cast();
        case T_IDENTIFIER:
                declaration = token.v.symbol->declaration;
                if(declaration != NULL &&
-                               (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
+                               (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
                        return parse_cast();
                }
        }
@@ -1512,6 +1559,32 @@ expression_t *parse_brace_expression(void)
        return result;
 }
 
+static
+expression_t *parse_function_keyword(void)
+{
+       eat(T___FUNCTION__);
+       /* TODO */
+
+       string_literal_t *expression = allocate_ast_zero(sizeof(expression[0]));
+       expression->expression.type  = EXPR_FUNCTION;
+       expression->value            = "TODO: FUNCTION";
+
+       return (expression_t*) expression;
+}
+
+static
+expression_t *parse_pretty_function_keyword(void)
+{
+       eat(T___PRETTY_FUNCTION__);
+       /* TODO */
+
+       string_literal_t *expression = allocate_ast_zero(sizeof(expression[0]));
+       expression->expression.type  = EXPR_PRETTY_FUNCTION;
+       expression->value            = "TODO: PRETTY FUNCTION";
+
+       return (expression_t*) expression;
+}
+
 static
 expression_t *parse_primary_expression(void)
 {
@@ -1522,6 +1595,10 @@ expression_t *parse_primary_expression(void)
                return parse_string_const();
        case T_IDENTIFIER:
                return parse_reference();
+       case T___FUNCTION__:
+               return parse_function_keyword();
+       case T___PRETTY_FUNCTION__:
+               return parse_pretty_function_keyword();
        case '(':
                return parse_brace_expression();
        }
@@ -1567,7 +1644,7 @@ type_t *get_expression_type(const expression_t *expression)
 }
 
 static
-int is_type_specifier(const token_t *token)
+int is_declaration_specifier(const token_t *token, int only_type_specifiers)
 {
        declaration_t *declaration;
 
@@ -1581,6 +1658,12 @@ int is_type_specifier(const token_t *token)
                        if(declaration->storage_class != STORAGE_CLASS_TYPEDEF)
                                return 0;
                        return 1;
+               STORAGE_CLASSES
+               TYPE_QUALIFIERS
+                       if(only_type_specifiers)
+                               return 0;
+                       return 1;
+
                default:
                        return 0;
        }
@@ -1595,13 +1678,14 @@ expression_t *parse_sizeof(unsigned precedence)
                = allocate_ast_zero(sizeof(sizeof_expression[0]));
        sizeof_expression->expression.type = EXPR_SIZEOF;
 
-       if(token.type == '(' && is_type_specifier(look_ahead(1))) {
+       if(token.type == '(' && is_declaration_specifier(look_ahead(1), 1)) {
                next_token();
                sizeof_expression->type = parse_typename();
                expect(')');
        } else {
-               expression_t *expression = parse_sub_expression(precedence);
-               sizeof_expression->type  = get_expression_type(expression);
+               expression_t *expression           = parse_sub_expression(precedence);
+               sizeof_expression->type            = get_expression_type(expression);
+               sizeof_expression->size_expression = expression;
        }
 
        return (expression_t*) sizeof_expression;
@@ -1613,7 +1697,7 @@ expression_t *parse_select_expression(unsigned precedence,
 {
        (void) precedence;
 
-       assert(token.type == '.' || token.type == T_SELECT);
+       assert(token.type == '.' || token.type == T_MINUSGREATER);
        next_token();
 
        select_expression_t *select = allocate_ast_zero(sizeof(select[0]));
@@ -1651,7 +1735,9 @@ expression_t *parse_call_expression(unsigned precedence,
                while(1) {
                        call_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
 
-                       argument->expression = parse_expression();
+                       /* we start parsing at precedence 2 so we don't get comma operators
+                        * parsed */
+                       argument->expression = parse_sub_expression(2);
                        if(last_argument == NULL) {
                                call->arguments = argument;
                        } else {
@@ -1686,6 +1772,15 @@ expression_t *parse_conditional_expression(unsigned precedence,
        return (expression_t*) conditional;
 }
 
+static expression_t *parse_extension(unsigned precedence)
+{
+       eat(T___extension__);
+
+       /* TODO enable extensions */
+
+       return parse_sub_expression(precedence);
+}
+
 #define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type)     \
 static                                                                    \
 expression_t *parse_##unexpression_type(unsigned precedence)              \
@@ -1741,14 +1836,15 @@ expression_t *parse_##binexpression_type(unsigned 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.type = EXPR_BINARY;                      \
+       binexpr->type            = binexpression_type;               \
+       binexpr->left            = left;                             \
+       binexpr->right           = right;                            \
                                                                  \
        return (expression_t*) binexpr;                              \
 }
 
+CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA)
 CREATE_BINEXPR_PARSER('*', BINEXPR_MUL)
 CREATE_BINEXPR_PARSER('/', BINEXPR_DIV)
 CREATE_BINEXPR_PARSER('+', BINEXPR_ADD)
@@ -1767,6 +1863,16 @@ CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND)
 CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR)
 CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT)
 CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT)
+CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN)
+CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN)
+CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, BINEXPR_MUL_ASSIGN)
+CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_DIV_ASSIGN)
+CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, BINEXPR_MOD_ASSIGN)
+CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, BINEXPR_SHIFTLEFT_ASSIGN)
+CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, BINEXPR_SHIFTRIGHT_ASSIGN)
+CREATE_BINEXPR_PARSER(T_ANDEQUAL, BINEXPR_BITWISE_AND_ASSIGN)
+CREATE_BINEXPR_PARSER(T_PIPEEQUAL, BINEXPR_BITWISE_OR_ASSIGN)
+CREATE_BINEXPR_PARSER(T_CARETEQUAL, BINEXPR_BITWISE_XOR_ASSIGN)
 
 static
 expression_t *parse_sub_expression(unsigned precedence)
@@ -1857,28 +1963,48 @@ void init_expression_parsers(void)
                                   T_LESSLESS, 16);
        register_expression_infix_parser(parse_BINEXPR_SHIFTRIGHT,
                                   T_GREATERGREATER, 16);
-       register_expression_infix_parser(parse_BINEXPR_ADD,       '+', 15);
-       register_expression_infix_parser(parse_BINEXPR_SUB,       '-', 15);
-       register_expression_infix_parser(parse_BINEXPR_LESS,      '<', 14);
-       register_expression_infix_parser(parse_BINEXPR_GREATER,   '>', 14);
-       register_expression_infix_parser(parse_BINEXPR_LESSEQUAL, T_LESSEQUAL, 14);
+       register_expression_infix_parser(parse_BINEXPR_ADD,         '+',        15);
+       register_expression_infix_parser(parse_BINEXPR_SUB,         '-',        15);
+       register_expression_infix_parser(parse_BINEXPR_LESS,        '<',        14);
+       register_expression_infix_parser(parse_BINEXPR_GREATER,     '>',        14);
+       register_expression_infix_parser(parse_BINEXPR_LESSEQUAL, T_LESSEQUAL,  14);
        register_expression_infix_parser(parse_BINEXPR_GREATEREQUAL,
-                                  T_GREATEREQUAL, 14);
+                                                               T_GREATEREQUAL, 14);
        register_expression_infix_parser(parse_BINEXPR_EQUAL,     T_EQUALEQUAL, 13);
        register_expression_infix_parser(parse_BINEXPR_NOTEQUAL,
-                                        T_EXCLAMATIONMARKEQUAL, 13);
+                                                       T_EXCLAMATIONMARKEQUAL, 13);
        register_expression_infix_parser(parse_BINEXPR_BITWISE_AND, '&',        12);
        register_expression_infix_parser(parse_BINEXPR_BITWISE_XOR, '^',        11);
        register_expression_infix_parser(parse_BINEXPR_BITWISE_OR,  '|',        10);
        register_expression_infix_parser(parse_BINEXPR_LOGICAL_AND, T_ANDAND,    9);
        register_expression_infix_parser(parse_BINEXPR_LOGICAL_OR,  T_PIPEPIPE,  8);
        register_expression_infix_parser(parse_conditional_expression, '?',      7);
-       register_expression_infix_parser(parse_BINEXPR_ASSIGN,      T_EQUAL,     2);
+       register_expression_infix_parser(parse_BINEXPR_ASSIGN,      '=',         2);
+       register_expression_infix_parser(parse_BINEXPR_ADD_ASSIGN, T_PLUSEQUAL,  2);
+       register_expression_infix_parser(parse_BINEXPR_SUB_ASSIGN, T_MINUSEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_MUL_ASSIGN,
+                                                               T_ASTERISKEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_DIV_ASSIGN, T_SLASHEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_MOD_ASSIGN,
+                                                                T_PERCENTEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_SHIFTLEFT_ASSIGN,
+                                                               T_LESSLESSEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_SHIFTRIGHT_ASSIGN,
+                                                         T_GREATERGREATEREQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_BITWISE_AND_ASSIGN,
+                                                                    T_ANDEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_BITWISE_OR_ASSIGN,
+                                                                   T_PIPEEQUAL, 2);
+       register_expression_infix_parser(parse_BINEXPR_BITWISE_XOR_ASSIGN,
+                                                                  T_CARETEQUAL, 2);
+
+       register_expression_infix_parser(parse_BINEXPR_COMMA,       ',',         1);
 
        register_expression_infix_parser(parse_array_expression,        '[',    30);
        register_expression_infix_parser(parse_call_expression,         '(',    30);
        register_expression_infix_parser(parse_select_expression,       '.',    30);
-       register_expression_infix_parser(parse_select_expression,  T_SELECT,    30);
+       register_expression_infix_parser(parse_select_expression,
+                                                               T_MINUSGREATER, 30);
        register_expression_infix_parser(parse_UNEXPR_POSTFIX_INCREMENT,
                                         T_PLUSPLUS, 30);
        register_expression_infix_parser(parse_UNEXPR_POSTFIX_DECREMENT,
@@ -1893,6 +2019,7 @@ void init_expression_parsers(void)
        register_expression_parser(parse_UNEXPR_PREFIX_INCREMENT, T_PLUSPLUS,   25);
        register_expression_parser(parse_UNEXPR_PREFIX_DECREMENT, T_MINUSMINUS, 25);
        register_expression_parser(parse_sizeof,                  T_sizeof,     25);
+       register_expression_parser(parse_extension,            T___extension__, 25);
 }
 
 
@@ -1900,21 +2027,31 @@ static
 statement_t *parse_case_statement(void)
 {
        eat(T_case);
-       parse_expression();
+       case_label_statement_t *label = allocate_ast_zero(sizeof(label[0]));
+       label->statement.type            = STATEMENT_CASE_LABEL;
+       label->statement.source_position = token.source_position;
+
+       label->expression = parse_expression();
+
        expect(':');
-       parse_statement();
+       label->statement.next = parse_statement();
 
-       return NULL;
+       return (statement_t*) label;
 }
 
 static
 statement_t *parse_default_statement(void)
 {
        eat(T_default);
+
+       case_label_statement_t *label = allocate_ast_zero(sizeof(label[0]));
+       label->statement.type            = STATEMENT_CASE_LABEL;
+       label->statement.source_position = token.source_position;
+
        expect(':');
-       parse_statement();
+       label->statement.next = parse_statement();
 
-       return NULL;
+       return (statement_t*) label;
 }
 
 static
@@ -1933,7 +2070,8 @@ statement_t *parse_if(void)
        eat(T_if);
 
        if_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.type = STATEMENT_IF;
+       statement->statement.type            = STATEMENT_IF;
+       statement->statement.source_position = token.source_position;
 
        expect('(');
        statement->condition = parse_expression();
@@ -1952,60 +2090,96 @@ static
 statement_t *parse_switch(void)
 {
        eat(T_switch);
+
+       switch_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+       statement->statement.type            = STATEMENT_SWITCH;
+       statement->statement.source_position = token.source_position;
+
        expect('(');
-       parse_expression();
+       statement->expression = parse_expression();
        expect(')');
-       parse_statement();
+       statement->body = parse_statement();
 
-       return NULL;
+       return (statement_t*) statement;
 }
 
 static
 statement_t *parse_while(void)
 {
        eat(T_while);
+
+       while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+       statement->statement.type            = STATEMENT_WHILE;
+       statement->statement.source_position = token.source_position;
+
        expect('(');
-       parse_expression();
+       statement->condition = parse_expression();
        expect(')');
-       parse_statement();
+       statement->body = parse_statement();
 
-       return NULL;
+       return (statement_t*) statement;
 }
 
 static
 statement_t *parse_do(void)
 {
        eat(T_do);
-       parse_statement();
+
+       do_while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+       statement->statement.type            = STATEMENT_DO_WHILE;
+       statement->statement.source_position = token.source_position;
+
+       statement->body = parse_statement();
        expect(T_while);
        expect('(');
-       parse_expression();
+       statement->condition = parse_expression();
        expect(')');
+       expect(';');
 
-       return NULL;
+       return (statement_t*) statement;
 }
 
 static
 statement_t *parse_for(void)
 {
        eat(T_for);
+
+       for_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+       statement->statement.type            = STATEMENT_FOR;
+       statement->statement.source_position = token.source_position;
+
        expect('(');
+
+       int         top          = environment_top();
+       context_t  *last_context = context;
+       set_context(&statement->context);
+
        if(token.type != ';') {
-               /* TODO not correct... this could also be a declaration */
-               parse_expression();
+               if(is_declaration_specifier(&token, 0)) {
+                       parse_declaration();
+               } else {
+                       statement->initialisation = parse_expression();
+                       expect(';');
+               }
+       } else {
+               expect(';');
        }
-       expect(';');
+
        if(token.type != ';') {
-               parse_expression();
+               statement->condition = parse_expression();
        }
        expect(';');
        if(token.type != ')') {
-               parse_expression();
+               statement->step = parse_expression();
        }
        expect(')');
-       parse_statement();
+       statement->body = parse_statement();
 
-       return NULL;
+       assert(context == &statement->context);
+       set_context(last_context);
+       environment_pop_to(top);
+
+       return (statement_t*) statement;
 }
 
 static
@@ -2037,7 +2211,11 @@ statement_t *parse_break(void)
        eat(T_break);
        expect(';');
 
-       return NULL;
+       statement_t *statement     = allocate_ast_zero(sizeof(statement[0]));
+       statement->source_position = token.source_position;
+       statement->type            = STATEMENT_BREAK;
+
+       return statement;
 }
 
 static
@@ -2046,7 +2224,9 @@ statement_t *parse_return(void)
        eat(T_return);
 
        return_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.type = STATEMENT_RETURN;
+
+       statement->statement.type            = STATEMENT_RETURN;
+       statement->statement.source_position = token.source_position;
        if(token.type != ';') {
                statement->return_value = parse_expression();
        }
@@ -2058,15 +2238,45 @@ statement_t *parse_return(void)
 static
 statement_t *parse_declaration_statement(void)
 {
-       parse_declaration();
-       return NULL;
+       declaration_t *before = last_declaration;
+
+       declaration_statement_t *statement
+               = allocate_ast_zero(sizeof(statement[0]));
+       statement->statement.type            = STATEMENT_DECLARATION;
+       statement->statement.source_position = token.source_position;
+
+       declaration_specifiers_t specifiers;
+       memset(&specifiers, 0, sizeof(specifiers));
+       parse_declaration_specifiers(&specifiers);
+
+       if(token.type == ';') {
+               eat(';');
+       } else {
+               parse_init_declarators(&specifiers);
+       }
+
+       if(before == NULL) {
+               statement->declarations_begin = context->declarations;
+       } else {
+               statement->declarations_begin = before->next;
+       }
+       statement->declarations_end = last_declaration;
+
+       return (statement_t*) statement;
 }
 
 static
 statement_t *parse_expression_statement(void)
 {
-       parse_expression();
-       return NULL;
+       expression_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+       statement->statement.type            = STATEMENT_EXPRESSION;
+       statement->statement.source_position = token.source_position;
+
+       statement->expression = parse_expression();
+
+       expect(';');
+
+       return (statement_t*) statement;
 }
 
 static
@@ -2146,6 +2356,15 @@ statement_t *parse_statement(void)
                statement = parse_expression_statement();
                break;
 
+       case T___extension__:
+               /* this can be a prefix to a declaration or an expression statement */
+               /* we simply eat it now and parse the rest with tail recursion */
+               do {
+                       next_token();
+               } while(token.type == T___extension__);
+               statement = parse_statement();
+               break;
+
        DECLARATION_START
                statement = parse_declaration_statement();
                break;
@@ -2155,6 +2374,8 @@ statement_t *parse_statement(void)
                break;
        }
 
+       assert(statement == NULL || statement->source_position.input_name != NULL);
+
        return statement;
 }
 
@@ -2165,7 +2386,8 @@ statement_t *parse_compound_statement(void)
 
        compound_statement_t *compound_statement
                = allocate_ast_zero(sizeof(compound_statement[0]));
-       compound_statement->statement.type = STATEMENT_COMPOUND;
+       compound_statement->statement.type            = STATEMENT_COMPOUND;
+       compound_statement->statement.source_position = token.source_position;
 
        int        top          = environment_top();
        context_t *last_context = context;
@@ -2175,12 +2397,18 @@ statement_t *parse_compound_statement(void)
 
        while(token.type != '}' && token.type != T_EOF) {
                statement_t *statement = parse_statement();
+               if(statement == NULL)
+                       continue;
 
                if(last_statement != NULL) {
                        last_statement->next = statement;
                } else {
                        compound_statement->statements = statement;
                }
+
+               while(statement->next != NULL)
+                       statement = statement->next;
+
                last_statement = statement;
        }
 
index ff8b237..2f98005 100644 (file)
@@ -44,6 +44,11 @@ S(_Imaginary)
 S(__extension__)
 S(__attribute__)
 S(__builtin_va_list)
+S(__PRETTY_FUNCTION__)
+S(__FUNCTION__)
+S(__alignof__)
+S(__real__)
+S(__imag__)
 #undef S
 
 T(const,               "__const",)
@@ -55,7 +60,7 @@ T(__asm__,             "__asm__", = T_asm)
 T(inline,               "inline",)
 T(__inline,           "__inline", = T_inline)
 
-T(SELECT,                   "->",)
+T(MINUSGREATER,             "->",)
 T(PLUSPLUS,                 "++",)
 T(MINUSMINUS,               "--",)
 T(LESSLESS,                 "<<",)
diff --git a/type.c b/type.c
index 36ca1c5..b964e2a 100644 (file)
--- a/type.c
+++ b/type.c
@@ -1,11 +1,13 @@
 #include <config.h>
 
+#include <stdio.h>
+#include <assert.h>
 #include "type_t.h"
 #include "adt/error.h"
 
-static struct obstack  _type_obst;
-struct obstack        *type_obst = &_type_obst;
-static FILE           *out;
+static struct obstack   _type_obst;
+struct obstack         *type_obst = &_type_obst;
+static FILE            *out;
 
 static void intern_print_type_pre(const type_t *type);
 static void intern_print_type_post(const type_t *type);
@@ -35,7 +37,7 @@ void print_type_qualifiers(unsigned qualifiers)
                fputs("volatile ", out);
        }
        if(qualifiers & TYPE_QUALIFIER_RESTRICT) {
-               fputs("restrict ", out);
+               fputs("__restrict ", out);
        }
        if(qualifiers & TYPE_QUALIFIER_INLINE) {
                fputs("inline ", out);
@@ -81,7 +83,7 @@ void print_method_type_pre(const method_type_t *type)
 }
 
 static
-void print_method_type_post(const method_type_t *type)
+void print_method_type_post(const method_type_t *type, const context_t *context)
 {
        /* TODO: don't emit braces if we're the toplevel type... */
        intern_print_type_post(type->result_type);
@@ -89,15 +91,28 @@ void print_method_type_post(const method_type_t *type)
 
        fputc('(', out);
 
-       method_parameter_t *parameter = type->parameters;
        int                 first     = 1;
-       for( ; parameter != NULL; parameter = parameter->next) {
-               if(first) {
-                       first = 0;
-               } else {
-                       fputs(", ", out);
+       if(context == NULL) {
+               method_parameter_t *parameter = type->parameters;
+               for( ; parameter != NULL; parameter = parameter->next) {
+                       if(first) {
+                               first = 0;
+                       } else {
+                               fputs(", ", out);
+                       }
+                       print_type(parameter->type);
+               }
+       } else {
+               declaration_t *parameter = context->declarations;
+               for( ; parameter != NULL; parameter = parameter->next) {
+                       if(first) {
+                               first = 0;
+                       } else {
+                               fputs(", ", out);
+                       }
+                       print_type_ext(parameter->type, parameter->symbol,
+                                      &parameter->context);
                }
-               print_type(parameter->type, NULL);
        }
        if(type->variadic) {
                if(first) {
@@ -136,12 +151,12 @@ void print_type_enum(const enum_type_t *type)
        } else {
                fprintf(out, "enum {\n");
 
-               enum_entry_t *entry = type->entries;
-               for( ; entry != NULL; entry = entry->next) {
+               declaration_t *entry = type->entries_begin;
+               for( ; entry != type->entries_end->next; entry = entry->next) {
                        fprintf(out, "\t%s", entry->symbol->string);
-                       if(entry->value != NULL) {
+                       if(entry->initializer != NULL) {
                                fprintf(out, " = ");
-                               print_expression(entry->value);
+                               print_expression(entry->initializer);
                        }
                        fprintf(out, ",\n");
                }
@@ -188,7 +203,7 @@ void intern_print_type_post(const type_t *type)
 {
        switch(type->type) {
        case TYPE_METHOD:
-               print_method_type_post((const method_type_t*) type);
+               print_method_type_post((const method_type_t*) type, NULL);
                return;
        case TYPE_POINTER:
                print_pointer_type_post((const pointer_type_t*) type);
@@ -203,7 +218,13 @@ void intern_print_type_post(const type_t *type)
        }
 }
 
-void print_type(const type_t *type, const symbol_t *symbol)
+void print_type(const type_t *type)
+{
+       print_type_ext(type, NULL, NULL);
+}
+
+void print_type_ext(const type_t *type, const symbol_t *symbol,
+                    const context_t *context)
 {
        if(type == NULL) {
                fputs("nil type", out);
@@ -215,7 +236,11 @@ void print_type(const type_t *type, const symbol_t *symbol)
                fputc(' ', out);
                fputs(symbol->string, out);
        }
-       intern_print_type_post(type);
+       if(type->type == TYPE_METHOD) {
+               print_method_type_post((const method_type_t*) type, context);
+       } else {
+               intern_print_type_post(type);
+       }
 }
 
 int type_valid(const type_t *type)
@@ -252,7 +277,7 @@ void dbg_type(const type_t *type)
 {
        FILE *old_out = out;
        out = stderr;
-       print_type(type, NULL);
+       print_type(type);
        puts("\n");
        fflush(stderr);
        out = old_out;
diff --git a/type.h b/type.h
index b3700a8..a3669a7 100644 (file)
--- a/type.h
+++ b/type.h
@@ -10,18 +10,20 @@ typedef struct pointer_type_t           pointer_type_t;
 typedef struct method_parameter_t       method_parameter_t;
 typedef struct method_type_t            method_type_t;
 typedef struct compound_type_t          compound_type_t;
-typedef struct enum_entry_t             enum_entry_t;
 typedef struct enum_type_t              enum_type_t;
 typedef struct builtin_type_t           builtin_type_t;
 
 void init_types(void);
 void exit_types(void);
 
+void print_type(const type_t *type);
+
 /**
  * prints a human readable form of @p type. prints an abstract typename
  * if symbol is NULL
  */
-void print_type(const type_t *type, const symbol_t *symbol);
+void print_type_ext(const type_t *type, const symbol_t *symbol,
+                    const context_t *context);
 
 /**
  * set output stream for the type printer
index 2526f43..d75a8bd 100644 (file)
 /* TODO: ^= is a bad way of combining hashes since most addresses are very
  * similar */
 
-static
-unsigned hash_ptr(const void *ptr)
+static unsigned hash_ptr(const void *ptr)
 {
        unsigned ptr_int = ((char*) ptr - (char*) NULL);
        return ptr_int >> 3;
 }
 
-static
-unsigned hash_atomic_type(const atomic_type_t *type)
+static unsigned hash_atomic_type(const atomic_type_t *type)
 {
        unsigned some_prime = 27644437;
 
        return type->atype * some_prime;
 }
 
-static
-unsigned hash_pointer_type(const pointer_type_t *type)
+static unsigned hash_pointer_type(const pointer_type_t *type)
 {
        return hash_ptr(type->points_to);
 }
 
-static
-unsigned hash_compound_type(const compound_type_t *type)
+static unsigned hash_compound_type(const compound_type_t *type)
 {
        unsigned result = hash_ptr(type->symbol);
 
        return result;
 }
 
-static
-unsigned hash_type(const type_t *type);
+static unsigned hash_type(const type_t *type);
 
-static
-unsigned hash_method_type(const method_type_t *type)
+static unsigned hash_method_type(const method_type_t *type)
 {
        unsigned result = hash_ptr(type->result_type);
 
@@ -64,18 +58,14 @@ unsigned hash_method_type(const method_type_t *type)
        return result;
 }
 
-static
-unsigned hash_enum_type(const enum_type_t *type)
+static unsigned hash_enum_type(const enum_type_t *type)
 {
        unsigned result = hash_ptr(type->symbol);
 
-       /* TODO */
-
        return result;
 }
 
-static
-unsigned hash_type(const type_t *type)
+static unsigned hash_type(const type_t *type)
 {
        unsigned hash;
 
@@ -110,53 +100,51 @@ unsigned hash_type(const type_t *type)
        return hash;
 }
 
-static
-int atomic_types_equal(const atomic_type_t *type1, const atomic_type_t *type2)
+static int atomic_types_equal(const atomic_type_t *type1,
+                              const atomic_type_t *type2)
 {
        return type1->atype == type2->atype;
 }
 
-static
-int compound_types_equal(const compound_type_t *type1,
-                         const compound_type_t *type2)
+static int compound_types_equal(const compound_type_t *type1,
+                                const compound_type_t *type2)
 {
        if(type1->type.type != type2->type.type)
                return 0;
        if(type1->symbol != type2->symbol)
                return 0;
 
+       /* anonymous types? */
        if(type1->symbol == NULL) {
                /* previous tests should already have checked for this */
                assert(type1 != type2);
                /* anonymous types are only equal if they are the very same type */
                return 0;
-       } else {
-               /* non-anonymous types are equal if they have the same symbol */
-               /* TODO: is this correct */
-               return 1;
        }
 
-#if 0
-       declaration_t *entry1 = type1->context.declarations;
-       declaration_t *entry2 = type2->context.declarations;
+       /* non-anonymous types with same symbol are equal */
+       return 1;
+}
 
-       while(entry1 != NULL && entry2 != NULL) {
-               if(entry1->type != entry2->type)
-                       return 0;
-               if(entry1->symbol != entry2->symbol)
-                       return 0;
-               entry1 = entry1->next;
-               entry2 = entry2->next;
-       }
-       if(entry1 != NULL || entry2 != NULL)
+static int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
+{
+       if(type1->symbol != type2->symbol)
                return 0;
-#endif
 
+       /* anonymous types? */
+       if(type1->symbol == NULL) {
+               /* previous tests should already have checked for this */
+               assert(type1 != type2);
+               /* 2 anonymous enums are never equal */
+               return 0;
+       }
+
+       /* non-anonymous types with same symbol are equal */
        return 1;
 }
 
-static
-int method_types_equal(const method_type_t *type1, const method_type_t *type2)
+static int method_types_equal(const method_type_t *type1,
+                              const method_type_t *type2)
 {
        if(type1->result_type != type2->result_type)
                return 0;
@@ -179,43 +167,19 @@ int method_types_equal(const method_type_t *type1, const method_type_t *type2)
        return 1;
 }
 
-static
-int pointer_types_equal(const pointer_type_t *type1,
-                        const pointer_type_t *type2)
+static int pointer_types_equal(const pointer_type_t *type1,
+                               const pointer_type_t *type2)
 {
        return type1->points_to == type2->points_to;
 }
 
-static
-int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
-{
-       if(type1->symbol != NULL && type1->symbol == type2->symbol)
-               return 1;
-
-       enum_entry_t *entry1 = type1->entries;
-       enum_entry_t *entry2 = type2->entries;
-       while(entry1 != NULL && entry2 != NULL) {
-               if(entry1->symbol != entry2->symbol)
-                       return 0;
-               /* TODO: compare expressions */
-               entry1 = entry1->next;
-               entry2 = entry2->next;
-       }
-       if(entry1 != NULL || entry2 != NULL)
-               return 0;
-
-       return 1;
-}
-
-static
-int builtin_types_equal(const builtin_type_t *type1,
-                        const builtin_type_t *type2)
+static int builtin_types_equal(const builtin_type_t *type1,
+                               const builtin_type_t *type2)
 {
        return type1->symbol == type2->symbol;
 }
 
-static
-int types_equal(const type_t *type1, const type_t *type2)
+static int types_equal(const type_t *type1, const type_t *type2)
 {
        if(type1 == type2)
                return 1;
index 5fc4a3e..09549cd 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -72,18 +72,14 @@ struct builtin_type_t {
        symbol_t *symbol;
 };
 
-struct enum_entry_t {
-       symbol_t     *symbol;
-       expression_t *value;
-       enum_entry_t *next;
-};
-
 struct enum_type_t {
        type_t             type;
        symbol_t          *symbol;
-       enum_entry_t      *entries;
        source_position_t  source_position;
        enum_type_t       *next;
+       declaration_t     *entries_begin;
+       declaration_t     *entries_end;
+       int                defined;
 };
 
 struct pointer_type_t {
index eab440b..651bcff 100644 (file)
@@ -51,7 +51,7 @@ static declaration_t *find_typedef(const type_t *type)
        /* first: search for a matching typedef in the global type... */
        declaration_t *declaration = global_context->declarations;
        while(declaration != NULL) {
-               if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
+               if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
                        declaration = declaration->next;
                        continue;
                }
@@ -230,12 +230,12 @@ static void write_enum(const symbol_t *symbol, const enum_type_t *type)
 {
        fprintf(out, "enum %s:\n", symbol->string);
 
-       const enum_entry_t *entry = type->entries;
-       for ( ; entry != NULL; entry = entry->next) {
+       declaration_t *entry = type->entries_begin;
+       for ( ; entry != type->entries_end->next; entry = entry->next) {
                fprintf(out, "\t%s", entry->symbol->string);
-               if(entry->value != NULL) {
+               if(entry->initializer != NULL) {
                        fprintf(out, " <- ");
-                       write_expression(entry->value);
+                       write_expression(entry->initializer);
                }
                fputc('\n', out);
        }
@@ -315,7 +315,7 @@ void write_fluffy_decls(const translation_unit_t *unit)
        declaration_t *declaration = unit->context.declarations;
        for( ; declaration != NULL; declaration = declaration->next) {
                //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
-               if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
+               if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
                        continue;
                }
                type_t *type = declaration->type;
@@ -331,7 +331,8 @@ void write_fluffy_decls(const translation_unit_t *unit)
        /* write global variables */
        declaration = unit->context.declarations;
        for( ; declaration != NULL; declaration = declaration->next) {
-               if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
+               if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
+                               || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
                        continue;
 
                type_t *type = declaration->type;
@@ -344,7 +345,8 @@ void write_fluffy_decls(const translation_unit_t *unit)
        /* write functions */
        declaration = unit->context.declarations;
        for( ; declaration != NULL; declaration = declaration->next) {
-               if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
+               if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
+                               || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
                        continue;
 
                type_t *type = declaration->type;