support OPEN_BRACKET, CLOSE_BRACKET, OP_INC, OP_DEC, OP_EQ, OP_NE, OP_LE,
authorJürg Billeter <j@bitron.ch>
Wed, 26 Apr 2006 14:58:13 +0000 (14:58 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 26 Apr 2006 14:58:13 +0000 (14:58 +0000)
2006-04-26  Jürg Billeter  <j@bitron.ch>

* valac/scanner.l: support OPEN_BRACKET, CLOSE_BRACKET, OP_INC, OP_DEC,
  OP_EQ, OP_NE, OP_LE, OP_GE, OP_LT, OP_GT, MINUS, STAR, DIV, ELSE, FOR,
  IF
* valac/parser.y: add array type references, equality expressions,
  relational expressions, multiplicative expressions, postfix
  operations, object creation, if conditionals, for loops
* valac/context.h: add ValaNamedArgument struct, support if and for
  statements
* valac/context.c: resolve types in object creation expressions of
  variable initializers
* valac/generator.c: support array type references, init and class_init
  methods, more operations, object creation, for loops, if conditionals,
  call g_type_init in main
* tests/test-006.vala: test instance method invocation, object creation,
  for loop, if conditional, multiplicative expression

svn path=/trunk/; revision=6

vala/ChangeLog
vala/tests/test-006.vala [new file with mode: 0644]
vala/valac/context.c
vala/valac/context.h
vala/valac/generator.c
vala/valac/parser.y
vala/valac/scanner.l

index dd70e70..68c5afc 100644 (file)
@@ -1,3 +1,21 @@
+2006-04-26  Jürg Billeter  <j@bitron.ch>
+
+       * valac/scanner.l: support OPEN_BRACKET, CLOSE_BRACKET, OP_INC, OP_DEC,
+         OP_EQ, OP_NE, OP_LE, OP_GE, OP_LT, OP_GT, MINUS, STAR, DIV, ELSE, FOR,
+         IF
+       * valac/parser.y: add array type references, equality expressions,
+         relational expressions, multiplicative expressions, postfix
+         operations, object creation, if conditionals, for loops
+       * valac/context.h: add ValaNamedArgument struct, support if and for
+         statements
+       * valac/context.c: resolve types in object creation expressions of
+         variable initializers
+       * valac/generator.c: support array type references, init and class_init
+         methods, more operations, object creation, for loops, if conditionals,
+         call g_type_init in main
+       * tests/test-006.vala: test instance method invocation, object creation,
+         for loop, if conditional, multiplicative expression
+
 2006-04-25  Jürg Billeter  <j@bitron.ch>
 
        * valac/parser.y: save cname in class, save location of statements and
diff --git a/vala/tests/test-006.vala b/vala/tests/test-006.vala
new file mode 100644 (file)
index 0000000..0d3aa97
--- /dev/null
@@ -0,0 +1,32 @@
+namespace Maman {
+       class Bar {
+               public int do_action (int i) {
+                       return (i + 42);
+               }
+       }
+       
+       class SubBar : Bar {
+               void init () {
+                       do_action (42);
+               }
+       
+               public static int main (int argc, string[] argv) {
+                       SubBar subbar = new SubBar ();
+               
+                       int i;
+                       int j;
+                       
+                       for (i = 0; i < argc; i++) {
+                               subbar.do_action (i);
+                       }
+                       
+                       if (i == 1) {
+                               j = 42;
+                       } else {
+                               j = argc;
+                       }
+                       
+                       return (i * j);
+               }
+       }
+}
index 983c03f..92bd39f 100644 (file)
@@ -281,11 +281,24 @@ vala_context_resolve_type_reference (ValaContext *context, ValaNamespace *namesp
 }
 
 static void
+vala_context_resolve_types_in_expression (ValaContext *context, ValaNamespace *namespace, ValaExpression *expr)
+{
+       switch (expr->type) {
+       case VALA_EXPRESSION_TYPE_OBJECT_CREATION:
+               vala_context_resolve_type_reference (context, namespace, expr->object_creation.type);
+               break;
+       }
+}
+
+static void
 vala_context_resolve_types_in_statement (ValaContext *context, ValaNamespace *namespace, ValaStatement *stmt)
 {
        switch (stmt->type) {
        case VALA_STATEMENT_TYPE_VARIABLE_DECLARATION:
                vala_context_resolve_type_reference (context, namespace, stmt->variable_declaration->type);
+               if (stmt->variable_declaration->declarator->initializer != NULL) {
+                       vala_context_resolve_types_in_expression (context, namespace, stmt->variable_declaration->declarator->initializer);
+               }
                break;
        }
 }
index f3866c1..8e68ac5 100644 (file)
@@ -42,6 +42,7 @@ typedef struct _ValaVariableDeclarator ValaVariableDeclarator;
 typedef struct _ValaExpression ValaExpression;
 typedef struct _ValaTypeReference ValaTypeReference;
 typedef struct _ValaFormalParameter ValaFormalParameter;
+typedef struct _ValaNamedArgument ValaNamedArgument;
 
 enum _ValaSymbolType {
        VALA_SYMBOL_TYPE_ROOT,
@@ -62,25 +63,38 @@ enum _ValaMethodFlags {
 enum _ValaStatementType {
        VALA_STATEMENT_TYPE_BLOCK,
        VALA_STATEMENT_TYPE_EXPRESSION,
+       VALA_STATEMENT_TYPE_IF,
+       VALA_STATEMENT_TYPE_FOR,
        VALA_STATEMENT_TYPE_RETURN,
        VALA_STATEMENT_TYPE_VARIABLE_DECLARATION,
 };
 
 enum _ValaExpressionType {
-       VALA_EXPRESSION_TYPE_ADDITIVE,
        VALA_EXPRESSION_TYPE_ASSIGNMENT,
        VALA_EXPRESSION_TYPE_EXPRESSION,
        VALA_EXPRESSION_TYPE_INVOCATION,
        VALA_EXPRESSION_TYPE_LITERAL_INTEGER,
        VALA_EXPRESSION_TYPE_LITERAL_STRING,
        VALA_EXPRESSION_TYPE_MEMBER_ACCESS,
+       VALA_EXPRESSION_TYPE_OBJECT_CREATION,
+       VALA_EXPRESSION_TYPE_OPERATION,
        VALA_EXPRESSION_TYPE_PARENTHESIZED,
+       VALA_EXPRESSION_TYPE_POSTFIX,
        VALA_EXPRESSION_TYPE_RETURN,
        VALA_EXPRESSION_TYPE_SIMPLE_NAME,
 };
 
 enum _ValaOpType {
        VALA_OP_TYPE_PLUS,
+       VALA_OP_TYPE_MINUS,
+       VALA_OP_TYPE_MUL,
+       VALA_OP_TYPE_DIV,
+       VALA_OP_TYPE_EQ,
+       VALA_OP_TYPE_NE,
+       VALA_OP_TYPE_LT,
+       VALA_OP_TYPE_GT,
+       VALA_OP_TYPE_LE,
+       VALA_OP_TYPE_GE,
 };
 
 struct _ValaContext {
@@ -132,6 +146,8 @@ struct _ValaClass {
        char *cname;
        char *lower_case_cname;
        char *upper_case_cname;
+       gboolean has_init;
+       gboolean has_class_init;
 };
 
 struct _ValaStruct {
@@ -169,6 +185,17 @@ struct _ValaStatement {
                } block;
                ValaExpression *expr;
                ValaVariableDeclaration *variable_declaration;
+               struct {
+                       ValaExpression *condition;
+                       ValaStatement *true_stmt;
+                       ValaStatement *false_stmt;
+               } if_stmt;
+               struct {
+                       GList *initializer;
+                       ValaExpression *condition;
+                       GList *iterator;
+                       ValaStatement *loop;
+               } for_stmt;
        };
 };
 
@@ -192,9 +219,9 @@ struct _ValaExpression {
                ValaExpression *inner;
                struct {
                        ValaExpression *left;
-                       ValaOpType op;
+                       ValaOpType type;
                        ValaExpression *right;
-               } additive;
+               } op;
                struct {
                        ValaExpression *left;
                        char *right;
@@ -208,6 +235,14 @@ struct _ValaExpression {
                        ValaExpression *left;
                        ValaExpression *right;
                } assignment;
+               struct {
+                       ValaTypeReference *type;
+                       GList *named_argument_list;
+               } object_creation;
+               struct {
+                       ValaExpression *inner;
+                       const char *cop;
+               } postfix;
        };
 };
 
@@ -216,6 +251,7 @@ struct _ValaTypeReference {
        char *type_name;
        ValaLocation *location;
        ValaSymbol *symbol;
+       gboolean array_type;
 };
 
 struct _ValaFormalParameter {
@@ -224,6 +260,13 @@ struct _ValaFormalParameter {
        ValaLocation *location;
 };
 
+struct _ValaNamedArgument {
+       char *name;
+       ValaExpression *expression;
+       ValaLocation *location;
+       ValaSymbol *symbol; /* symbol corresponding to name */
+};
+
 ValaContext *vala_context_new ();
 void vala_context_free (ValaContext *context);
 void vala_context_parse (ValaContext *context);
index aad37a1..0508261 100644 (file)
@@ -56,17 +56,17 @@ filename_to_define (const char *filename)
 }
 
 static char *
-get_cname_for_type_symbol (ValaSymbol *sym, ValaLocation *location)
+get_cname_for_type_reference (ValaTypeReference *type, ValaLocation *location)
 {
-       switch (sym->type) {
+       switch (type->symbol->type) {
        case VALA_SYMBOL_TYPE_CLASS:
-               return g_strdup_printf ("%s *", sym->class->cname);
+               return g_strdup_printf ("%s *%s", type->symbol->class->cname, type->array_type ? "*" : "");
        case VALA_SYMBOL_TYPE_STRUCT:
-               return g_strdup_printf ("%s %s", sym->struct_->cname, (sym->struct_->reference_type ? "*" : ""));
+               return g_strdup_printf ("%s %s%s", type->symbol->struct_->cname, (type->symbol->struct_->reference_type ? "*" : ""), type->array_type ? "*" : "");
        case VALA_SYMBOL_TYPE_VOID:
                return g_strdup ("void");
        default:
-               err (location, "internal error: symbol type %d is not a type symbol", sym->type);
+               err (location, "internal error: unhandled symbol type %d", type->symbol->type);
                return NULL;
        }
 }
@@ -91,15 +91,9 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
        for (l = class->methods; l != NULL; l = l->next) {
                ValaMethod *method = l->data;
                
-               char *method_return_type_cname = get_cname_for_type_symbol (method->return_type->symbol, method->location);
-               if ((method->modifiers & VALA_METHOD_STATIC) && strcmp (method->name, "main") == 0 && strcmp (method->return_type->type_name, "int") == 0) {
-                       if (g_list_length (method->formal_parameters) == 2) {
-                               method->cname = g_strdup ("main");
-                       }
-               }
-               if (method->cname == NULL) {
-                       method->cname = g_strdup_printf ("%s%s_%s", ns_lower, lower_case, method->name);
-               }
+               char *method_return_type_cname = get_cname_for_type_reference (method->return_type, method->location);
+               method->cname = g_strdup_printf ("%s%s_%s", ns_lower, lower_case, method->name);
+
                char *parameters;
                GList *parameter_list = NULL;
                if ((method->modifiers & VALA_METHOD_STATIC) == 0) {
@@ -109,7 +103,7 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
                GList *pl;
                for (pl = method->formal_parameters; pl != NULL; pl = pl->next) {
                        ValaFormalParameter *param = pl->data;
-                       char *param_string = g_strdup_printf ("%s%s", get_cname_for_type_symbol (param->type->symbol, param->location), param->name);
+                       char *param_string = g_strdup_printf ("%s%s", get_cname_for_type_reference (param->type, param->location), param->name);
                        parameter_list = g_list_append (parameter_list, param_string);
                }
                
@@ -134,6 +128,23 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
                        fprintf (generator->c_file, "%s %s;\n", method->cdecl1, method->cdecl2);
                }
 
+               if (strcmp (method->name, "init") == 0) {
+                       if (method->modifiers & VALA_METHOD_STATIC) {
+                               err (method->location, "error: instance initializer must not be static");
+                       }
+                       if (method->formal_parameters != NULL) {
+                               err (method->location, "error: instance initializer must not have any arguments");
+                       }
+                       class->has_init = TRUE;
+               } else if (strcmp (method->name, "class_init") == 0) {
+                       if ((method->modifiers & VALA_METHOD_STATIC) == 0) {
+                               err (method->location, "error: class initializer must be static");
+                       }
+                       if (method->formal_parameters != NULL) {
+                               err (method->location, "error: class initializer must not have any arguments");
+                       }
+                       class->has_class_init = TRUE;
+               }
        }
        fprintf (generator->c_file, "\n");
 }
@@ -141,11 +152,44 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
 static void vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpression *expr);
 
 static void
-vala_code_generator_process_additive_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+vala_code_generator_process_operation_expression (ValaCodeGenerator *generator, ValaExpression *expr)
 {
-       vala_code_generator_process_expression (generator, expr->additive.left);
-       fprintf (generator->c_file, " + ");
-       vala_code_generator_process_expression (generator, expr->additive.right);
+       char *cop = "";
+       vala_code_generator_process_expression (generator, expr->op.left);
+       switch (expr->op.type) {
+       case VALA_OP_TYPE_PLUS:
+               cop = "+";
+               break;
+       case VALA_OP_TYPE_MINUS:
+               cop = "-";
+               break;
+       case VALA_OP_TYPE_MUL:
+               cop = "*";
+               break;
+       case VALA_OP_TYPE_DIV:
+               cop = "/";
+               break;
+       case VALA_OP_TYPE_EQ:
+               cop = "==";
+               break;
+       case VALA_OP_TYPE_NE:
+               cop = "!=";
+               break;
+       case VALA_OP_TYPE_LT:
+               cop = "<";
+               break;
+       case VALA_OP_TYPE_GT:
+               cop = ">";
+               break;
+       case VALA_OP_TYPE_LE:
+               cop = "<=";
+               break;
+       case VALA_OP_TYPE_GE:
+               cop = ">=";
+               break;
+       }
+       fprintf (generator->c_file, " %s ", cop);
+       vala_code_generator_process_expression (generator, expr->op.right);
 }
 
 static void
@@ -225,8 +269,6 @@ vala_code_generator_find_static_type_of_expression (ValaCodeGenerator *generator
                return;
                
        switch (expr->type) {
-       case VALA_EXPRESSION_TYPE_ADDITIVE:
-               break;
        case VALA_EXPRESSION_TYPE_ASSIGNMENT:
                break;
        case VALA_EXPRESSION_TYPE_INVOCATION:
@@ -243,6 +285,11 @@ vala_code_generator_find_static_type_of_expression (ValaCodeGenerator *generator
                        err (expr->member_access.left->location, "error: specified expression type %d can't be used for member access", sym->type);
                }
                break;
+       case VALA_EXPRESSION_TYPE_OBJECT_CREATION:
+               expr->static_type_symbol = expr->object_creation.type->symbol;
+               break;
+       case VALA_EXPRESSION_TYPE_OPERATION:
+               break;
        case VALA_EXPRESSION_TYPE_PARENTHESIZED:
                vala_code_generator_find_static_type_of_expression (generator, expr->inner);
                expr->static_type_symbol = expr->inner->static_type_symbol;
@@ -294,6 +341,14 @@ vala_code_generator_process_member_access (ValaCodeGenerator *generator, ValaExp
 }
 
 static void
+vala_code_generator_process_object_creation_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       fprintf (generator->c_file, "g_object_new (%sTYPE_%s", expr->object_creation.type->symbol->class->namespace->upper_case_cname, expr->object_creation.type->symbol->class->upper_case_cname);
+       /* FIXME: add property arguments */
+       fprintf (generator->c_file, ", NULL)");
+}
+
+static void
 vala_code_generator_process_parenthesized_expression (ValaCodeGenerator *generator, ValaExpression *expr)
 {
        fprintf (generator->c_file, "(");
@@ -302,6 +357,13 @@ vala_code_generator_process_parenthesized_expression (ValaCodeGenerator *generat
 }
 
 static void
+vala_code_generator_process_postfix_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       vala_code_generator_process_expression (generator, expr->postfix.inner);
+       fprintf (generator->c_file, "%s", expr->postfix.cop);
+}
+
+static void
 vala_code_generator_process_simple_name (ValaCodeGenerator *generator, ValaExpression *expr)
 {
        switch (expr->static_type_symbol->type) {
@@ -320,9 +382,6 @@ vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpres
        vala_code_generator_find_static_type_of_expression (generator, expr);
 
        switch (expr->type) {
-       case VALA_EXPRESSION_TYPE_ADDITIVE:
-               vala_code_generator_process_additive_expression (generator, expr);
-               break;
        case VALA_EXPRESSION_TYPE_ASSIGNMENT:
                vala_code_generator_process_assignment (generator, expr);
                break;
@@ -332,9 +391,18 @@ vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpres
        case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
                vala_code_generator_process_member_access (generator, expr);
                break;
+       case VALA_EXPRESSION_TYPE_OBJECT_CREATION:
+               vala_code_generator_process_object_creation_expression (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_OPERATION:
+               vala_code_generator_process_operation_expression (generator, expr);
+               break;
        case VALA_EXPRESSION_TYPE_PARENTHESIZED:
                vala_code_generator_process_parenthesized_expression (generator, expr);
                break;
+       case VALA_EXPRESSION_TYPE_POSTFIX:
+               vala_code_generator_process_postfix_expression (generator, expr);
+               break;
        case VALA_EXPRESSION_TYPE_LITERAL_INTEGER:
        case VALA_EXPRESSION_TYPE_LITERAL_STRING:
                vala_code_generator_process_literal (generator, expr);
@@ -348,9 +416,9 @@ vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpres
 static void
 vala_code_generator_process_variable_declaration (ValaCodeGenerator *generator, ValaStatement *stmt)
 {
-       ValaSymbol *sym = stmt->variable_declaration->type->symbol;
+       ValaTypeReference *type = stmt->variable_declaration->type;
 
-       char *decl_string = get_cname_for_type_symbol (sym, stmt->location);
+       char *decl_string = get_cname_for_type_reference (type, stmt->location);
 
        fprintf (generator->c_file, "\t%s%s", decl_string, stmt->variable_declaration->declarator->name);
        
@@ -362,7 +430,7 @@ vala_code_generator_process_variable_declaration (ValaCodeGenerator *generator,
 
        fprintf (generator->c_file, ";\n");
 
-       sym = vala_symbol_new (VALA_SYMBOL_TYPE_LOCAL_VARIABLE);
+       ValaSymbol *sym = vala_symbol_new (VALA_SYMBOL_TYPE_LOCAL_VARIABLE);
        g_hash_table_insert (generator->sym->symbol_table, stmt->variable_declaration->declarator->name, sym);
        sym->typeref = stmt->variable_declaration->type;
 }
@@ -384,6 +452,52 @@ vala_code_generator_process_block (ValaCodeGenerator *generator, ValaStatement *
 }
 
 static void
+vala_code_generator_process_statement_expression_list (ValaCodeGenerator *generator, GList *list)
+{
+       GList *l;
+       gboolean first = TRUE;
+       
+       for (l = list; l != NULL; l = l->next) {
+               if (!first) {
+                       fprintf (generator->c_file, ", ");
+               } else {
+                       first = FALSE;
+               }
+               vala_code_generator_process_expression (generator, l->data);
+       }
+}
+
+static void
+vala_code_generator_process_for_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+       GList *l;
+       
+       fprintf (generator->c_file, "\tfor (");
+       vala_code_generator_process_statement_expression_list (generator, stmt->for_stmt.initializer);
+       fprintf (generator->c_file, "; ");
+       vala_code_generator_process_expression (generator, stmt->for_stmt.condition);
+       fprintf (generator->c_file, "; ");
+       vala_code_generator_process_statement_expression_list (generator, stmt->for_stmt.iterator);
+       fprintf (generator->c_file, ")\n");
+       vala_code_generator_process_statement (generator, stmt->for_stmt.loop);
+}
+
+static void
+vala_code_generator_process_if_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+       GList *l;
+       
+       fprintf (generator->c_file, "\tif (");
+       vala_code_generator_process_expression (generator, stmt->if_stmt.condition);
+       fprintf (generator->c_file, ")\n");
+       vala_code_generator_process_statement (generator, stmt->if_stmt.true_stmt);
+       if (stmt->if_stmt.false_stmt != NULL) {
+               fprintf (generator->c_file, "\telse ");
+               vala_code_generator_process_statement (generator, stmt->if_stmt.false_stmt);
+       }
+}
+
+static void
 vala_code_generator_process_return_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
 {
        GList *l;
@@ -405,6 +519,12 @@ vala_code_generator_process_statement (ValaCodeGenerator *generator, ValaStateme
                vala_code_generator_process_expression (generator, stmt->expr);
                fprintf (generator->c_file, ";\n");
                break;
+       case VALA_STATEMENT_TYPE_FOR:
+               vala_code_generator_process_for_statement (generator, stmt);
+               break;
+       case VALA_STATEMENT_TYPE_IF:
+               vala_code_generator_process_if_statement (generator, stmt);
+               break;
        case VALA_STATEMENT_TYPE_RETURN:
                vala_code_generator_process_return_statement (generator, stmt);
                break;
@@ -462,21 +582,39 @@ vala_code_generator_process_methods2 (ValaCodeGenerator *generator, ValaClass *c
                }
                
                fprintf (generator->c_file, "\n");
+
+               if ((method->modifiers & VALA_METHOD_STATIC) && strcmp (method->name, "main") == 0 && strcmp (method->return_type->type_name, "int") == 0) {
+                       if (g_list_length (method->formal_parameters) == 2) {
+                               /* main method */
+                               
+                               fprintf (generator->c_file, "int\n");
+                               fprintf (generator->c_file, "main (int argc, char **argv)\n");
+                               fprintf (generator->c_file, "{\n");
+                               fprintf (generator->c_file, "\tg_type_init ();\n");
+                               fprintf (generator->c_file, "\treturn %s (argc, argv);\n", method->cname);
+                               fprintf (generator->c_file, "}\n");
+                               fprintf (generator->c_file, "\n");
+                       }
+               }
        }
        fprintf (generator->h_file, "\n");
 
        /* constructors */
-       fprintf (generator->c_file, "static void\n");
-       fprintf (generator->c_file, "%s%s_init (%s%s *self)\n", ns_lower, lower_case, namespace->name, class->name);
-       fprintf (generator->c_file, "{\n");
-       fprintf (generator->c_file, "}\n");
-       fprintf (generator->c_file, "\n");
+       if (!class->has_init) {
+               fprintf (generator->c_file, "static void\n");
+               fprintf (generator->c_file, "%s%s_init (%s%s *self)\n", ns_lower, lower_case, namespace->name, class->name);
+               fprintf (generator->c_file, "{\n");
+               fprintf (generator->c_file, "}\n");
+               fprintf (generator->c_file, "\n");
+       }
 
-       fprintf (generator->c_file, "static void\n");
-       fprintf (generator->c_file, "%s%s_class_init (%s%sClass *klass)\n", ns_lower, lower_case, namespace->name, class->name);
-       fprintf (generator->c_file, "{\n");
-       fprintf (generator->c_file, "}\n");
-       fprintf (generator->c_file, "\n");
+       if (!class->has_class_init) {
+               fprintf (generator->c_file, "static void\n");
+               fprintf (generator->c_file, "%s%s_class_init (%s%sClass *klass)\n", ns_lower, lower_case, namespace->name, class->name);
+               fprintf (generator->c_file, "{\n");
+               fprintf (generator->c_file, "}\n");
+               fprintf (generator->c_file, "\n");
+       }
 }
 
 static void
index 5c28426..3395119 100644 (file)
@@ -112,6 +112,7 @@ ValaLocation *get_location (int lineno, int colno)
 %union {
        int num;
        char *str;
+       gboolean bool;
        GList *list;
        ValaTypeReference *type_reference;
        ValaFormalParameter *formal_parameter;
@@ -119,20 +120,39 @@ ValaLocation *get_location (int lineno, int colno)
        ValaVariableDeclaration *variable_declaration;
        ValaVariableDeclarator *variable_declarator;
        ValaExpression *expression;
+       ValaNamedArgument *named_argument;
 }
 
 %token OPEN_BRACE "{"
 %token CLOSE_BRACE "}"
 %token OPEN_PARENS "("
 %token CLOSE_PARENS ")"
+%token OPEN_BRACKET "["
+%token CLOSE_BRACKET "]"
 %token DOT "."
 %token COLON ":"
 %token COMMA ","
 %token SEMICOLON ";"
+
+%token OP_INC "++"
+%token OP_DEC "--"
+%token OP_EQ "=="
+%token OP_NE "!="
+%token OP_LE "<="
+%token OP_GE ">="
+%token OP_LT "<"
+%token OP_GT ">"
+
 %token ASSIGN "="
 %token PLUS "+"
+%token MINUS "-"
+%token STAR "*"
+%token DIV "/"
 
 %token CLASS "class"
+%token ELSE "else"
+%token FOR "for"
+%token IF "if"
 %token NAMESPACE "namespace"
 %token PUBLIC "public"
 %token RETURN "return"
@@ -152,14 +172,21 @@ ValaLocation *get_location (int lineno, int colno)
 %type <list> statement_list
 %type <list> opt_argument_list
 %type <list> argument_list
+%type <list> opt_named_argument_list
+%type <list> named_argument_list
+%type <list> opt_statement_expression_list
+%type <list> statement_expression_list
 %type <num> opt_method_modifiers
 %type <num> method_modifiers
 %type <num> method_modifier
+%type <bool> opt_brackets
 %type <type_reference> type_name
 %type <expression> variable_initializer
 %type <expression> opt_expression
 %type <expression> expression
 %type <expression> additive_expression
+%type <expression> multiplicative_expression
+%type <expression> unary_expression
 %type <expression> assignment
 %type <expression> primary_expression
 %type <expression> literal
@@ -169,16 +196,26 @@ ValaLocation *get_location (int lineno, int colno)
 %type <expression> invocation_expression
 %type <expression> statement_expression
 %type <expression> argument
+%type <expression> object_creation_expression
+%type <expression> equality_expression
+%type <expression> relational_expression
+%type <expression> post_increment_expression
+%type <expression> post_decrement_expression
 %type <statement> block
 %type <statement> statement
 %type <statement> declaration_statement
 %type <statement> embedded_statement
 %type <statement> expression_statement
+%type <statement> selection_statement
+%type <statement> if_statement
+%type <statement> iteration_statement
+%type <statement> for_statement
 %type <statement> jump_statement
 %type <statement> return_statement
 %type <formal_parameter> fixed_parameter
 %type <variable_declaration> variable_declaration
 %type <variable_declarator> variable_declarator
+%type <named_argument> named_argument
 
 %%
 
@@ -286,23 +323,36 @@ type_list
        ;
 
 type_name
-       : IDENTIFIER
+       : IDENTIFIER opt_brackets
          {
                ValaTypeReference *type_reference = g_new0 (ValaTypeReference, 1);
                type_reference->type_name = g_strdup ($1);
                type_reference->location = current_location (@1);
+               type_reference->array_type = $2;
                $$ = type_reference;
          }
-       | IDENTIFIER DOT IDENTIFIER
+       | IDENTIFIER DOT IDENTIFIER opt_brackets
          {
                ValaTypeReference *type_reference = g_new0 (ValaTypeReference, 1);
                type_reference->namespace_name = g_strdup ($1);
                type_reference->type_name = g_strdup ($3);
                type_reference->location = current_location (@1);
+               type_reference->array_type = $4;
                $$ = type_reference;
          }
        ;
 
+opt_brackets
+       : /* empty */
+         {
+               $$ = FALSE;
+         }
+       | OPEN_BRACKET CLOSE_BRACKET
+         {
+               $$ = TRUE;
+         }
+       ;
+
 class_body
        : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
        ;
@@ -512,7 +562,7 @@ opt_expression
        ;
 
 expression
-       : additive_expression
+       : equality_expression
          {
                $$ = $1;
          }
@@ -522,19 +572,128 @@ expression
          }
        ;
 
+equality_expression
+       : relational_expression
+         {
+               $$ = $1;
+         }
+       | equality_expression OP_EQ relational_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_EQ;
+               $$->op.right = $3;
+         }
+       | equality_expression OP_NE relational_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_NE;
+               $$->op.right = $3;
+         }
+       ;
+
+relational_expression
+       : additive_expression
+         {
+               $$ = $1;
+         }
+       | relational_expression OP_LT additive_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_LT;
+               $$->op.right = $3;
+         }
+       | relational_expression OP_GT additive_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_GT;
+               $$->op.right = $3;
+         }
+       | relational_expression OP_LE additive_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_LE;
+               $$->op.right = $3;
+         }
+       | relational_expression OP_GE additive_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_GE;
+               $$->op.right = $3;
+         }
+       ;
+
 additive_expression
