From 3c1619c183b5758147962d4fcbafe1b2893cca8d Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Mon, 24 Apr 2006 06:58:11 +0000 Subject: [PATCH] set token location, support OPEN_PARENS, CLOSE_PARENS, SEMICOLON, PUBLIC, MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2006-04-24 Jürg Billeter * valac/scanner.l: set token location, support OPEN_PARENS, CLOSE_PARENS, SEMICOLON, PUBLIC, STATIC * valac/parser.y: save symbol location, output exact error location, support method declarations * valac/context.h: add ValaLocation, ValaMethod, and ValaFormalParameter structs, add location to ValaClass and ValaTypeReference structs * valac/context.c: output error location, support method declarations * valac/generator.c: support method declarations * valac/driver.c: add comment * tests/test-004.vala: test method declaration svn path=/trunk/; revision=3 --- vala/ChangeLog | 13 ++++ vala/tests/test-004.vala | 9 +++ vala/valac/context.c | 75 +++++++++++++++------ vala/valac/context.h | 36 ++++++++++ vala/valac/driver.c | 1 + vala/valac/generator.c | 166 ++++++++++++++++++++++++++++++++++++++++++----- vala/valac/parser.y | 162 ++++++++++++++++++++++++++++++++++++++++++--- vala/valac/scanner.l | 26 +++++--- 8 files changed, 431 insertions(+), 57 deletions(-) create mode 100644 vala/tests/test-004.vala diff --git a/vala/ChangeLog b/vala/ChangeLog index 9af11ba..019cd38 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,16 @@ +2006-04-24 Jürg Billeter + + * valac/scanner.l: set token location, support OPEN_PARENS, + CLOSE_PARENS, SEMICOLON, PUBLIC, STATIC + * valac/parser.y: save symbol location, output exact error location, + support method declarations + * valac/context.h: add ValaLocation, ValaMethod, and ValaFormalParameter + structs, add location to ValaClass and ValaTypeReference structs + * valac/context.c: output error location, support method declarations + * valac/generator.c: support method declarations + * valac/driver.c: add comment + * tests/test-004.vala: test method declaration + 2006-04-22 Jürg Billeter * valac/scanner.l: support DOT, COLON, and COMMA diff --git a/vala/tests/test-004.vala b/vala/tests/test-004.vala new file mode 100644 index 0000000..7375568 --- /dev/null +++ b/vala/tests/test-004.vala @@ -0,0 +1,9 @@ +namespace Maman { + class Bar { + public void do_action () { + } + } + + class SubBar : Bar { + } +} diff --git a/vala/valac/context.c b/vala/valac/context.c index 481e860..baa534d 100644 --- a/vala/valac/context.c +++ b/vala/valac/context.c @@ -60,6 +60,18 @@ vala_symbol_new (ValaSymbolType type) } static void +err (ValaLocation *location, const char *format, ...) +{ + va_list args; + va_start (args, format); + fprintf (stderr, "%s:%d:%d: ", location->source_file->filename, location->lineno, location->colno); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + va_end (args); + exit (1); +} + +static void vala_context_add_symbols_from_namespace (ValaContext *context, ValaNamespace *namespace) { ValaSymbol *ns_symbol, *class_symbol; @@ -82,8 +94,7 @@ vala_context_add_symbols_from_namespace (ValaContext *context, ValaNamespace *na class_symbol = g_hash_table_lookup (ns_symbol->symbol_table, class->name); if (class_symbol != NULL) { - fprintf (stderr, "Error: Class '%s.%s' defined twice.\n", namespace->name, class->name); - exit (1); + err (class->location, "error: class ´%s.%s´ already defined", namespace->name, class->name); } class_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_CLASS); @@ -101,6 +112,11 @@ vala_context_add_fundamental_symbols (ValaContext *context) context->root = vala_symbol_new (VALA_SYMBOL_TYPE_ROOT); + /* void */ + symbol = vala_symbol_new (VALA_SYMBOL_TYPE_VOID); + g_hash_table_insert (context->root->symbol_table, "void", symbol); + + /* namespace G */ namespace = g_new0 (ValaNamespace, 1); namespace->name = g_strdup ("G"); namespace->lower_case_cname = g_strdup ("g_"); @@ -155,9 +171,11 @@ vala_context_resolve_type_reference (ValaContext *context, ValaNamespace *namesp /* FIXME: look in namespaces specified by using directives */ - if (type_symbol == NULL) { + if (type_symbol != NULL) { + type_reference->namespace_name = ""; + } else { /* specified namespace not found */ - fprintf (stderr, "Error: Specified type '%s' not found.\n", type_reference->type_name); + err (type_reference->location, "error: specified type ´%s´ not found", type_reference->type_name); exit (1); } } else { @@ -165,49 +183,61 @@ vala_context_resolve_type_reference (ValaContext *context, ValaNamespace *namesp ns_symbol = g_hash_table_lookup (context->root->symbol_table, type_reference->namespace_name); if (ns_symbol == NULL) { /* specified namespace not found */ - fprintf (stderr, "Error: Specified namespace '%s' not found.\n", type_reference->namespace_name); - exit (1); + 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); if (type_symbol == NULL) { /* specified namespace not found */ - fprintf (stderr, "Error: Specified type '%s' not found in namespace '%s'.\n", type_reference->type_name, type_reference->namespace_name); - exit (1); + 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_CLASS) { + if (type_symbol->type == VALA_SYMBOL_TYPE_VOID || + type_symbol->type == VALA_SYMBOL_TYPE_CLASS) { type_reference->symbol = type_symbol; } else { - fprintf (stderr, "Error: Specified symbol '%s' is not a type.\n", type_reference->type_name); - exit (1); + err (type_reference->location, "error: specified symbol ´%s´ is not a type", type_reference->type_name); + } +} + +static void +vala_context_resolve_types_in_method (ValaContext *context, ValaMethod *method) +{ + GList *l; + + vala_context_resolve_type_reference (context, method->class->namespace, method->return_type); + + for (l = method->formal_parameters; l != NULL; l = l->next) { + ValaFormalParameter *formal_parameter = l->data; + + vala_context_resolve_type_reference (context, method->class->namespace, formal_parameter->type); + if (formal_parameter->type->symbol->type == VALA_SYMBOL_TYPE_VOID) { + err (formal_parameter->location, "error: method parameters cannot be of type `void`"); + } } } static void -vala_context_resolve_types_in_class (ValaContext *context, ValaNamespace *namespace, ValaClass *class) +vala_context_resolve_types_in_class (ValaContext *context, ValaClass *class) { GList *l; for (l = class->base_types; l != NULL; l = l->next) { ValaTypeReference *type_reference = l->data; - vala_context_resolve_type_reference (context, namespace, type_reference); + vala_context_resolve_type_reference (context, class->namespace, type_reference); if (type_reference->symbol->type == VALA_SYMBOL_TYPE_CLASS) { if (class->base_class != NULL) { - fprintf (stderr, "Error: More than one base class specified in class '%s.%s'.\n", class->namespace->name, class->name); - exit (1); + err (type_reference->location, "error: more than one base class specified in class ´%s.%s´", class->namespace->name, class->name); } class->base_class = type_reference->symbol->class; if (class->base_class == class) { - fprintf (stderr, "Error: '%s.%s' cannot be subtype of '%s.%s'.\n", class->namespace->name, class->name, class->namespace->name, class->name); - exit (1); + err (type_reference->location, "error: ´%s.%s´ cannot be subtype of ´%s.%s´", class->namespace->name, class->name, class->namespace->name, class->name); } /* FIXME: check whether base_class is not a subtype of class */ } else { - fprintf (stderr, "Error: '%s.%s' cannot be subtype of '%s.%s'.\n", class->namespace->name, class->name, type_reference->symbol->class->namespace->name, type_reference->symbol->class->name); - exit (1); + err (type_reference->location, "error: ´%s.%s´ cannot be subtype of ´%s.%s´", class->namespace->name, class->name, type_reference->namespace_name, type_reference->type_name); } } @@ -215,6 +245,11 @@ vala_context_resolve_types_in_class (ValaContext *context, ValaNamespace *namesp ValaSymbol *symbol = g_hash_table_lookup (context->root->symbol_table, "object"); class->base_class = symbol->class; } + + for (l = class->methods; l != NULL; l = l->next) { + ValaMethod *method = l->data; + vala_context_resolve_types_in_method (context, method); + } } static void @@ -225,7 +260,7 @@ vala_context_resolve_types_in_namespace (ValaContext *context, ValaNamespace *na for (cl = namespace->classes; cl != NULL; cl = cl->next) { ValaClass *class = cl->data; - vala_context_resolve_types_in_class (context, namespace, class); + vala_context_resolve_types_in_class (context, class); } } diff --git a/vala/valac/context.h b/vala/valac/context.h index 92daabe..b1c3ecb 100644 --- a/vala/valac/context.h +++ b/vala/valac/context.h @@ -23,20 +23,30 @@ #include typedef enum _ValaSymbolType ValaSymbolType; +typedef enum _ValaMethodFlags ValaMethodFlags; typedef struct _ValaContext ValaContext; typedef struct _ValaSymbol ValaSymbol; typedef struct _ValaSourceFile ValaSourceFile; +typedef struct _ValaLocation ValaLocation; typedef struct _ValaNamespace ValaNamespace; typedef struct _ValaClass ValaClass; +typedef struct _ValaMethod ValaMethod; typedef struct _ValaTypeReference ValaTypeReference; +typedef struct _ValaFormalParameter ValaFormalParameter; enum _ValaSymbolType { VALA_SYMBOL_TYPE_ROOT, VALA_SYMBOL_TYPE_NAMESPACE, + VALA_SYMBOL_TYPE_VOID, VALA_SYMBOL_TYPE_CLASS, }; +enum _ValaMethodFlags { + VALA_METHOD_PUBLIC = 0x01, + VALA_METHOD_STATIC = 0x02, +}; + struct _ValaContext { GList *source_files; ValaSymbol *root; @@ -56,6 +66,12 @@ struct _ValaSourceFile { GList *namespaces; }; +struct _ValaLocation { + ValaSourceFile *source_file; + int lineno; + int colno; +}; + struct _ValaNamespace { char *name; ValaSymbol *symbol; @@ -66,19 +82,39 @@ struct _ValaNamespace { struct _ValaClass { char *name; + ValaLocation *location; ValaNamespace *namespace; ValaClass *base_class; GList *base_types; + GList *methods; char *lower_case_cname; char *upper_case_cname; }; +struct _ValaMethod { + char *name; + ValaLocation *location; + ValaClass *class; + ValaTypeReference *return_type; + GList *formal_parameters; + ValaMethodFlags modifiers; + char *cdecl1; + char *cdecl2; +}; + struct _ValaTypeReference { char *namespace_name; char *type_name; + ValaLocation *location; ValaSymbol *symbol; }; +struct _ValaFormalParameter { + char *name; + ValaTypeReference *type; + ValaLocation *location; +}; + ValaContext *vala_context_new (); void vala_context_free (ValaContext *context); void vala_context_parse (ValaContext *context); diff --git a/vala/valac/driver.c b/vala/valac/driver.c index 63d72e0..ce6d085 100644 --- a/vala/valac/driver.c +++ b/vala/valac/driver.c @@ -34,6 +34,7 @@ driver_main (char **sources, char *directory) * Copy namespace and type names from parse tree into symbol tables * Resolve type references in parse tree * Load metadata from parse tree into symbol tables + * Add memory management calls * Generate code */ diff --git a/vala/valac/generator.c b/vala/valac/generator.c index 26153b6..4498668 100644 --- a/vala/valac/generator.c +++ b/vala/valac/generator.c @@ -55,7 +55,112 @@ filename_to_define (const char *filename) } static void -vala_code_generator_process_class (ValaCodeGenerator *generator, ValaClass *class) +vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *class) +{ + GList *l; + + char *camel_case; + char *ns_lower; + char *ns_upper; + + ValaNamespace *namespace = class->namespace; + + ns_lower = namespace->lower_case_cname; + ns_upper = namespace->upper_case_cname; + + char *lower_case = class->lower_case_cname; + char *upper_case = class->upper_case_cname; + + 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 *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)); + } + + 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)); + } + + if (parameter_list == NULL) { + parameters = g_strdup (""); + } else { + parameters = parameter_list->data; + GList *sl; + for (sl = parameter_list->next; sl != NULL; sl = sl->next) { + parameters = g_strdup_printf ("%s, %s", parameters, sl->data); + g_free (sl->data); + } + g_list_free (parameter_list); + } + + method->cdecl2 = g_strdup_printf ("%s (%s)", method_cname, parameters); + + if (method->modifiers & VALA_METHOD_PUBLIC) { + method->cdecl1 = g_strdup (method_return_type_cname); + } else { + method->cdecl1 = g_strdup_printf ("static %s", method_return_type_cname); + fprintf (generator->c_file, "%s %s;\n", method->cdecl1, method->cdecl2); + } + + } + fprintf (generator->c_file, "\n"); +} + +static void +vala_code_generator_process_methods2 (ValaCodeGenerator *generator, ValaClass *class) +{ + GList *l; + + char *camel_case; + char *ns_lower; + char *ns_upper; + + ValaNamespace *namespace = class->namespace; + + ns_lower = namespace->lower_case_cname; + ns_upper = namespace->upper_case_cname; + + char *lower_case = class->lower_case_cname; + char *upper_case = class->upper_case_cname; + + for (l = class->methods; l != NULL; l = l->next) { + ValaMethod *method = l->data; + + if (method->modifiers & VALA_METHOD_PUBLIC) { + fprintf (generator->h_file, "%s %s;\n", method->cdecl1, method->cdecl2); + } + + 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"); + 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"); + + 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 +vala_code_generator_process_class1 (ValaCodeGenerator *generator, ValaClass *class) { ValaNamespace *namespace = class->namespace; @@ -83,7 +188,27 @@ vala_code_generator_process_class (ValaCodeGenerator *generator, ValaClass *clas fprintf (generator->h_file, "typedef struct _%s %s;\n", camel_case, camel_case); fprintf (generator->h_file, "typedef struct _%sClass %sClass;\n", camel_case, camel_case); fprintf (generator->h_file, "\n"); + + vala_code_generator_process_methods1 (generator, class); +} + +static void +vala_code_generator_process_class2 (ValaCodeGenerator *generator, ValaClass *class) +{ + ValaNamespace *namespace = class->namespace; + + char *camel_case; + char *ns_lower; + char *ns_upper; + + camel_case = g_strdup_printf ("%s%s", namespace->name, class->name); + ns_lower = namespace->lower_case_cname; + ns_upper = namespace->upper_case_cname; + + char *lower_case = class->lower_case_cname; + char *upper_case = class->upper_case_cname; + /* structs */ fprintf (generator->h_file, "struct _%s {\n", camel_case); fprintf (generator->h_file, "\t%s%s parent;\n", class->base_class->namespace->name, class->base_class->name); fprintf (generator->h_file, "};\n"); @@ -98,19 +223,8 @@ vala_code_generator_process_class (ValaCodeGenerator *generator, ValaClass *clas fprintf (generator->h_file, "GType %s%s_get_type () G_GNUC_CONST;\n", ns_lower, lower_case); fprintf (generator->h_file, "\n"); - /* constructors */ - fprintf (generator->c_file, "static void\n"); - fprintf (generator->c_file, "%s%s_init (%s *self)\n", ns_lower, lower_case, camel_case); - 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 (%sClass *klass)\n", ns_lower, lower_case, camel_case); - fprintf (generator->c_file, "{\n"); - fprintf (generator->c_file, "}\n"); - fprintf (generator->c_file, "\n"); - + vala_code_generator_process_methods2 (generator, class); + /* type initialization function */ fprintf (generator->c_file, "GType\n"); fprintf (generator->c_file, "%s%s_get_type ()\n", ns_lower, lower_case); @@ -139,11 +253,20 @@ vala_code_generator_process_class (ValaCodeGenerator *generator, ValaClass *clas } static void -vala_code_generator_process_namespace (ValaCodeGenerator *generator, ValaNamespace *namespace) +vala_code_generator_process_namespace1 (ValaCodeGenerator *generator, ValaNamespace *namespace) { GList *l; for (l = namespace->classes; l != NULL; l = l->next) { - vala_code_generator_process_class (generator, l->data); + vala_code_generator_process_class1 (generator, l->data); + } +} + +static void +vala_code_generator_process_namespace2 (ValaCodeGenerator *generator, ValaNamespace *namespace) +{ + GList *l; + for (l = namespace->classes; l != NULL; l = l->next) { + vala_code_generator_process_class2 (generator, l->data); } } @@ -186,10 +309,17 @@ vala_code_generator_process_source_file (ValaCodeGenerator *generator, ValaSourc fprintf (generator->c_file, "#include \"%s\"\n", g_path_get_basename (h_filename)); fprintf (generator->c_file, "\n"); - vala_code_generator_process_namespace (generator, source_file->root_namespace); + vala_code_generator_process_namespace1 (generator, source_file->root_namespace); GList *l; + + for (l = source_file->namespaces; l != NULL; l = l->next) { + vala_code_generator_process_namespace1 (generator, l->data); + } + + vala_code_generator_process_namespace1 (generator, source_file->root_namespace); + for (l = source_file->namespaces; l != NULL; l = l->next) { - vala_code_generator_process_namespace (generator, l->data); + vala_code_generator_process_namespace2 (generator, l->data); } fprintf (generator->h_file, "G_END_DECLS\n"); diff --git a/vala/valac/parser.y b/vala/valac/parser.y index 4dd5975..7b36ec5 100644 --- a/vala/valac/parser.y +++ b/vala/valac/parser.y @@ -23,6 +23,7 @@ %{ #include #include +#include #include @@ -86,8 +87,21 @@ camel_case_to_upper_case (const char *camel_case) return str; } -ValaSourceFile *current_source_file; -ValaNamespace *current_namespace; +static ValaSourceFile *current_source_file; +static ValaNamespace *current_namespace; +static ValaClass *current_class; +static ValaMethod *current_method; + +ValaLocation *get_location (int lineno, int colno) +{ + ValaLocation *loc = g_new0 (ValaLocation, 1); + loc->source_file = current_source_file; + loc->lineno = lineno; + loc->colno = colno; + return loc; +} + +#define current_location(token) get_location (token.first_line, token.first_column) %} %defines @@ -96,25 +110,39 @@ ValaNamespace *current_namespace; %pure_parser %glr-parser %union { + int num; char *str; GList *list; ValaTypeReference *type_reference; + ValaFormalParameter *formal_parameter; } %token OPEN_BRACE "{" %token CLOSE_BRACE "}" +%token OPEN_PARENS "(" +%token CLOSE_PARENS ")" %token DOT "." %token COLON ":" %token COMMA "," +%token SEMICOLON ";" %token NAMESPACE "namespace" %token CLASS "class" +%token PUBLIC "public" +%token STATIC "static" %token IDENTIFIER "identifier" %type opt_class_base %type class_base %type type_list %type type_name +%type opt_formal_parameter_list +%type formal_parameter_list +%type fixed_parameters +%type fixed_parameter +%type opt_method_modifiers +%type method_modifiers +%type method_modifier %% @@ -179,13 +207,14 @@ type_declaration class_declaration : CLASS IDENTIFIER opt_class_base { - ValaClass *class = g_new0 (ValaClass, 1); - class->name = g_strdup ($2); - class->base_types = $3; - class->namespace = current_namespace; - class->lower_case_cname = camel_case_to_lower_case (class->name); - class->upper_case_cname = camel_case_to_upper_case (class->name); - current_namespace->classes = g_list_append (current_namespace->classes, class); + current_class = g_new0 (ValaClass, 1); + current_class->name = g_strdup ($2); + current_class->base_types = $3; + current_class->location = current_location (@2); + current_class->namespace = current_namespace; + 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); } class_body ; @@ -224,6 +253,7 @@ type_name { ValaTypeReference *type_reference = g_new0 (ValaTypeReference, 1); type_reference->type_name = g_strdup ($1); + type_reference->location = current_location (@1); $$ = type_reference; } | IDENTIFIER DOT IDENTIFIER @@ -231,11 +261,123 @@ type_name 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; } ; class_body + : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE + ; + +opt_class_member_declarations + : /* empty */ + | class_member_declarations + ; + +class_member_declarations + : class_member_declaration + | class_member_declarations class_member_declaration + ; + +class_member_declaration + : method_declaration + ; + +method_declaration + : method_header method_body + ; + +method_header + : opt_method_modifiers type_name IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + { + current_method = g_new0 (ValaMethod, 1); + current_method->name = g_strdup ($3); + current_method->class = current_class; + current_method->return_type = $2; + current_method->formal_parameters = $5; + current_method->modifiers = $1; + current_method->location = current_location (@3); + + current_class->methods = g_list_append (current_class->methods, current_method); + } + ; + +opt_method_modifiers + : /* empty */ + { + $$ = 0; + } + | method_modifiers + { + $$ = $1; + } + ; + +method_modifiers + : method_modifier + { + $$ = $1; + } + | method_modifiers method_modifier + { + $$ = $1 | $2; + } + ; + +method_modifier + : PUBLIC + { + $$ = VALA_METHOD_PUBLIC; + } + | STATIC + { + $$ = VALA_METHOD_STATIC; + } + ; + +opt_formal_parameter_list + : /* empty */ + { + $$ = NULL; + } + | formal_parameter_list + { + $$ = $1; + } + ; + +formal_parameter_list + : fixed_parameters + ; + +fixed_parameters + : fixed_parameter + { + $$ = g_list_append (NULL, $1); + } + | fixed_parameters COMMA fixed_parameter + { + $$ = g_list_append ($1, $3); + } + ; + +fixed_parameter + : type_name IDENTIFIER + { + $$ = g_new0 (ValaFormalParameter, 1); + $$->type = $1; + $$->name = $2; + $$->location = current_location (@2); + } + ; + +method_body + : block + | SEMICOLON + ; + +block : OPEN_BRACE CLOSE_BRACE ; @@ -245,7 +387,7 @@ extern FILE *yyin; void yyerror (YYLTYPE *locp, const char *s) { - printf ("%d: %s\n", locp->first_line, s); + printf ("%s:%d:%d-%d: %s\n", current_source_file->filename, locp->first_line, locp->first_column, locp->last_column, s); } void vala_parser_parse (ValaSourceFile *source_file) diff --git a/vala/valac/scanner.l b/vala/valac/scanner.l index 1d2a636..0a41db5 100644 --- a/vala/valac/scanner.l +++ b/vala/valac/scanner.l @@ -23,6 +23,8 @@ %{ #include "context.h" #include "parser.h" + +#define uploc { yylloc->first_column = yylloc->last_column + 1; yylloc->last_column += strlen (yytext); } %} %option yylineno @@ -32,15 +34,21 @@ %% -"{" { return OPEN_BRACE; } -"}" { return CLOSE_BRACE; } -"." { return DOT; } -":" { return COLON; } -"," { return COMMA; } +"{" { uploc; return OPEN_BRACE; } +"}" { uploc; return CLOSE_BRACE; } +"(" { uploc; return OPEN_PARENS; } +")" { uploc; return CLOSE_PARENS; } +"." { uploc; return DOT; } +":" { uploc; return COLON; } +"," { uploc; return COMMA; } +";" { uploc; return SEMICOLON; } -"namespace" { return NAMESPACE; } -"class" { return CLASS; } +"namespace" { uploc; return NAMESPACE; } +"class" { uploc; return CLASS; } +"public" { uploc; return PUBLIC; } +"static" { uploc; return STATIC; } -[[:alnum:]_]+ { yylval->str = strdup (yytext); return IDENTIFIER; } +[[:alnum:]_]+ { uploc; yylval->str = strdup (yytext); return IDENTIFIER; } -[ \t\n]+ /* eat up whitespace */ +[ \t]+ { uploc; /* eat up whitespace */ } +[\n]+ { yylloc->first_line = yylloc->last_line = yylineno; yylloc->first_column = 1; yylloc->last_column = 0; } -- 2.7.4