+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
--- /dev/null
+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);
+ }
+ }
+}
}
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;
}
}
typedef struct _ValaExpression ValaExpression;
typedef struct _ValaTypeReference ValaTypeReference;
typedef struct _ValaFormalParameter ValaFormalParameter;
+typedef struct _ValaNamedArgument ValaNamedArgument;
enum _ValaSymbolType {
VALA_SYMBOL_TYPE_ROOT,
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 {
char *cname;
char *lower_case_cname;
char *upper_case_cname;
+ gboolean has_init;
+ gboolean has_class_init;
};
struct _ValaStruct {
} 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;
};
};
ValaExpression *inner;
struct {
ValaExpression *left;
- ValaOpType op;
+ ValaOpType type;
ValaExpression *right;
- } additive;
+ } op;
struct {
ValaExpression *left;
char *right;
ValaExpression *left;
ValaExpression *right;
} assignment;
+ struct {
+ ValaTypeReference *type;
+ GList *named_argument_list;
+ } object_creation;
+ struct {
+ ValaExpression *inner;
+ const char *cop;
+ } postfix;
};
};
char *type_name;
ValaLocation *location;
ValaSymbol *symbol;
+ gboolean array_type;
};
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);
}
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;
}
}
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) {
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);
}
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");
}
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
return;
switch (expr->type) {
- case VALA_EXPRESSION_TYPE_ADDITIVE:
- break;
case VALA_EXPRESSION_TYPE_ASSIGNMENT:
break;
case VALA_EXPRESSION_TYPE_INVOCATION:
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;
}
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, "(");
}
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) {
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;
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);
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);
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;
}
}
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;
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;
}
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
%union {
int num;
char *str;
+ gboolean bool;
GList *list;
ValaTypeReference *type_reference;
ValaFormalParameter *formal_parameter;
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"
%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
%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
%%
;
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
;
;
expression
- : additive_expression
+ : equality_expression
{
$$ = $1;
}
}
;
+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;
}
;
{
$$ = $1;
}
+ | post_increment_expression
+ {
+ $$ = $1;
+ }
+ | post_decrement_expression
+ {
+ $$ = $1;
+ }
+ | object_creation_expression
+ {
+ $$ = $1;
+ }
;
literal
}
;
+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
{
{
$$ = $1;
}
+ | selection_statement
+ {
+ $$ = $1;
+ }
+ | iteration_statement
+ {
+ $$ = $1;
+ }
| jump_statement
{
$$ = $1;
{
$$ = $1;
}
+ | object_creation_expression
+ {
+ $$ = $1;
+ }
| assignment
{
$$ = $1;
}
+ | post_increment_expression
+ {
+ $$ = $1;
+ }
+ | post_decrement_expression
+ {
+ $$ = $1;
+ }
;
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
{
"}" { 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; }