-       : primary_expression
+       : multiplicative_expression
          {
                $$ = $1;
          }
-       | additive_expression PLUS primary_expression
+       | additive_expression PLUS multiplicative_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_PLUS;
+               $$->op.right = $3;
+         }
+       | additive_expression MINUS multiplicative_expression
          {
                $$ = g_new0 (ValaExpression, 1);
-               $$->type = VALA_EXPRESSION_TYPE_ADDITIVE;
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
                $$->location = current_location (@1);
-               $$->additive.left = $1;
-               $$->additive.op = VALA_OP_TYPE_PLUS;
-               $$->additive.right = $3;
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_MINUS;
+               $$->op.right = $3;
+         }
+       ;
+
+multiplicative_expression
+       : unary_expression
+         {
+               $$ = $1;
+         }
+       | multiplicative_expression STAR unary_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_MUL;
+               $$->op.right = $3;
+         }
+       | multiplicative_expression DIV unary_expression
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OPERATION;
+               $$->location = current_location (@1);
+               $$->op.left = $1;
+               $$->op.type = VALA_OP_TYPE_DIV;
+               $$->op.right = $3;
+         }
+       ;
+
+unary_expression
+       : primary_expression
+         {
+               $$ = $1;
          }
        ;
 
@@ -559,6 +718,18 @@ primary_expression
          {
                $$ = $1;
          }
