}
}
-static ValaSymbol *
+ValaSymbol *
vala_symbol_new (ValaSymbolType type)
{
ValaSymbol *symbol;
return symbol;
}
-static void
+void
err (ValaLocation *location, const char *format, ...)
{
va_list args;
}
static void
+vala_context_add_symbols_from_method (ValaContext *context, ValaSymbol *class_symbol, ValaMethod *method)
+{
+ ValaSymbol *method_symbol;
+
+ method_symbol = g_hash_table_lookup (class_symbol->symbol_table, method->name);
+ if (method_symbol != NULL) {
+ err (method->location, "error: class member ´%s.%s.%s´ already defined", class_symbol->class->namespace->name, class_symbol->class->name, method->name);
+ }
+
+ method_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_METHOD);
+ method_symbol->method = method;
+ g_hash_table_insert (class_symbol->symbol_table, method->name, method_symbol);
+
+ if (method->body != NULL) {
+ method->body->method = method_symbol;
+ }
+}
+
+static void
+vala_context_add_symbols_from_class (ValaContext *context, ValaClass *class)
+{
+ ValaSymbol *ns_symbol, *class_symbol;
+ ns_symbol = class->namespace->symbol;
+ GList *ml;
+
+ class_symbol = g_hash_table_lookup (ns_symbol->symbol_table, class->name);
+ if (class_symbol != NULL) {
+ err (class->location, "error: class ´%s.%s´ already defined", class->namespace->name, class->name);
+ }
+
+ class_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_CLASS);
+ class_symbol->class = class;
+ g_hash_table_insert (ns_symbol->symbol_table, class->name, class_symbol);
+
+ class->symbol = class_symbol;
+
+ for (ml = class->methods; ml != NULL; ml = ml->next) {
+ vala_context_add_symbols_from_method (context, class_symbol, ml->data);
+ }
+}
+
+static void
+vala_context_add_symbols_from_struct (ValaContext *context, ValaStruct *struct_)
+{
+ ValaSymbol *ns_symbol, *struct_symbol;
+ ns_symbol = struct_->namespace->symbol;
+ GList *ml;
+
+ struct_symbol = g_hash_table_lookup (ns_symbol->symbol_table, struct_->name);
+ if (struct_symbol != NULL) {
+ err (struct_->location, "error: struct ´%s.%s´ already defined", struct_->namespace->name, struct_->name);
+ }
+
+ struct_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_STRUCT);
+ struct_symbol->struct_ = struct_;
+ g_hash_table_insert (ns_symbol->symbol_table, struct_->name, struct_symbol);
+
+ struct_->symbol = struct_symbol;
+}
+
+static void
vala_context_add_symbols_from_namespace (ValaContext *context, ValaNamespace *namespace)
{
ValaSymbol *ns_symbol, *class_symbol;
namespace->symbol = ns_symbol;
for (cl = namespace->classes; cl != NULL; cl = cl->next) {
- ValaClass *class = cl->data;
-
- class_symbol = g_hash_table_lookup (ns_symbol->symbol_table, class->name);
- if (class_symbol != NULL) {
- err (class->location, "error: class ´%s.%s´ already defined", namespace->name, class->name);
- }
-
- class_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_CLASS);
- class_symbol->class = class;
- g_hash_table_insert (ns_symbol->symbol_table, class->name, class_symbol);
+ vala_context_add_symbols_from_class (context, cl->data);
+ }
+
+ for (cl = namespace->structs; cl != NULL; cl = cl->next) {
+ vala_context_add_symbols_from_struct (context, cl->data);
}
}
ValaSymbol *symbol;
ValaNamespace *namespace;
ValaClass *class;
+ ValaStruct *struct_;
context->root = vala_symbol_new (VALA_SYMBOL_TYPE_ROOT);
+
+ namespace = g_new0 (ValaNamespace, 1);
+ namespace->name = g_strdup ("");
+ namespace->lower_case_cname = g_strdup ("");
+ namespace->upper_case_cname = g_strdup ("");
/* void */
symbol = vala_symbol_new (VALA_SYMBOL_TYPE_VOID);
g_hash_table_insert (context->root->symbol_table, "void", symbol);
+ /* int */
+ struct_ = g_new0 (ValaStruct, 1);
+ struct_->name = g_strdup ("int");
+ struct_->namespace = namespace;
+ struct_->cname = g_strdup ("int");
+ namespace->structs = g_list_append (namespace->structs, struct_);
+
+ /* string */
+ struct_ = g_new0 (ValaStruct, 1);
+ struct_->name = g_strdup ("string");
+ struct_->reference_type = TRUE;
+ struct_->namespace = namespace;
+ struct_->cname = g_strdup ("char");
+ namespace->structs = g_list_append (namespace->structs, struct_);
+
+ vala_context_add_symbols_from_namespace (context, namespace);
+
/* namespace G */
namespace = g_new0 (ValaNamespace, 1);
namespace->name = g_strdup ("G");
err (type_reference->location, "error: specified namespace '%s' not found", type_reference->namespace_name);
}
- type_symbol = g_hash_table_lookup (namespace->symbol->symbol_table, type_reference->type_name);
+ type_symbol = g_hash_table_lookup (ns_symbol->symbol_table, type_reference->type_name);
if (type_symbol == NULL) {
/* specified namespace not found */
err (type_reference->location, "error: specified type ´%s´ not found in namespace ´%s´", type_reference->type_name, type_reference->namespace_name);
}
if (type_symbol->type == VALA_SYMBOL_TYPE_VOID ||
- type_symbol->type == VALA_SYMBOL_TYPE_CLASS) {
+ type_symbol->type == VALA_SYMBOL_TYPE_CLASS ||
+ type_symbol->type == VALA_SYMBOL_TYPE_STRUCT) {
type_reference->symbol = type_symbol;
} else {
err (type_reference->location, "error: specified symbol ´%s´ is not a type", type_reference->type_name);
}
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);
+ break;
+ }
+}
+
+static void
+vala_context_resolve_types_in_block (ValaContext *context, ValaNamespace *namespace, ValaStatement *stmt)
+{
+ GList *l;
+
+ for (l = stmt->block.statements; l != NULL; l = l ->next) {
+ vala_context_resolve_types_in_statement (context, namespace, l->data);
+ }
+}
+
+static void
vala_context_resolve_types_in_method (ValaContext *context, ValaMethod *method)
{
GList *l;
err (formal_parameter->location, "error: method parameters cannot be of type `void`");
}
}
+
+ if (method->body != NULL) {
+ vala_context_resolve_types_in_block (context, method->class->namespace, method->body);
+ }
}
static void
* Jürg Billeter <j@bitron.ch>
*/
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
return define;
}
+static char *
+get_cname_for_type_symbol (ValaSymbol *sym, ValaLocation *location)
+{
+ switch (sym->type) {
+ case VALA_SYMBOL_TYPE_CLASS:
+ return g_strdup_printf ("%s *", sym->class->cname);
+ case VALA_SYMBOL_TYPE_STRUCT:
+ return g_strdup_printf ("%s %s", sym->struct_->cname, (sym->struct_->reference_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);
+ return NULL;
+ }
+}
+
static void
vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *class)
{
for (l = class->methods; l != NULL; l = l->next) {
ValaMethod *method = l->data;
- char *method_return_type_cname = g_strdup_printf ("%s%s", method->return_type->namespace_name, method->return_type->type_name);
- char *method_cname = g_strdup_printf ("%s%s_%s", ns_lower, lower_case, method->name);
+ 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 *parameters;
GList *parameter_list = NULL;
if ((method->modifiers & VALA_METHOD_STATIC) == 0) {
- parameter_list = g_list_append (parameter_list, g_strdup_printf ("%s%s *self", namespace->name, class->name));
+ parameter_list = g_list_append (parameter_list, g_strdup_printf ("%s *self", class->cname));
}
GList *pl;
for (pl = method->formal_parameters; pl != NULL; pl = pl->next) {
ValaFormalParameter *param = pl->data;
- parameter_list = g_list_append (parameter_list, g_strdup_printf ("%s%s *%s", param->type->symbol->class->namespace->name, param->type->symbol->class->name, param->name));
+ char *param_string = g_strdup_printf ("%s%s", get_cname_for_type_symbol (param->type->symbol, param->location), param->name);
+ parameter_list = g_list_append (parameter_list, param_string);
}
if (parameter_list == NULL) {
g_list_free (parameter_list);
}
- method->cdecl2 = g_strdup_printf ("%s (%s)", method_cname, parameters);
+ method->cdecl2 = g_strdup_printf ("%s (%s)", method->cname, parameters);
if (method->modifiers & VALA_METHOD_PUBLIC) {
method->cdecl1 = g_strdup (method_return_type_cname);
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_expression (generator, expr->additive.left);
+ fprintf (generator->c_file, " + ");
+ vala_code_generator_process_expression (generator, expr->additive.right);
+}
+
+static void
+vala_code_generator_process_assignment (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ vala_code_generator_process_expression (generator, expr->assignment.left);
+ fprintf (generator->c_file, " = ");
+ vala_code_generator_process_expression (generator, expr->assignment.right);
+}
+
+static void
+vala_code_generator_process_invocation (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ GList *l;
+ ValaMethod *method = NULL;
+ gboolean first = TRUE;
+
+ vala_code_generator_process_expression (generator, expr->invocation.call);
+ method = expr->invocation.call->static_type_symbol->method;
+ switch (expr->invocation.call->type) {
+ case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
+ expr->invocation.instance = expr->invocation.call->member_access.left;
+ break;
+ }
+ fprintf (generator->c_file, " (");
+ if ((method->modifiers & VALA_METHOD_STATIC) == 0) {
+ if (expr->invocation.instance != NULL) {
+ vala_code_generator_process_expression (generator, expr->invocation.instance);
+ } else {
+ fprintf (generator->c_file, "self");
+ }
+ first = FALSE;
+ }
+ for (l = expr->invocation.argument_list; l != NULL; l = l->next) {
+ if (!first) {
+ fprintf (generator->c_file, ", ");
+ } else {
+ first = FALSE;
+ }
+ vala_code_generator_process_expression (generator, l->data);
+ }
+ fprintf (generator->c_file, ")");
+}
+
+static void
+vala_code_generator_process_literal (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ fprintf (generator->c_file, "%s", expr->str);
+}
+
+static ValaSymbol *
+get_inherited_member (ValaSymbol *type, const char *name, ValaLocation *location, gboolean break_on_failure)
+{
+ ValaSymbol *sym;
+ sym = g_hash_table_lookup (type->symbol_table, name);
+ if (sym != NULL) {
+ return sym;
+ }
+
+ if (type->class->base_class == NULL) {
+ if (break_on_failure) {
+ err (location, "error: type member ´%s´ not found", name);
+ }
+
+ return NULL;
+ }
+
+ return get_inherited_member (type->class->base_class->symbol, name, location, break_on_failure);
+}
+
+static void
+vala_code_generator_find_static_type_of_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ ValaSymbol *sym = NULL, *sym2 = NULL;
+
+ if (expr->static_type_symbol != NULL)
+ return;
+
+ switch (expr->type) {
+ case VALA_EXPRESSION_TYPE_ADDITIVE:
+ break;
+ case VALA_EXPRESSION_TYPE_ASSIGNMENT:
+ break;
+ case VALA_EXPRESSION_TYPE_INVOCATION:
+ vala_code_generator_find_static_type_of_expression (generator, expr->invocation.call);
+ expr->static_type_symbol = expr->invocation.call->static_type_symbol->method->return_type->symbol;
+ break;
+ case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
+ vala_code_generator_find_static_type_of_expression (generator, expr->member_access.left);
+ sym = expr->member_access.left->static_type_symbol;
+ if (sym != NULL && sym->type == VALA_SYMBOL_TYPE_CLASS) {
+ expr->static_type_symbol = get_inherited_member (sym, expr->member_access.right, expr->member_access.left->location, TRUE);
+ } else if (sym != NULL && sym->type == VALA_SYMBOL_TYPE_LOCAL_VARIABLE) {
+ } else {
+ 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_PARENTHESIZED:
+ vala_code_generator_find_static_type_of_expression (generator, expr->inner);
+ expr->static_type_symbol = expr->inner->static_type_symbol;
+ break;
+ case VALA_EXPRESSION_TYPE_LITERAL_INTEGER:
+ case VALA_EXPRESSION_TYPE_LITERAL_STRING:
+ break;
+ case VALA_EXPRESSION_TYPE_SIMPLE_NAME:
+ if (strcmp (expr->str, "this") == 0) {
+ expr->static_type_symbol = generator->sym->stmt->method->method->class->symbol;
+ }
+
+ if (expr->static_type_symbol == NULL) {
+ /* local variable */
+ sym = g_hash_table_lookup (generator->sym->symbol_table, expr->str);
+ if (sym != NULL) {
+ expr->static_type_symbol = sym->typeref->symbol;
+ }
+ }
+
+ if (expr->static_type_symbol == NULL) {
+ /* member of this */
+ expr->static_type_symbol = get_inherited_member (generator->sym->stmt->method->method->class->symbol, expr->str, expr->location, FALSE);
+ }
+
+ if (expr->static_type_symbol == NULL) {
+ /* member of this */
+ expr->static_type_symbol = g_hash_table_lookup (generator->context->root->symbol_table, expr->str);
+ }
+
+ if (expr->static_type_symbol == NULL) {
+ err (expr->location, "error: symbol ´%s´ not found", expr->str);
+ }
+ break;
+ }
+}
+
+static void
+vala_code_generator_process_member_access (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ ValaSymbol *sym = expr->static_type_symbol;
+ if (sym->type == VALA_SYMBOL_TYPE_METHOD) {
+ ValaMethod *method = sym->method;
+ fprintf (generator->c_file, "%s", method->cname);
+ } else {
+ vala_code_generator_process_expression (generator, expr->member_access.left);
+ fprintf (generator->c_file, "->%s", expr->member_access.right);
+ }
+}
+
+static void
+vala_code_generator_process_parenthesized_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ fprintf (generator->c_file, "(");
+ vala_code_generator_process_expression (generator, expr->inner);
+ fprintf (generator->c_file, ")");
+}
+
+static void
+vala_code_generator_process_simple_name (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ switch (expr->static_type_symbol->type) {
+ case VALA_SYMBOL_TYPE_METHOD:
+ fprintf (generator->c_file, "%s", expr->static_type_symbol->method->cname);
+ break;
+ default:
+ fprintf (generator->c_file, "%s", expr->str);
+ break;
+ }
+}
+
+static void
+vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+ 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_INVOCATION:
+ vala_code_generator_process_invocation (generator, expr);
+ break;
+ case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
+ vala_code_generator_process_member_access (generator, expr);
+ break;
+ case VALA_EXPRESSION_TYPE_PARENTHESIZED:
+ vala_code_generator_process_parenthesized_expression (generator, expr);
+ break;
+ case VALA_EXPRESSION_TYPE_LITERAL_INTEGER:
+ case VALA_EXPRESSION_TYPE_LITERAL_STRING:
+ vala_code_generator_process_literal (generator, expr);
+ break;
+ case VALA_EXPRESSION_TYPE_SIMPLE_NAME:
+ vala_code_generator_process_simple_name (generator, expr);
+ break;
+ }
+}
+
+static void
+vala_code_generator_process_variable_declaration (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+ ValaSymbol *sym = stmt->variable_declaration->type->symbol;
+
+ char *decl_string = get_cname_for_type_symbol (sym, stmt->location);
+
+ fprintf (generator->c_file, "\t%s%s", decl_string, stmt->variable_declaration->declarator->name);
+
+ ValaExpression *expr = stmt->variable_declaration->declarator->initializer;
+ if (expr != NULL) {
+ fprintf (generator->c_file, " = ");
+ vala_code_generator_process_expression (generator, expr);
+ }
+
+ fprintf (generator->c_file, ";\n");
+
+ 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 (ValaCodeGenerator *generator, ValaStatement *stmt);
+
+static void
+vala_code_generator_process_block (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+ GList *l;
+
+ fprintf (generator->c_file, "{\n");
+
+ for (l = stmt->block.statements; l != NULL; l = l->next) {
+ vala_code_generator_process_statement (generator, l->data);
+ }
+
+ fprintf (generator->c_file, "}\n");
+}
+
+static void
+vala_code_generator_process_return_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+ GList *l;
+
+ fprintf (generator->c_file, "\treturn ");
+ vala_code_generator_process_expression (generator, stmt->expr);
+ fprintf (generator->c_file, ";\n");
+}
+
+static void
+vala_code_generator_process_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+ switch (stmt->type) {
+ case VALA_STATEMENT_TYPE_BLOCK:
+ vala_code_generator_process_block (generator, stmt);
+ break;
+ case VALA_STATEMENT_TYPE_EXPRESSION:
+ fprintf (generator->c_file, "\t");
+ vala_code_generator_process_expression (generator, stmt->expr);
+ fprintf (generator->c_file, ";\n");
+ break;
+ case VALA_STATEMENT_TYPE_RETURN:
+ vala_code_generator_process_return_statement (generator, stmt);
+ break;
+ case VALA_STATEMENT_TYPE_VARIABLE_DECLARATION:
+ vala_code_generator_process_variable_declaration (generator, stmt);
+ break;
+ default:
+ fprintf (generator->c_file, "\t;\n");
+ }
+}
+
static void
vala_code_generator_process_methods2 (ValaCodeGenerator *generator, ValaClass *class)
{
fprintf (generator->c_file, "%s\n", method->cdecl1);
fprintf (generator->c_file, "%s\n", method->cdecl2);
- fprintf (generator->c_file, "{\n");
- fprintf (generator->c_file, "}\n");
+
+ if (method->body != NULL) {
+ generator->sym = vala_symbol_new (VALA_SYMBOL_TYPE_BLOCK);
+ generator->sym->stmt = method->body;
+
+ ValaSymbol *sym;
+ GList *pl;
+
+ for (pl = method->formal_parameters; pl != NULL; pl = pl->next) {
+ ValaFormalParameter *param = pl->data;
+
+ sym = vala_symbol_new (VALA_SYMBOL_TYPE_LOCAL_VARIABLE);
+ g_hash_table_insert (generator->sym->symbol_table, param->name, sym);
+ sym->typeref = param->type;
+ }
+
+ vala_code_generator_process_block (generator, method->body);
+ }
+
fprintf (generator->c_file, "\n");
}
fprintf (generator->h_file, "\n");
current_class->base_types = $3;
current_class->location = current_location (@2);
current_class->namespace = current_namespace;
+ current_class->cname = g_strdup_printf ("%s%s", current_namespace->name, current_class->name);
current_class->lower_case_cname = camel_case_to_lower_case (current_class->name);
current_class->upper_case_cname = camel_case_to_upper_case (current_class->name);
current_namespace->classes = g_list_append (current_namespace->classes, current_class);
{
$$ = g_new0 (ValaStatement, 1);
$$->type = VALA_STATEMENT_TYPE_BLOCK;
+ $$->location = current_location (@1);
$$->block.statements = $2;
}
;
{
$$ = g_new0 (ValaStatement, 1);
$$->type = VALA_STATEMENT_TYPE_VARIABLE_DECLARATION;
+ $$->location = current_location (@1);
$$->variable_declaration = $1;;
}
;
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_ADDITIVE;
+ $$->location = current_location (@1);
$$->additive.left = $1;
$$->additive.op = VALA_OP_TYPE_PLUS;
$$->additive.right = $3;
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_LITERAL_INTEGER;
+ $$->location = current_location (@1);
$$->str = $1;
}
| LITERAL_STRING
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_LITERAL_STRING;
+ $$->location = current_location (@1);
$$->str = $1;
}
;
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_SIMPLE_NAME;
+ $$->location = current_location (@1);
$$->str = $1;
}
;
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_PARENTHESIZED;
+ $$->location = current_location (@1);
$$->inner = $2;
}
;
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_MEMBER_ACCESS;
+ $$->location = current_location (@1);
$$->member_access.left = $1;
$$->member_access.right = $3;
}
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_INVOCATION;
+ $$->location = current_location (@1);
$$->invocation.call = $1;
$$->invocation.argument_list = $3;
}
{
$$ = g_new0 (ValaStatement, 1);
$$->type = VALA_STATEMENT_TYPE_EXPRESSION;
+ $$->location = current_location (@1);
$$->expr = $1;
}
;
{
$$ = g_new0 (ValaExpression, 1);
$$->type = VALA_EXPRESSION_TYPE_ASSIGNMENT;
+ $$->location = current_location (@1);
$$->assignment.left = $1;
$$->assignment.right = $3;
}
{
$$ = g_new0 (ValaStatement, 1);
$$->type = VALA_STATEMENT_TYPE_RETURN;
+ $$->location = current_location (@1);
$$->expr = $2;
}
;
%%
extern FILE *yyin;
+extern int yylineno;
void yyerror (YYLTYPE *locp, const char *s)
{
printf ("Couldn't open source file: %s.\n", source_file->filename);
return;
}
+
+ /* restart line counter on each file */
+ yylineno = 1;
+
yyparse ();
fclose (yyin);
yyin = NULL;