From: Jürg Billeter Date: Wed, 26 Apr 2006 14:58:13 +0000 (+0000) Subject: support OPEN_BRACKET, CLOSE_BRACKET, OP_INC, OP_DEC, OP_EQ, OP_NE, OP_LE, X-Git-Tag: VALA_0_0_1~73 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8ff7a6ebcbef3df62a7c8d2bc39e4a47ac3bae1b;p=thirdparty%2Fvala.git support OPEN_BRACKET, CLOSE_BRACKET, OP_INC, OP_DEC, OP_EQ, OP_NE, OP_LE, 2006-04-26 Jürg Billeter * 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 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index dd70e70f9..68c5afce6 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,21 @@ +2006-04-26 Jürg Billeter + + * 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 * 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 index 000000000..0d3aa9706 --- /dev/null +++ b/vala/tests/test-006.vala @@ -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); + } + } +} diff --git a/vala/valac/context.c b/vala/valac/context.c index 983c03f97..92bd39f0c 100644 --- a/vala/valac/context.c +++ b/vala/valac/context.c @@ -280,12 +280,25 @@ 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; } } diff --git a/vala/valac/context.h b/vala/valac/context.h index f3866c16b..8e68ac51c 100644 --- a/vala/valac/context.h +++ b/vala/valac/context.h @@ -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); diff --git a/vala/valac/generator.c b/vala/valac/generator.c index aad37a1fa..0508261f2 100644 --- a/vala/valac/generator.c +++ b/vala/valac/generator.c @@ -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; @@ -293,6 +340,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) { @@ -301,6 +356,13 @@ vala_code_generator_process_parenthesized_expression (ValaCodeGenerator *generat fprintf (generator->c_file, ")"); } +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) { @@ -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; } @@ -383,6 +451,52 @@ vala_code_generator_process_block (ValaCodeGenerator *generator, ValaStatement * fprintf (generator->c_file, "}\n"); } +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) { @@ -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 diff --git a/vala/valac/parser.y b/vala/valac/parser.y index 5c28426ff..33951196a 100644 --- a/vala/valac/parser.y +++ b/vala/valac/parser.y @@ -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 statement_list %type opt_argument_list %type argument_list +%type opt_named_argument_list +%type named_argument_list +%type opt_statement_expression_list +%type statement_expression_list %type opt_method_modifiers %type method_modifiers %type method_modifier +%type opt_brackets %type type_name %type variable_initializer %type opt_expression %type expression %type additive_expression +%type multiplicative_expression +%type unary_expression %type assignment %type primary_expression %type literal @@ -169,16 +196,26 @@ ValaLocation *get_location (int lineno, int colno) %type invocation_expression %type statement_expression %type argument +%type object_creation_expression +%type equality_expression +%type relational_expression +%type post_increment_expression +%type post_decrement_expression %type block %type statement %type declaration_statement %type embedded_statement %type expression_statement +%type selection_statement +%type if_statement +%type iteration_statement +%type for_statement %type jump_statement %type return_statement %type fixed_parameter %type variable_declaration %type variable_declarator +%type 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 { diff --git a/vala/valac/scanner.l b/vala/valac/scanner.l index 64dc066bf..050af0660 100644 --- a/vala/valac/scanner.l +++ b/vala/valac/scanner.l @@ -40,14 +40,32 @@ "}" { 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; }