+       | post_increment_expression
+         {
+               $$ = $1;
+         }
+       | post_decrement_expression
+         {
+               $$ = $1;
+         }
+       | object_creation_expression
+         {
+               $$ = $1;
+         }
        ;
 
 literal
@@ -649,6 +820,76 @@ argument
          }
        ;
 
+post_increment_expression
+       : primary_expression OP_INC
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_POSTFIX;
+               $$->location = current_location (@1);
+               $$->postfix.inner = $1;
+               $$->postfix.cop = "++";
+         }
+       ;
+
+post_decrement_expression
+       : primary_expression OP_DEC
+         {
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_POSTFIX;
+               $$->location = current_location (@1);
+               $$->postfix.inner = $1;
+               $$->postfix.cop = "--";
+         }
+       ;
+
+object_creation_expression
+       : IDENTIFIER type_name OPEN_PARENS opt_named_argument_list CLOSE_PARENS
+         {
+               if (strcmp ($1, "new") != 0) {
+                       /* raise error */
+                       fprintf (stderr, "syntax error: object creation expression without new\n");
+               }
+               
+               $$ = g_new0 (ValaExpression, 1);
+               $$->type = VALA_EXPRESSION_TYPE_OBJECT_CREATION;
+               $$->location = current_location (@1);
+               $$->object_creation.type = $2;
+               $$->object_creation.named_argument_list = $4;
+         }
+       ;
+
+opt_named_argument_list
+       : /* empty */
+         {
+               $$ = NULL;
+         }
+       | named_argument_list
+         {
+               $$ = $1;
+         }
+       ;
+
+named_argument_list
+       : named_argument
+         {
+               $$ = g_list_append (NULL, $1);
+         }
+       | named_argument_list COMMA named_argument
+         {
+               $$ = g_list_append ($1, $3);
+         }
+       ;
+
+named_argument
+       : IDENTIFIER ASSIGN expression
+         {
+               $$ = g_new0 (ValaNamedArgument, 1);
+               $$->name = $1;
+               $$->expression = $3;
+               $$->location = current_location (@1);
+         }
+       ;
+
 embedded_statement
        : block
          {
@@ -662,6 +903,14 @@ embedded_statement
          {
                $$ = $1;
          }
+       | selection_statement
+         {
+               $$ = $1;
+         }
+       | iteration_statement
+         {
+               $$ = $1;
+         }
        | jump_statement
          {
                $$ = $1;
@@ -687,10 +936,22 @@ statement_expression
          {
                $$ = $1;
          }
+       | object_creation_expression
+         {
+               $$ = $1;
+         }
        | assignment
          {
                $$ = $1;
          }
+       | post_increment_expression
+         {
+               $$ = $1;
+         }
+       | post_decrement_expression
+         {
+               $$ = $1;
+         }
        ;
 
 assignment
@@ -704,6 +965,76 @@ assignment
          }
        ;
 
+selection_statement
+       : if_statement
+         {
+               $$ = $1;
+         }
+       ;
+
+if_statement
+       : IF OPEN_PARENS expression CLOSE_PARENS embedded_statement
+         {
+               $$ = g_new0 (ValaStatement, 1);
+               $$->type = VALA_STATEMENT_TYPE_IF;
+               $$->location = current_location (@1);
+               $$->if_stmt.condition = $3;
+               $$->if_stmt.true_stmt = $5;
+         }
+       | IF OPEN_PARENS expression CLOSE_PARENS embedded_statement ELSE embedded_statement
+         {
+               $$ = g_new0 (ValaStatement, 1);
+               $$->type = VALA_STATEMENT_TYPE_IF;
+               $$->location = current_location (@1);
+               $$->if_stmt.condition = $3;
+               $$->if_stmt.true_stmt = $5;
+               $$->if_stmt.false_stmt = $7;
+         }
+       ;
+
+
+iteration_statement
+       : for_statement
+         {
+               $$ = $1;
+         }
+       ;
+
+for_statement
+       : FOR OPEN_PARENS opt_statement_expression_list SEMICOLON opt_expression SEMICOLON opt_statement_expression_list CLOSE_PARENS embedded_statement
+         {
+               $$ = g_new0 (ValaStatement, 1);
+               $$->type = VALA_STATEMENT_TYPE_FOR;
+               $$->location = current_location (@1);
+               $$->for_stmt.initializer = $3;
+               $$->for_stmt.condition = $5;
+               $$->for_stmt.iterator = $7;
+               $$->for_stmt.loop = $9;
+         }
+       ;
+
+opt_statement_expression_list
+       : /* empty */
+         {
+               $$ = NULL;
+         }
+       | statement_expression_list
+         {
+               $$ = $1;
+         }
+       ;
+
+statement_expression_list
+       : statement_expression
+         {
+               $$ = g_list_append (NULL, $1);
+         }
+       | statement_expression_list COMMA statement_expression
+         {
+               $$ = g_list_append ($1, $3);
+         }
+       ;
+
 jump_statement
        : return_statement
          {
index 64dc066..050af06 100644 (file)
 "}"            { uploc; return CLOSE_BRACE; }
 "("            { uploc; return OPEN_PARENS; }
 ")"            { uploc; return CLOSE_PARENS; }
+"["            { uploc; return OPEN_BRACKET; }
+"]"            { uploc; return CLOSE_BRACKET; }
 "."            { uploc; return DOT; }
 ":"            { uploc; return COLON; }
 ","            { uploc; return COMMA; }
 ";"            { uploc; return SEMICOLON; }
+
+"++"           { uploc; return OP_INC; }
+"--"           { uploc; return OP_DEC; }
+"=="           { uploc; return OP_EQ; }
+"!="           { uploc; return OP_NE; }
+"<="           { uploc; return OP_LE; }
+">="           { uploc; return OP_GE; }
+"<"            { uploc; return OP_LT; }
+">"            { uploc; return OP_GT; }
+
 "="            { uploc; return ASSIGN; }
 "+"            { uploc; return PLUS; }
+"-"            { uploc; return MINUS; }
+"*"            { uploc; return STAR; }
+"/"            { uploc; return DIV; }
 
 "class"                { uploc; return CLASS; }
+"else"         { uploc; return ELSE; }
+"for"          { uploc; return FOR; }
+"if"           { uploc; return IF; }
 "namespace"    { uploc; return NAMESPACE; }
 "public"       { uploc; return PUBLIC; }
 "return"       { uploc; return RETURN; }