From eba85accb7d719808c26d2624ed04d81c4b7c3ab Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Sun, 13 Apr 2008 09:25:25 +0000 Subject: [PATCH] Replace generated Vala scanner and parser by handwritten classes 2008-04-13 Juerg Billeter * vala/Makefile.am, vala/valaassignment.vala, vala/valabinaryexpression.vala, vala/valaclass.vala, vala/valanamespace.vala, vala/valaparser.vala, vala/valascanner.vala, vala/valascope.vala, vala/valasourcefile.vala, vala/valasourcelocation.vala, vala/valatokentype.vala, vala/valatuple.vala, vala/valaunaryexpression.vala, vala/valaunresolvedtype.vala: Replace generated Vala scanner and parser by handwritten classes svn path=/trunk/; revision=1194 --- ChangeLog | 12 + vala/Makefile.am | 9 +- vala/parser.y | 4563 ---------------------------------------- vala/scanner.l | 209 -- vala/valaassignment.vala | 1 + vala/valabinaryexpression.vala | 1 + vala/valaclass.vala | 6 + vala/valanamespace.vala | 54 + vala/valaparser.vala | 2658 ++++++++++++++++++++++- vala/valascanner.vala | 774 +++++++ vala/valascope.vala | 8 +- vala/valasourcefile.vala | 17 + vala/valasourcelocation.vala | 39 + vala/valatokentype.vala | 256 +++ vala/valatuple.vala | 47 + vala/valaunaryexpression.vala | 1 + vala/valaunresolvedtype.vala | 4 + 17 files changed, 3844 insertions(+), 4815 deletions(-) delete mode 100644 vala/parser.y delete mode 100644 vala/scanner.l create mode 100644 vala/valascanner.vala create mode 100644 vala/valasourcelocation.vala create mode 100644 vala/valatokentype.vala create mode 100644 vala/valatuple.vala diff --git a/ChangeLog b/ChangeLog index 108ca3c..4787fdc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2008-04-13 Jürg Billeter + * vala/Makefile.am, vala/valaassignment.vala, + vala/valabinaryexpression.vala, vala/valaclass.vala, + vala/valanamespace.vala, vala/valaparser.vala, + vala/valascanner.vala, vala/valascope.vala, + vala/valasourcefile.vala, vala/valasourcelocation.vala, + vala/valatokentype.vala, vala/valatuple.vala, + vala/valaunaryexpression.vala, vala/valaunresolvedtype.vala: + + Replace generated Vala scanner and parser by handwritten classes + +2008-04-13 Jürg Billeter + * vapi/glib-2.0.vapi: add GEnumClass and GEnumValue bindings 2008-04-13 Jürg Billeter diff --git a/vala/Makefile.am b/vala/Makefile.am index b52b2fe..7b6f0ef 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -7,8 +7,7 @@ AM_CPPFLAGS = \ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \ $(NULL) -BUILT_SOURCES = parser.h vala.vala.stamp -AM_YFLAGS = -d +BUILT_SOURCES = vala.vala.stamp noinst_LTLIBRARIES = \ libvalacore.la @@ -106,6 +105,7 @@ libvalacore_la_VALASOURCES = \ valareferencetype.vala \ valareport.vala \ valareturnstatement.vala \ + valascanner.vala \ valascope.vala \ valasemanticanalyzer.vala \ valasignal.vala \ @@ -113,6 +113,7 @@ libvalacore_la_VALASOURCES = \ valasizeofexpression.vala \ valasourcefile.vala \ valasourcefilecycle.vala \ + valasourcelocation.vala \ valasourcereference.vala \ valastatement.vala \ valastringliteral.vala \ @@ -123,7 +124,9 @@ libvalacore_la_VALASOURCES = \ valasymbol.vala \ valasymbolresolver.vala \ valathrowstatement.vala \ + valatokentype.vala \ valatrystatement.vala \ + valatuple.vala \ valatypecheck.vala \ valatypeofexpression.vala \ valatypeparameter.vala \ @@ -139,8 +142,6 @@ libvalacore_la_VALASOURCES = \ $(NULL) libvalacore_la_SOURCES = \ - parser.y \ - scanner.l \ vala.h \ vala.vala.stamp \ $(libvalacore_la_VALASOURCES:.vala=.c) \ diff --git a/vala/parser.y b/vala/parser.y deleted file mode 100644 index fc7b3ac..0000000 --- a/vala/parser.y +++ /dev/null @@ -1,4563 +0,0 @@ -/* parser.y - * - * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter - * Raffaele Sandrini - */ - -%{ -#include -#include -#include - -#include - -#include "vala.h" -#include "parser.h" - -#define src(l) (vala_source_reference_new (current_source_file, l.first_line, l.first_column, l.last_line, l.last_column)) - -#define src_com(l,c) (vala_source_reference_new_with_comment (current_source_file, l.first_line, l.first_column, l.last_line, l.last_column, c)) - -static ValaCodeContext *context; -static ValaSourceFile *current_source_file; -static GList *symbol_stack; -static GList *scope_stack; - -typedef enum { - VALA_MODIFIER_NONE, - VALA_MODIFIER_ABSTRACT = 1 << 0, - VALA_MODIFIER_OVERRIDE = 1 << 1, - VALA_MODIFIER_STATIC = 1 << 2, - VALA_MODIFIER_VIRTUAL = 1 << 3, - VALA_MODIFIER_VOLATILE = 1 << 4, - VALA_MODIFIER_INLINE = 1 << 5 -} ValaModifier; - -int yylex (YYSTYPE *yylval_param, YYLTYPE *yylloc_param, ValaParser *parser); -static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); - -static void push_symbol (ValaSymbol *symbol); -static ValaSymbol *pop_symbol (void); - -static gboolean check_is_namespace (ValaSymbol *symbol, ValaSourceReference *src); -static gboolean check_is_class (ValaSymbol *symbol, ValaSourceReference *src); -static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src); -%} - -%defines -%locations -%pure-parser -%parse-param {ValaParser *parser} -%lex-param {ValaParser *parser} -%error-verbose -%union { - int num; - char *str; - GList *list; - ValaUnresolvedSymbol *unresolved_symbol; - ValaDataType *type_reference; - ValaExpression *expression; - ValaStatement *statement; - ValaBlock *block; - ValaInterface *interface; - ValaEnumValue *enum_value; - ValaErrorCode *error_code; - ValaConstant *constant; - ValaField *field; - ValaMethod *method; - ValaFormalParameter *formal_parameter; - ValaProperty *property; - ValaPropertyAccessor *property_accessor; - ValaSignal *signal; - ValaConstructor *constructor; - ValaDestructor *destructor; - ValaLocalVariableDeclaration *local_variable_declaration; - ValaVariableDeclarator *variable_declarator; - ValaTypeParameter *type_parameter; - ValaMemberInitializer *member_initializer; - ValaAttribute *attribute; - ValaNamedArgument *named_argument; - ValaSwitchSection *switch_section; - ValaSwitchLabel *switch_label; - ValaCatchClause *catch_clause; -} - -%token OPEN_BRACE "{" -%token CLOSE_BRACE "}" -%token OPEN_PARENS "(" -%token OPEN_CAST_PARENS "cast (" -%token CLOSE_PARENS ")" -%token BRACKET_PAIR "[]" -%token OPEN_ARRAY_TYPE_BRACKET "array [" -%token OPEN_BRACKET "[" -%token CLOSE_BRACKET "]" -%token ELLIPSIS "..." -%token DOT "." -%token COLON ":" -%token COMMA "," -%token SEMICOLON ";" -%token HASH "#" -%token INTERR "?" -%token NULLABLE_INTERR "nullable ?" - -%token ASSIGN_BITWISE_OR "|=" -%token ASSIGN_BITWISE_AND "&=" -%token ASSIGN_BITWISE_XOR "^=" -%token ASSIGN_ADD "+=" -%token ASSIGN_SUB "-=" -%token ASSIGN_MUL "*=" -%token ASSIGN_DIV "/=" -%token ASSIGN_PERCENT "%=" -%token ASSIGN_SHIFT_LEFT "<<=" -%token ASSIGN_SHIFT_RIGHT ">>=" - -%token OP_INC "++" -%token OP_DEC "--" -%token OP_EQ "==" -%token OP_NE "!=" -%token OP_SHIFT_LEFT "<<" -%token OP_SHIFT_RIGHT ">>" -%token OP_LE "<=" -%token OP_GE ">=" -%token LAMBDA "=>" -%token GENERIC_LT "generic <" -%token OP_LT "<" -%token OP_GT ">" -%token OP_NEG "!" -%token CARRET "^" -%token BITWISE_OR "|" -%token BITWISE_AND "&" -%token OP_OR "||" -%token OP_AND "&&" -%token TILDE "~" - -%token OP_PTR "->" - -%token ASSIGN "=" -%token PLUS "+" -%token MINUS "-" -%token STAR "*" -%token DIV "/" -%token PERCENT "%" - -%token ABSTRACT "abstract" -%token AS "as" -%token BASE "base" -%token BREAK "break" -%token CASE "case" -%token CATCH "catch" -%token CLASS "class" -%token CONST "const" -%token CONSTRUCT "construct" -%token CONTINUE "continue" -%token DEFAULT "default" -%token DELEGATE "delegate" -%token DELETE "delete" -%token DO "do" -%token ELSE "else" -%token ENSURES "ensures" -%token ENUM "enum" -%token ERRORDOMAIN "errordomain" -%token VALA_FALSE "false" -%token FINALLY "finally" -%token FOR "for" -%token FOREACH "foreach" -%token GET "get" -%token IF "if" -%token IN "in" -%token INLINE "inline" -%token INTERFACE "interface" -%token IS "is" -%token LOCK "lock" -%token NAMESPACE "namespace" -%token NEW "new" -%token VALA_NULL "null" -%token OUT "out" -%token OVERRIDE "override" -%token PRIVATE "private" -%token PROTECTED "protected" -%token PUBLIC "public" -%token REF "ref" -%token REQUIRES "requires" -%token RETURN "return" -%token SET "set" -%token SIGNAL "signal" -%token SIZEOF "sizeof" -%token STATIC "static" -%token STRUCT "struct" -%token SWITCH "switch" -%token THIS "this" -%token THROW "throw" -%token THROWS "throws" -%token VALA_TRUE "true" -%token TRY "try" -%token TYPEOF "typeof" -%token USING "using" -%token VAR "var" -%token VIRTUAL "virtual" -%token VOID "void" -%token VOLATILE "volatile" -%token WEAK "weak" -%token WHILE "while" - -%token IDENTIFIER "identifier" -%token INTEGER_LITERAL "integer" -%token REAL_LITERAL "real" -%token CHARACTER_LITERAL "character" -%token STRING_LITERAL "string" - -%type comment -%type identifier -%type identifier_or_keyword -%type literal -%type boolean_literal -%type stars -%type symbol_name -%type type_name -%type type -%type opt_argument_list -%type argument_list -%type argument -%type primary_expression -%type array_creation_expression -%type size_specifier_list -%type opt_initializer -%type opt_rank_specifier -%type rank_specifier -%type opt_bracket_pair -%type bracket_pair -%type opt_comma_list -%type comma_list -%type primary_no_array_creation_expression -%type simple_name -%type parenthesized_expression -%type member_access -%type pointer_member_access -%type invocation_expression -%type element_access -%type expression_list -%type this_access -%type base_access -%type post_increment_expression -%type post_decrement_expression -%type object_creation_expression -%type opt_object_initializer -%type object_initializer -%type member_initializer_list -%type member_initializer -%type sizeof_expression -%type typeof_expression -%type unary_expression -%type pre_increment_expression -%type pre_decrement_expression -%type cast_expression -%type pointer_indirection_expression -%type addressof_expression -%type multiplicative_expression -%type additive_expression -%type shift_expression -%type relational_expression -%type equality_expression -%type and_expression -%type exclusive_or_expression -%type inclusive_or_expression -%type in_expression -%type conditional_and_expression -%type conditional_or_expression -%type conditional_expression -%type lambda_expression -%type opt_lambda_parameter_list -%type lambda_parameter_list -%type assignment -%type assignment_operator -%type opt_expression -%type expression -%type statement -%type embedded_statement -%type block -%type opt_statement_list -%type statement_list -%type empty_statement -%type declaration_statement -%type local_variable_declaration -%type local_variable_type -%type opt_op_neg -%type opt_any_interr -%type opt_nullable_interr -%type expression_statement -%type statement_expression -%type selection_statement -%type if_statement -%type switch_statement -%type switch_block -%type opt_switch_sections -%type switch_sections -%type switch_section -%type switch_labels -%type switch_label -%type iteration_statement -%type while_statement -%type do_statement -%type for_statement -%type opt_statement_expression_list -%type statement_expression_list -%type foreach_statement -%type jump_statement -%type break_statement -%type continue_statement -%type return_statement -%type throw_statement -%type try_statement -%type catch_clauses -%type specific_catch_clauses -%type specific_catch_clause -%type opt_general_catch_clause -%type general_catch_clause -%type opt_finally_clause -%type finally_clause -%type lock_statement -%type delete_statement -%type opt_name_specifier -%type name_specifier -%type opt_access_modifier -%type access_modifier -%type opt_modifiers -%type modifiers -%type modifier -%type opt_class_base -%type class_base -%type type_list -%type property_declaration -%type opt_get_accessor_declaration -%type get_accessor_declaration -%type opt_set_accessor_declaration -%type set_accessor_declaration -%type opt_default_value -%type default_value -%type constant_declaration -%type field_declaration -%type variable_declarators -%type variable_declarator -%type initializer -%type opt_variable_initializer_list -%type variable_initializer_list -%type variable_initializer -%type method_declaration -%type method_header -%type method_body -%type opt_formal_parameter_list -%type formal_parameter_list -%type opt_construct -%type fixed_parameters -%type fixed_parameter -%type opt_throws_declaration -%type throws_declaration -%type opt_requires_declarations -%type requires_declarations -%type requires_declaration -%type opt_ensures_declarations -%type ensures_declarations -%type ensures_declaration -%type signal_declaration -%type constructor_declaration -%type destructor_declaration -%type opt_attributes -%type attributes -%type attribute_sections -%type attribute_section -%type attribute_list -%type attribute -%type attribute_name -%type opt_named_argument_list -%type named_argument_list -%type named_argument -%type opt_type_parameter_list -%type type_parameter_list -%type type_parameters -%type type_parameter -%type opt_type_argument_list -%type type_argument_list -%type type_arguments -%type type_argument -%type member_name - -/* expect shift/reduce conflict on if/else */ -%expect 1 - -%start compilation_unit - -%% - -opt_comma - : /* empty */ - | COMMA - ; - -/* identifiers never conflict with context-specific keywords get, set, requires, or ensures */ -identifier - : IDENTIFIER - | GET { $$ = g_strdup ("get"); } - | SET { $$ = g_strdup ("set"); } - | REQUIRES { $$ = g_strdup ("requires"); } - | ENSURES { $$ = g_strdup ("ensures"); } - ; - -/* identifiers never conflict with context-specific keywords get, set, requires, or ensures */ -identifier_or_keyword - : IDENTIFIER - | ABSTRACT { $$ = g_strdup ("abstract"); } - | AS { $$ = g_strdup ("as"); } - | BASE { $$ = g_strdup ("base"); } - | BREAK { $$ = g_strdup ("break"); } - | CASE { $$ = g_strdup ("case"); } - | CATCH { $$ = g_strdup ("catch"); } - | CLASS { $$ = g_strdup ("class"); } - | CONST { $$ = g_strdup ("const"); } - | CONSTRUCT { $$ = g_strdup ("construct"); } - | CONTINUE { $$ = g_strdup ("continue"); } - | DEFAULT { $$ = g_strdup ("default"); } - | DELEGATE { $$ = g_strdup ("delegate"); } - | DELETE { $$ = g_strdup ("delete"); } - | DO { $$ = g_strdup ("do"); } - | ELSE { $$ = g_strdup ("else"); } - | ENSURES { $$ = g_strdup ("ensures"); } - | ENUM { $$ = g_strdup ("enum"); } - | ERRORDOMAIN { $$ = g_strdup ("errordomain"); } - | VALA_FALSE { $$ = g_strdup ("false"); } - | FINALLY { $$ = g_strdup ("finally"); } - | FOR { $$ = g_strdup ("for"); } - | FOREACH { $$ = g_strdup ("foreach"); } - | GET { $$ = g_strdup ("get"); } - | IF { $$ = g_strdup ("if"); } - | IN { $$ = g_strdup ("in"); } - | INLINE { $$ = g_strdup ("inline"); } - | INTERFACE { $$ = g_strdup ("interface"); } - | IS { $$ = g_strdup ("is"); } - | LOCK { $$ = g_strdup ("lock"); } - | NAMESPACE { $$ = g_strdup ("namespace"); } - | NEW { $$ = g_strdup ("new"); } - | VALA_NULL { $$ = g_strdup ("null"); } - | OUT { $$ = g_strdup ("out"); } - | OVERRIDE { $$ = g_strdup ("override"); } - | PRIVATE { $$ = g_strdup ("private"); } - | PROTECTED { $$ = g_strdup ("protected"); } - | PUBLIC { $$ = g_strdup ("public"); } - | REF { $$ = g_strdup ("ref"); } - | REQUIRES { $$ = g_strdup ("requires"); } - | RETURN { $$ = g_strdup ("return"); } - | SET { $$ = g_strdup ("set"); } - | SIGNAL { $$ = g_strdup ("signal"); } - | SIZEOF { $$ = g_strdup ("sizeof"); } - | STATIC { $$ = g_strdup ("static"); } - | STRUCT { $$ = g_strdup ("struct"); } - | SWITCH { $$ = g_strdup ("switch"); } - | THIS { $$ = g_strdup ("this"); } - | THROW { $$ = g_strdup ("throw"); } - | THROWS { $$ = g_strdup ("throws"); } - | VALA_TRUE { $$ = g_strdup ("true"); } - | TRY { $$ = g_strdup ("try"); } - | TYPEOF { $$ = g_strdup ("typeof"); } - | USING { $$ = g_strdup ("using"); } - | VAR { $$ = g_strdup ("var"); } - | VIRTUAL { $$ = g_strdup ("virtual"); } - | VOID { $$ = g_strdup ("void"); } - | VOLATILE { $$ = g_strdup ("volatile"); } - | WEAK { $$ = g_strdup ("weak"); } - | WHILE { $$ = g_strdup ("while"); } - ; - -literal - : boolean_literal - | INTEGER_LITERAL - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_integer_literal (context, $1, src)); - g_object_unref (src); - g_free ($1); - } - | REAL_LITERAL - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_real_literal (context, $1, src)); - g_free ($1); - g_object_unref (src); - } - | CHARACTER_LITERAL - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_character_literal (context, $1, src)); - g_object_unref (src); - g_free ($1); - } - | STRING_LITERAL - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_string_literal (context, $1, src)); - g_object_unref (src); - g_free ($1); - } - | VALA_NULL - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_null_literal (context, src)); - g_object_unref (src); - } - ; - -boolean_literal - : VALA_TRUE - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_boolean_literal (context, TRUE, src)); - g_object_unref (src); - } - | VALA_FALSE - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_boolean_literal (context, FALSE, src)); - g_object_unref (src); - } - ; - -compilation_unit - : opt_using_directives opt_outer_declarations - ; - -symbol_name - : identifier - { - ValaSourceReference *src = src(@1); - $$ = vala_unresolved_symbol_new (NULL, $1, src); - g_free ($1); - g_object_unref (src); - } - | symbol_name DOT identifier - { - ValaSourceReference *src = src(@1); - $$ = vala_unresolved_symbol_new ($1, $3, src); - g_free ($3); - g_object_unref (src); - } - ; - -type_name - : symbol_name opt_type_argument_list - { - GList *l; - ValaSourceReference *src = src(@1); - $$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_symbol ($1, src)); - g_object_unref ($1); - g_object_unref (src); - for (l = $2; l != NULL; l = l->next) { - vala_data_type_add_type_argument (VALA_DATA_TYPE ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($2); - } - ; - -stars - : STAR - { - $$ = 1; - } - | stars STAR - { - $$ = $1 + 1; - } - ; - -type - : type_name opt_rank_specifier opt_op_neg opt_any_interr - { - $$ = $1; - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2); - if ($4) { - vala_data_type_set_nullable ($$, TRUE); - vala_data_type_set_requires_null_check ($$, TRUE); - } - } - | WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr - { - $$ = $2; - vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); - if ($5) { - vala_data_type_set_nullable ($$, TRUE); - vala_data_type_set_requires_null_check ($$, TRUE); - } - } - | type_name opt_rank_specifier opt_op_neg opt_any_interr HASH - { - $$ = $1; - vala_data_type_set_transfers_ownership ($$, TRUE); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2); - if ($4) { - vala_data_type_set_nullable ($$, TRUE); - vala_data_type_set_requires_null_check ($$, TRUE); - } - } - | REF type_name opt_rank_specifier opt_op_neg opt_any_interr - { - $$ = $2; - vala_data_type_set_is_ref ($$, TRUE); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); - if ($5) { - vala_data_type_set_nullable ($$, TRUE); - vala_data_type_set_requires_null_check ($$, TRUE); - } - } - | OUT type_name opt_rank_specifier opt_op_neg opt_any_interr - { - $$ = $2; - vala_data_type_set_is_out ($$, TRUE); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); - if ($5) { - vala_data_type_set_nullable ($$, TRUE); - vala_data_type_set_requires_null_check ($$, TRUE); - } - } - | OUT WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr - { - $$ = $3; - vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE); - vala_data_type_set_is_out ($$, TRUE); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $4); - if ($6) { - vala_data_type_set_nullable ($$, TRUE); - vala_data_type_set_requires_null_check ($$, TRUE); - } - } - | type_name stars opt_rank_specifier - { - $$ = $1; - vala_unresolved_type_set_pointer_level (VALA_UNRESOLVED_TYPE ($$), $2); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); - } - | VOID - { - $$ = VALA_DATA_TYPE (vala_void_type_new ()); - } - | VOID stars - { - int pointer_level; - - $$ = VALA_DATA_TYPE (vala_void_type_new ()); - - for (pointer_level = $2; pointer_level > 0; pointer_level--) { - ValaDataType *base_type = $$; - $$ = VALA_DATA_TYPE (vala_pointer_type_new (base_type)); - g_object_unref (base_type); - } - } - ; - -opt_argument_list - : /* empty */ - { - $$ = NULL; - } - | argument_list - ; - -argument_list - : argument - { - $$ = g_list_append (NULL, $1); - } - | argument_list COMMA argument - { - $$ = g_list_append ($1, $3); - } - ; - -argument - : expression - ; - -primary_expression - : primary_no_array_creation_expression - | array_creation_expression - ; - -array_creation_expression - : NEW member_name size_specifier_list opt_initializer - { - GList *l; - ValaSourceReference *src = src(@2); - ValaDataType *t = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression (VALA_EXPRESSION ($2))); - $$ = VALA_EXPRESSION (vala_code_context_create_array_creation_expression (context, t, g_list_length ($3), VALA_INITIALIZER_LIST ($4), src)); - g_object_unref (t); - for (l = $3; l != NULL; l = l->next) { - vala_array_creation_expression_append_size (VALA_ARRAY_CREATION_EXPRESSION ($$), VALA_EXPRESSION (l->data)); - g_object_unref (l->data); - } - g_list_free ($3); - g_object_unref (src); - g_object_unref ($2); - if ($4 != NULL) { - g_object_unref ($4); - } - } - | NEW member_name rank_specifier initializer - { - ValaSourceReference *src = src(@2); - ValaDataType *t = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression (VALA_EXPRESSION ($2))); - $$ = VALA_EXPRESSION (vala_code_context_create_array_creation_expression (context, t, $3, VALA_INITIALIZER_LIST ($4), src)); - g_object_unref (t); - g_object_unref (src); - g_object_unref ($2); - g_object_unref ($4); - } - ; - -size_specifier_list - : OPEN_BRACKET expression_list CLOSE_BRACKET - { - $$ = $2; - } - ; - -opt_initializer - : /* empty */ - { - $$ = NULL; - } - | initializer - ; - -opt_rank_specifier - : /* empty */ - { - $$ = 0; - } - | rank_specifier - ; - -rank_specifier - : OPEN_BRACKET opt_comma_list CLOSE_BRACKET - { - $$ = $2; - } - | bracket_pair - ; - -opt_bracket_pair - : /* empty */ - { - $$ = 0; - } - | bracket_pair - ; - -bracket_pair - : OPEN_ARRAY_TYPE_BRACKET opt_comma_list CLOSE_BRACKET - { - $$ = $2; - } - ; - -opt_comma_list - : /* empty */ - { - $$ = 1; - } - | comma_list - ; - -comma_list - : COMMA - { - $$ = 2; - } - | comma_list COMMA - { - $$ = $1 + 1; - } - ; - -primary_no_array_creation_expression - : literal - | simple_name - | parenthesized_expression - | member_access - | pointer_member_access - | invocation_expression - | element_access - | this_access - | base_access - | post_increment_expression - | post_decrement_expression - | object_creation_expression - | sizeof_expression - | typeof_expression - ; - -simple_name - : identifier opt_type_argument_list - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_member_access (context, NULL, $1, src)); - g_free ($1); - g_object_unref (src); - - if ($2 != NULL) { - GList *l; - for (l = $2; l != NULL; l = l->next) { - vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($2); - } - } - ; - -parenthesized_expression - : OPEN_PARENS expression CLOSE_PARENS - { - ValaSourceReference *src = src(@2); - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = VALA_EXPRESSION (vala_code_context_create_parenthesized_expression (context, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - ; - -member_access - : primary_expression DOT identifier_or_keyword opt_type_argument_list - { - ValaSourceReference *src = src(@3); - $$ = VALA_EXPRESSION (vala_code_context_create_member_access (context, $1, $3, src)); - g_object_unref ($1); - g_free ($3); - g_object_unref (src); - - if ($4 != NULL) { - GList *l; - for (l = $4; l != NULL; l = l->next) { - vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($4); - } - } - ; - -pointer_member_access - : primary_expression OP_PTR identifier opt_type_argument_list - { - ValaSourceReference *src = src(@3); - $$ = VALA_EXPRESSION (vala_code_context_create_member_access_pointer (context, $1, $3, src)); - g_object_unref ($1); - g_free ($3); - g_object_unref (src); - - if ($4 != NULL) { - GList *l; - for (l = $4; l != NULL; l = l->next) { - vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($4); - } - } - ; - -invocation_expression - : primary_expression open_parens opt_argument_list CLOSE_PARENS - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_invocation_expression (context, $1, src)); - g_object_unref ($1); - g_object_unref (src); - - if ($3 != NULL) { - GList *l; - for (l = $3; l != NULL; l = l->next) { - if (l->data == NULL) { - // error in subexpression - } else { - vala_invocation_expression_add_argument (VALA_INVOCATION_EXPRESSION ($$), l->data); - g_object_unref (l->data); - } - } - g_list_free ($3); - } - } - ; - -element_access - : primary_no_array_creation_expression OPEN_BRACKET expression_list CLOSE_BRACKET - { - GList *l; - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_element_access (context, $1, src)); - for (l = $3; l != NULL; l = l->next) { - if (l->data == NULL) { - // error in subexpression - } else { - vala_element_access_append_index (VALA_ELEMENT_ACCESS ($$), VALA_EXPRESSION (l->data)); - g_object_unref (l->data); - } - } - g_list_free ($3); - g_object_unref ($1); - g_object_unref (src); - } - ; - -expression_list - : expression - { - $$ = g_list_append (NULL, $1); - } - | expression_list COMMA expression - { - $$ = g_list_append ($1, $3); - } - ; - -this_access - : THIS - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_member_access (context, NULL, "this", src)); - g_object_unref (src); - } - ; - -base_access - : BASE - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_base_access (context, src)); - g_object_unref (src); - } - ; - -post_increment_expression - : primary_expression OP_INC - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_postfix_expression (context, $1, TRUE, src)); - g_object_unref (src); - g_object_unref ($1); - } - ; - -post_decrement_expression - : primary_expression OP_DEC - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_postfix_expression (context, $1, FALSE, src)); - g_object_unref (src); - g_object_unref ($1); - } - ; - -object_creation_expression - : NEW member_name open_parens opt_argument_list CLOSE_PARENS opt_object_initializer - { - ValaSourceReference *src = src(@2); - ValaObjectCreationExpression *expr; - vala_member_access_set_creation_member (VALA_MEMBER_ACCESS ($2), TRUE); - expr = vala_code_context_create_object_creation_expression (context, VALA_MEMBER_ACCESS ($2), src); - g_object_unref ($2); - g_object_unref (src); - - if ($4 != NULL) { - GList *l; - for (l = $4; l != NULL; l = l->next) { - vala_object_creation_expression_add_argument (expr, l->data); - g_object_unref (l->data); - } - g_list_free ($4); - } - - if ($6 != NULL) { - GList *l; - for (l = $6; l != NULL; l = l->next) { - vala_object_creation_expression_add_member_initializer (expr, l->data); - g_object_unref (l->data); - } - g_list_free ($6); - } - - $$ = VALA_EXPRESSION (expr); - } - ; - -opt_object_initializer - : /* empty */ - { - $$ = NULL; - } - | object_initializer - ; - -object_initializer - : OPEN_BRACE member_initializer_list CLOSE_BRACE - { - $$ = $2; - } - ; - -member_initializer_list - : member_initializer - { - $$ = g_list_append (NULL, $1); - } - | member_initializer_list COMMA member_initializer - { - $$ = g_list_append ($1, $3); - } - ; - -member_initializer - : IDENTIFIER ASSIGN expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = vala_member_initializer_new ($1, $3, src); - g_object_unref (src); - g_free ($1); - g_object_unref ($3); - } - } - ; - -sizeof_expression - : SIZEOF open_parens type_name CLOSE_PARENS - { - if ($3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_sizeof_expression (context, $3, src)); - g_object_unref ($3); - g_object_unref (src); - } - } - -typeof_expression - : TYPEOF open_parens type CLOSE_PARENS - { - if ($3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_typeof_expression (context, $3, src)); - g_object_unref ($3); - g_object_unref (src); - } - } - -unary_expression - : primary_expression - | PLUS unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_PLUS, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | MINUS unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_MINUS, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | OP_NEG unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_LOGICAL_NEGATION, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | TILDE unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_BITWISE_COMPLEMENT, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | pre_increment_expression - | pre_decrement_expression - | REF unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_REF, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | OUT unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_OUT, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | HASH unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_reference_transfer_expression (context, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - | cast_expression - | pointer_indirection_expression - | addressof_expression - ; - -pre_increment_expression - : OP_INC unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_INCREMENT, $2, src)); - g_object_unref ($2); - g_object_unref (src); - } - } - ; - -pre_decrement_expression - : OP_DEC unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_unary_expression (context, VALA_UNARY_OPERATOR_DECREMENT, $2, src)); - g_object_unref ($2); - g_object_unref (src); - } - } - ; - -cast_expression - : OPEN_CAST_PARENS type CLOSE_PARENS unary_expression - { - if ($2 == NULL || $4 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_cast_expression (context, $4, $2, src, FALSE)); - g_object_unref (src); - g_object_unref ($2); - g_object_unref ($4); - } - } - ; - -pointer_indirection_expression - : STAR unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_pointer_indirection (context, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - ; - -addressof_expression - : BITWISE_AND unary_expression - { - if ($2 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_addressof_expression (context, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - } - ; - -multiplicative_expression - : unary_expression - | multiplicative_expression STAR unary_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_MUL, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | multiplicative_expression DIV unary_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_DIV, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | multiplicative_expression PERCENT unary_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_MOD, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -additive_expression - : multiplicative_expression - | additive_expression PLUS multiplicative_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_PLUS, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | additive_expression MINUS multiplicative_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_MINUS, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -shift_expression - : additive_expression - | shift_expression OP_SHIFT_LEFT additive_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_SHIFT_LEFT, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - /* don't use two OP_GT to resolve parse conflicts - * stacked generics won't be that common in vala */ - | shift_expression OP_SHIFT_RIGHT additive_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_SHIFT_RIGHT, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -relational_expression - : shift_expression - | relational_expression OP_LT shift_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_LESS_THAN, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | relational_expression OP_GT shift_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_GREATER_THAN, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | relational_expression OP_LE shift_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_LESS_THAN_OR_EQUAL, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | relational_expression OP_GE shift_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_GREATER_THAN_OR_EQUAL, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | relational_expression IS type_name - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_type_check (context, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | relational_expression AS type_name - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_cast_expression (context, $1, $3, src, TRUE)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -equality_expression - : relational_expression - | equality_expression OP_EQ relational_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_EQUALITY, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - | equality_expression OP_NE relational_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_INEQUALITY, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -and_expression - : equality_expression - | and_expression BITWISE_AND equality_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_BITWISE_AND, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -exclusive_or_expression - : and_expression - | exclusive_or_expression CARRET and_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_BITWISE_XOR, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -inclusive_or_expression - : exclusive_or_expression - | inclusive_or_expression BITWISE_OR exclusive_or_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_BITWISE_OR, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -in_expression - : inclusive_or_expression - | in_expression IN inclusive_or_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_IN, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - - -conditional_and_expression - : in_expression - | conditional_and_expression OP_AND in_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_AND, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -conditional_or_expression - : conditional_and_expression - | conditional_or_expression OP_OR conditional_and_expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_binary_expression (context, VALA_BINARY_OPERATOR_OR, $1, $3, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -conditional_expression - : conditional_or_expression - | conditional_or_expression INTERR expression COLON expression - { - if ($1 == NULL || $3 == NULL || $5 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_conditional_expression (context, $1, $3, $5, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - g_object_unref ($5); - } - } - ; - -lambda_expression - : OPEN_PARENS opt_lambda_parameter_list CLOSE_PARENS LAMBDA expression - { - if ($5 == NULL) { - // error in lambda expression - $$ = NULL; - } else { - ValaSourceReference *src = src(@4); - $$ = VALA_EXPRESSION (vala_code_context_create_lambda_expression (context, $5, src)); - if ($2 != NULL) { - GList *l; - for (l = $2; l != NULL; l = l->next) { - vala_lambda_expression_add_parameter (VALA_LAMBDA_EXPRESSION ($$), l->data); - g_free (l->data); - } - g_list_free ($2); - } - g_object_unref ($5); - g_object_unref (src); - } - } - | identifier LAMBDA expression - { - if ($3 == NULL) { - // error in lambda expression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_lambda_expression (context, $3, src)); - g_object_unref ($3); - g_object_unref (src); - vala_lambda_expression_add_parameter (VALA_LAMBDA_EXPRESSION ($$), $1); - g_free ($1); - } - } - | OPEN_PARENS opt_lambda_parameter_list CLOSE_PARENS LAMBDA block - { - if ($5 == NULL) { - // error in lambda block - $$ = NULL; - } else { - ValaSourceReference *src = src(@4); - $$ = VALA_EXPRESSION (vala_code_context_create_lambda_expression_with_statement_body (context, VALA_BLOCK ($5), src)); - if ($2 != NULL) { - GList *l; - for (l = $2; l != NULL; l = l->next) { - vala_lambda_expression_add_parameter (VALA_LAMBDA_EXPRESSION ($$), l->data); - g_free (l->data); - } - g_list_free ($2); - } - g_object_unref ($5); - g_object_unref (src); - } - } - | identifier LAMBDA block - { - if ($3 == NULL) { - // error in lambda block - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_lambda_expression_with_statement_body (context, VALA_BLOCK ($3), src)); - g_object_unref ($3); - g_object_unref (src); - vala_lambda_expression_add_parameter (VALA_LAMBDA_EXPRESSION ($$), $1); - g_free ($1); - } - } - ; - -opt_lambda_parameter_list - : /* empty */ - { - $$ = NULL; - } - | lambda_parameter_list - ; - -lambda_parameter_list - : identifier COMMA identifier - { - $$ = g_list_append (NULL, $1); - $$ = g_list_append ($$, $3); - } - | lambda_parameter_list COMMA identifier - { - $$ = g_list_append ($1, $3); - } - ; - -assignment - : unary_expression assignment_operator expression - { - if ($1 == NULL || $3 == NULL) { - // error in subexpression - $$ = NULL; - } else { - ValaSourceReference *src = src(@2); - $$ = VALA_EXPRESSION (vala_code_context_create_assignment (context, $1, $3, $2, src)); - g_object_unref (src); - g_object_unref ($1); - g_object_unref ($3); - } - } - ; - -assignment_operator - : ASSIGN - { - $$ = VALA_ASSIGNMENT_OPERATOR_SIMPLE; - } - | ASSIGN_BITWISE_OR - { - $$ = VALA_ASSIGNMENT_OPERATOR_BITWISE_OR; - } - | ASSIGN_BITWISE_AND - { - $$ = VALA_ASSIGNMENT_OPERATOR_BITWISE_AND; - } - | ASSIGN_BITWISE_XOR - { - $$ = VALA_ASSIGNMENT_OPERATOR_BITWISE_XOR; - } - | ASSIGN_ADD - { - $$ = VALA_ASSIGNMENT_OPERATOR_ADD; - } - | ASSIGN_SUB - { - $$ = VALA_ASSIGNMENT_OPERATOR_SUB; - } - | ASSIGN_MUL - { - $$ = VALA_ASSIGNMENT_OPERATOR_MUL; - } - | ASSIGN_DIV - { - $$ = VALA_ASSIGNMENT_OPERATOR_DIV; - } - | ASSIGN_PERCENT - { - $$ = VALA_ASSIGNMENT_OPERATOR_PERCENT; - } - | ASSIGN_SHIFT_LEFT - { - $$ = VALA_ASSIGNMENT_OPERATOR_SHIFT_LEFT; - } - | ASSIGN_SHIFT_RIGHT - { - $$ = VALA_ASSIGNMENT_OPERATOR_SHIFT_RIGHT; - } - ; - -opt_expression - : /* empty */ - { - $$ = NULL; - } - | expression - ; - -expression - : conditional_expression - | lambda_expression - | assignment - | error - { - $$ = NULL; - } - ; - -statement - : declaration_statement - | block - { - $$ = VALA_STATEMENT ($1); - } - | empty_statement - | expression_statement - | selection_statement - | iteration_statement - | jump_statement - | try_statement - | lock_statement - | delete_statement - ; - -embedded_statement - : block - | empty_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | expression_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | selection_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | iteration_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | jump_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | try_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | lock_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - | delete_statement - { - ValaSourceReference *src = src(@1); - if ($1 == NULL) { - // error in subexpression - $$ = NULL; - } else { - $$ = vala_code_context_create_block (context, src); - vala_block_add_statement ($$, $1); - g_object_unref ($1); - g_object_unref (src); - } - } - ; - -block - : OPEN_BRACE opt_statement_list CLOSE_BRACE - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_block (context, src); - if ($2 != NULL) { - GList *l; - for (l = $2; l != NULL; l = l->next) { - if (l->data == NULL) { - // error in subexpression - } else { - vala_block_add_statement ($$, l->data); - g_object_unref (l->data); - } - } - g_list_free ($2); - } - g_object_unref (src); - } - ; - -opt_statement_list - : /* empty */ - { - $$ = NULL; - } - | statement_list - ; - -statement_list - : statement - { - $$ = g_list_append (NULL, $1); - } - | statement_list statement - { - $$ = g_list_append ($1, $2); - } - ; - -empty_statement - : SEMICOLON - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_empty_statement (context, src)); - g_object_unref (src); - } - ; - -declaration_statement - : comment local_variable_declaration SEMICOLON - { - ValaSourceReference *src = src_com(@2, $1); - $$ = VALA_STATEMENT (vala_code_context_create_declaration_statement (context, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - ; - -local_variable_declaration - : local_variable_type variable_declarators - { - GList *l; - ValaSourceReference *src = src(@2); - $$ = vala_code_context_create_local_variable_declaration (context, $1, src); - g_object_unref (src); - for (l = $2; l != NULL; l = l->next) { - ValaVariableDeclarator *decl = l->data; - ValaDataType *type = vala_data_type_copy ($1); - vala_variable_declarator_set_type_reference (decl, type); - g_object_unref (type); - vala_local_variable_declaration_add_declarator ($$, decl); - g_object_unref (decl); - } - g_list_free ($2); - g_object_unref ($1); - } - | VAR variable_declarators - { - GList *l; - ValaSourceReference *src = src(@2); - $$ = vala_code_context_create_local_variable_declaration_var_type (context, src); - g_object_unref (src); - for (l = $2; l != NULL; l = l->next) { - vala_local_variable_declaration_add_declarator ($$, l->data); - g_object_unref (l->data); - } - g_list_free ($2); - } - ; - -/* don't use type to prevent reduce/reduce conflict */ -local_variable_type - : primary_expression opt_bracket_pair opt_op_neg opt_nullable_interr - { - ValaSourceReference *src = src(@1); - $$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($1)); - g_object_unref ($1); - g_object_unref (src); - vala_data_type_set_takes_ownership ($$, TRUE); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2); - vala_data_type_set_nullable ($$, TRUE); - } - | primary_expression stars - { - ValaSourceReference *src = src(@1); - $$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($1)); - g_object_unref ($1); - g_object_unref (src); - vala_unresolved_type_set_pointer_level (VALA_UNRESOLVED_TYPE ($$), $2); - } - | WEAK primary_expression opt_bracket_pair opt_op_neg opt_nullable_interr - { - ValaSourceReference *src = src(@2); - $$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($2)); - g_object_unref ($2); - g_object_unref (src); - vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); - vala_data_type_set_nullable ($$, TRUE); - } - | VOID - { - ValaSourceReference *src = src(@1); - $$ = VALA_DATA_TYPE (vala_void_type_new ()); - g_object_unref (src); - } - | VOID stars - { - int pointer_level; - ValaSourceReference *src = src(@1); - $$ = VALA_DATA_TYPE (vala_void_type_new ()); - g_object_unref (src); - - for (pointer_level = $2; pointer_level > 0; pointer_level--) { - ValaDataType *base_type = $$; - $$ = VALA_DATA_TYPE (vala_pointer_type_new (base_type)); - g_object_unref (base_type); - } - } - ; - -opt_op_neg - : /* empty */ - { - $$ = FALSE; - } - | OP_NEG - { - $$ = TRUE; - } - ; - -opt_any_interr - : /* empty */ - { - $$ = FALSE; - } - | INTERR - { - $$ = TRUE; - } - | NULLABLE_INTERR - { - $$ = TRUE; - } - ; - -opt_nullable_interr - : /* empty */ - { - $$ = FALSE; - } - | NULLABLE_INTERR - { - $$ = TRUE; - } - ; - -expression_statement - : comment statement_expression SEMICOLON - { - ValaSourceReference *src = src_com(@2, $1); - $$ = VALA_STATEMENT (vala_code_context_create_expression_statement (context, $2, src)); - g_object_unref (src); - g_object_unref ($2); - } - ; - -statement_expression - : invocation_expression - | object_creation_expression - | assignment - | post_increment_expression - | post_decrement_expression - | pre_increment_expression - | pre_decrement_expression - ; - -selection_statement - : if_statement - | switch_statement - ; - -if_statement - : comment IF open_parens expression CLOSE_PARENS embedded_statement - { - ValaSourceReference *src; - - if ($4 == NULL || $6 == NULL) { - // error in subexpression - $$ = NULL; - } else { - src = src_com(@4, $1); - $$ = VALA_STATEMENT (vala_code_context_create_if_statement (context, $4, $6, NULL, src)); - g_object_unref (src); - g_object_unref ($4); - g_object_unref ($6); - } - } - | comment IF open_parens expression CLOSE_PARENS embedded_statement ELSE embedded_statement - { - ValaSourceReference *src; - - if ($4 == NULL || $6 == NULL || $8 == NULL) { - // error in subexpression - $$ = NULL; - } else { - src = src_com(@4, $1); - $$ = VALA_STATEMENT (vala_code_context_create_if_statement (context, $4, $6, $8, src)); - g_object_unref (src); - g_object_unref ($4); - g_object_unref ($6); - g_object_unref ($8); - } - } - ; - -switch_statement - : comment SWITCH open_parens expression CLOSE_PARENS switch_block - { - ValaSourceReference *src = src_com(@4, $1); - $$ = VALA_STATEMENT (vala_code_context_create_switch_statement (context, $4, src)); - g_object_unref ($4); - g_object_unref (src); - - if ($6 != NULL) { - GList *l; - for (l = $6; l != NULL; l = l->next) { - vala_switch_statement_add_section (VALA_SWITCH_STATEMENT ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($6); - } - } - ; - -switch_block - : OPEN_BRACE opt_switch_sections CLOSE_BRACE - { - $$ = $2; - } - ; - -opt_switch_sections - : /* empty */ - { - $$ = NULL; - } - | switch_sections - ; - -switch_sections - : switch_section - { - $$ = g_list_append (NULL, $1); - } - | switch_sections switch_section - { - $$ = g_list_append ($1, $2); - } - ; - -switch_section - : comment switch_labels statement_list - { - GList *l; - ValaSourceReference *src = src_com(@2, $1); - $$ = vala_code_context_create_switch_section (context, src); - g_object_unref (src); - - for (l = $2; l != NULL; l = l->next) { - vala_switch_section_add_label ($$, l->data); - g_object_unref (l->data); - } - g_list_free ($2); - for (l = $3; l != NULL; l = l->next) { - vala_switch_section_add_statement ($$, l->data); - g_object_unref (l->data); - } - g_list_free ($3); - } - ; - -switch_labels - : switch_label - { - $$ = g_list_append (NULL, $1); - } - | switch_labels switch_label - { - $$ = g_list_append ($1, $2); - } - ; - -switch_label - : CASE expression COLON - { - ValaSourceReference *src = src(@2); - $$ = vala_code_context_create_switch_label (context, $2, src); - g_object_unref ($2); - g_object_unref (src); - } - | DEFAULT COLON - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_switch_label_with_default (context, src); - g_object_unref (src); - } - ; - -iteration_statement - : while_statement - | do_statement - | for_statement - | foreach_statement - ; - -while_statement - : WHILE open_parens expression CLOSE_PARENS embedded_statement - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_while_statement (context, $3, $5, src)); - g_object_unref (src); - g_object_unref ($3); - g_object_unref ($5); - } - ; - -do_statement - : DO embedded_statement WHILE open_parens expression CLOSE_PARENS SEMICOLON - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_do_statement (context, $2, $5, src)); - g_object_unref ($2); - g_object_unref ($5); - g_object_unref (src); - } - ; - -for_statement - : FOR OPEN_PARENS opt_statement_expression_list SEMICOLON opt_expression SEMICOLON opt_statement_expression_list CLOSE_PARENS embedded_statement - { - GList *l; - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_for_statement (context, $5, $9, src)); - if ($5 != NULL) { - g_object_unref ($5); - } - g_object_unref ($9); - g_object_unref (src); - - if ($3 != NULL) { - for (l = $3; l != NULL; l = l->next) { - vala_for_statement_add_initializer (VALA_FOR_STATEMENT ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($3); - } - if ($7 != NULL) { - for (l = $7; l != NULL; l = l->next) { - vala_for_statement_add_iterator (VALA_FOR_STATEMENT ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($7); - } - } - | FOR OPEN_PARENS local_variable_declaration SEMICOLON opt_expression SEMICOLON opt_statement_expression_list CLOSE_PARENS embedded_statement - { - GeeCollection *decls; - GeeIterator *decls_it; - - ValaDeclarationStatement *decl_statement; - - ValaSourceReference *src = src(@1); - - ValaBlock *block = vala_code_context_create_block (context, src); - - ValaForStatement *for_statement = vala_code_context_create_for_statement (context, $5, $9, src); - if ($5 != NULL) { - g_object_unref ($5); - } - g_object_unref ($9); - - - decls = vala_local_variable_declaration_get_variable_declarators ($3); - decls_it = gee_iterable_iterator (GEE_ITERABLE (decls)); - g_object_unref (decls); - while (gee_iterator_next (decls_it)) { - ValaVariableDeclarator *decl = gee_iterator_get (decls_it); - ValaExpression *init = vala_variable_declarator_get_initializer (decl); - - if (init != NULL) { - ValaSourceReference *decl_src = vala_code_node_get_source_reference (VALA_CODE_NODE (decl)); - ValaMemberAccess *lhs = vala_code_context_create_member_access (context, NULL, vala_symbol_get_name (VALA_SYMBOL (decl)), decl_src); - ValaAssignment *assign = vala_code_context_create_assignment (context, VALA_EXPRESSION (lhs), init, VALA_ASSIGNMENT_OPERATOR_SIMPLE, decl_src); - g_object_unref (lhs); - vala_for_statement_add_initializer (for_statement, VALA_EXPRESSION (assign)); - g_object_unref (assign); - - vala_variable_declarator_set_initializer (decl, NULL); - } - } - g_object_unref (decls_it); - - decl_statement = vala_code_context_create_declaration_statement (context, $3, src); - g_object_unref ($3); - g_object_unref (src); - vala_block_add_statement (block, VALA_STATEMENT (decl_statement)); - g_object_unref (decl_statement); - - if ($7 != NULL) { - GList *l; - for (l = $7; l != NULL; l = l->next) { - vala_for_statement_add_iterator (for_statement, l->data); - g_object_unref (l->data); - } - g_list_free ($7); - } - - vala_block_add_statement (block, VALA_STATEMENT (for_statement)); - - $$ = VALA_STATEMENT (block); - } - ; - -opt_statement_expression_list - : /* empty */ - { - $$ = NULL; - } - | statement_expression_list - ; - -statement_expression_list - : statement_expression - { - $$ = g_list_append (NULL, $1); - } - | statement_expression_list COMMA statement_expression - { - $$ = g_list_append ($1, $3); - } - ; - -foreach_statement - : FOREACH OPEN_PARENS type identifier IN expression CLOSE_PARENS embedded_statement - { - ValaSourceReference *src = src(@3); - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) { - vala_data_type_set_takes_ownership ($3, TRUE); - } - $$ = VALA_STATEMENT (vala_code_context_create_foreach_statement (context, $3, $4, $6, $8, src)); - g_object_unref ($3); - g_free ($4); - g_object_unref ($6); - g_object_unref ($8); - g_object_unref (src); - } - ; - -jump_statement - : break_statement - | continue_statement - | return_statement - | throw_statement - ; - -break_statement - : BREAK SEMICOLON - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_break_statement (context, src)); - g_object_unref (src); - } - ; - -continue_statement - : CONTINUE SEMICOLON - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_continue_statement (context, src)); - g_object_unref (src); - } - ; - -return_statement - : RETURN opt_expression SEMICOLON - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_return_statement (context, $2, src)); - g_object_unref (src); - if ($2 != NULL) { - g_object_unref ($2); - } - } - ; - -throw_statement - : THROW expression SEMICOLON - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_throw_statement (context, $2, src)); - g_object_unref (src); - if ($2 != NULL) { - g_object_unref ($2); - } - } - ; - -try_statement - : TRY block catch_clauses opt_finally_clause - { - GList *l; - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_try_statement (context, $2, $4, src)); - g_object_unref ($2); - if ($4 != NULL) { - g_object_unref ($4); - } - g_object_unref (src); - - for (l = $3; l != NULL; l = l->next) { - vala_try_statement_add_catch_clause (VALA_TRY_STATEMENT ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($3); - } - | TRY block finally_clause - { - ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_code_context_create_try_statement (context, $2, $3, src)); - g_object_unref ($2); - g_object_unref ($3); - g_object_unref (src); - } - ; - -catch_clauses - : specific_catch_clauses opt_general_catch_clause - { - if ($2 != NULL) { - $$ = g_list_append ($1, $2); - } else { - $$ = $1; - } - } - | general_catch_clause - { - $$ = g_list_append (NULL, $1); - } - ; - -specific_catch_clauses - : specific_catch_clause - { - $$ = g_list_append (NULL, $1); - } - | specific_catch_clauses specific_catch_clause - { - $$ = g_list_append ($1, $2); - } - ; - -specific_catch_clause - : CATCH OPEN_PARENS type identifier CLOSE_PARENS block - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_catch_clause (context, $3, $4, VALA_BLOCK ($6), src); - g_object_unref ($3); - g_free ($4); - g_object_unref ($6); - g_object_unref (src); - } - ; - -opt_general_catch_clause - : /* empty */ - { - $$ = NULL; - } - | general_catch_clause - ; - -general_catch_clause - : CATCH block - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_catch_clause (context, NULL, NULL, VALA_BLOCK ($2), src); - g_object_unref ($2); - g_object_unref (src); - } - ; - -opt_finally_clause - : /* empty */ - { - $$ = NULL; - } - | finally_clause - ; - - -finally_clause - : FINALLY block - { - $$ = $2; - } - ; - -lock_statement - : comment LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement - { - ValaSourceReference *src = src_com(@4, $1); - $$ = VALA_STATEMENT (vala_code_context_create_lock_statement (context, $4, $6, src)); - g_object_unref (src); - g_object_unref ($4); - g_object_unref ($6); - } - ; - -delete_statement - : comment DELETE expression SEMICOLON - { - ValaSourceReference *src = src_com(@2, $1); - $$ = VALA_STATEMENT (vala_code_context_create_delete_statement (context, $3, src)); - g_object_unref (src); - g_object_unref ($3); - } - ; - -namespace_declaration - : comment opt_attributes NAMESPACE identifier - { - ValaSourceReference *src = src_com(@4, $1); - ValaSymbol *current_symbol = vala_scope_lookup (scope_stack->data, $4); - if (current_symbol != NULL) { - if (check_is_namespace (current_symbol, src)) { - // merge namespace declarations - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (current_symbol), FALSE); - } - VALA_CODE_NODE (current_symbol)->attributes = $2; - } - } else { - current_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $4, src)); - vala_namespace_set_pkg (VALA_NAMESPACE (current_symbol), vala_source_file_get_pkg (current_source_file)); - VALA_CODE_NODE (current_symbol)->attributes = g_list_concat (VALA_CODE_NODE (current_symbol)->attributes, $2); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (current_symbol)); - } - g_object_unref (src); - g_free ($4); - - push_symbol (current_symbol); - } - namespace_body - { - g_object_unref (pop_symbol ()); - } - ; - -namespace_body - : OPEN_BRACE opt_namespace_member_declarations CLOSE_BRACE - | OPEN_BRACE error CLOSE_BRACE - ; - -opt_name_specifier - : /* empty */ - { - $$ = NULL; - } - | name_specifier - ; - -name_specifier - : DOT identifier - { - $$ = $2; - } - ; - -opt_using_directives - : /* empty */ - | using_directives - ; - -using_directives - : using_directive - | using_directives using_directive - ; - -using_directive - : USING using_list SEMICOLON - ; - -using_list - : using_list COMMA namespace_identifier - | namespace_identifier - ; - -namespace_identifier - : identifier - { - ValaSourceReference *src = src(@1); - ValaNamespaceReference *ns_ref = vala_namespace_reference_new ($1, src); - g_object_unref (src); - g_free ($1); - vala_source_file_add_using_directive (current_source_file, ns_ref); - g_object_unref (ns_ref); - } - ; - -opt_outer_declarations - : /* empty */ - | outer_declarations - ; - -outer_declarations - : outer_declaration - | outer_declarations outer_declaration - ; - -outer_declaration - : namespace_member_declaration - ; - -opt_namespace_member_declarations - : /* empty */ - | namespace_member_declarations - ; - -namespace_member_declarations - : namespace_member_declaration - | namespace_member_declarations namespace_member_declaration - ; - -namespace_member_declaration - : namespace_declaration - | class_declaration - | struct_declaration - | interface_declaration - | enum_declaration - | errordomain_declaration - | delegate_declaration - | constant_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_constant (VALA_NAMESPACE (symbol_stack->data), $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - } - | field_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - /* field must be static, don't require developer - * to explicitly state it */ - vala_field_set_instance ($1, FALSE); - - vala_namespace_add_field (VALA_NAMESPACE (symbol_stack->data), $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - } - | method_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - /* method must be static, don't require developer - * to explicitly state it */ - vala_method_set_instance ($1, FALSE); - - vala_namespace_add_method (VALA_NAMESPACE (symbol_stack->data), $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - } - ; - -class_declaration - : comment opt_attributes opt_access_modifier opt_modifiers CLASS identifier opt_name_specifier opt_type_parameter_list opt_class_base - { - ValaSourceReference *src; - - char *name = $6; - - ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); - ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); - ValaSymbol *current_symbol; - - if ($7 != NULL) { - ValaSourceReference *ns_src = src(@6); - g_object_unref (parent_symbol); - parent_symbol = vala_scope_lookup (parent_scope, $6); - if (parent_symbol != NULL) { - if (check_is_namespace (parent_symbol, ns_src)) { - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); - } - } - } else { - parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $6, ns_src)); - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); - } - parent_scope = vala_symbol_get_scope (parent_symbol); - g_free ($6); - g_object_unref (ns_src); - - name = $7; - } - - src = src_com(@6, $1); - current_symbol = vala_scope_lookup (parent_scope, name); - if (current_symbol != NULL) { - if (check_is_class (current_symbol, src)) { - // merge class declarations - } - } else { - current_symbol = VALA_SYMBOL (vala_code_context_create_class (context, name, src)); - g_free (name); - g_object_unref (src); - - if (VALA_IS_CLASS (parent_symbol)) { - vala_class_add_class (VALA_CLASS (parent_symbol), VALA_CLASS (current_symbol)); - } else if (VALA_IS_INTERFACE (parent_symbol)) { - vala_interface_add_class (VALA_INTERFACE (parent_symbol), VALA_CLASS (current_symbol)); - } else if (VALA_IS_NAMESPACE (parent_symbol)) { - vala_namespace_add_class (VALA_NAMESPACE (parent_symbol), VALA_CLASS (current_symbol)); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE (current_symbol)); - } else { - g_assert_not_reached (); - } - - VALA_CODE_NODE (current_symbol)->attributes = $2; - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL (current_symbol), $3); - } - if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { - vala_class_set_is_abstract (VALA_CLASS (current_symbol), TRUE); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_class_set_is_static (VALA_CLASS (current_symbol), TRUE); - } - if ($8 != NULL) { - GList *l; - for (l = $8; l != NULL; l = l->next) { - vala_class_add_type_parameter (VALA_CLASS (current_symbol), l->data); - g_object_unref (l->data); - } - g_list_free ($8); - } - if ($9 != NULL) { - GList *l; - for (l = $9; l != NULL; l = l->next) { - vala_class_add_base_type (VALA_CLASS (current_symbol), l->data); - g_object_unref (l->data); - } - g_list_free ($9); - } - } - - g_object_unref (parent_symbol); - push_symbol (current_symbol); - } - class_body - { - /* ensure there is always a default construction method */ - ValaClass *cl = VALA_CLASS (symbol_stack->data); - if (!vala_source_file_get_pkg (current_source_file) && - !vala_class_get_is_abstract (cl) && - !vala_class_get_is_static (cl) && - vala_class_get_default_construction_method (cl) == NULL) { - ValaSourceReference *src; - ValaMethod *m; - ValaBlock *block; - src = vala_code_node_get_source_reference (VALA_CODE_NODE (cl)); - m = VALA_METHOD (vala_code_context_create_creation_method (context, vala_symbol_get_name (VALA_SYMBOL (cl)), NULL, src)); - vala_method_set_instance (m, FALSE); - vala_symbol_set_access (VALA_SYMBOL (m), VALA_SYMBOL_ACCESSIBILITY_PUBLIC); - block = vala_code_context_create_block (context, src); - vala_method_set_body (m, block); - g_object_unref (block); - vala_class_add_method (cl, m); - g_object_unref (m); - } - g_object_unref (pop_symbol ()); - } - ; - -opt_access_modifier - : /* empty */ - { - $$ = -1; - } - | access_modifier - ; - -access_modifier - : PUBLIC - { - $$ = VALA_SYMBOL_ACCESSIBILITY_PUBLIC; - } - | PROTECTED - { - $$ = VALA_SYMBOL_ACCESSIBILITY_PROTECTED; - } - | PRIVATE - { - $$ = VALA_SYMBOL_ACCESSIBILITY_PRIVATE; - } - ; - -opt_modifiers - : /* empty */ - { - $$ = VALA_MODIFIER_NONE; - } - | modifiers - ; - -modifiers - : modifier - | modifiers modifier - { - if (($1 & $2) == $2) { - ValaSourceReference *src = src(@2); - vala_report_error (src, "Modifier may only be specified once."); - g_object_unref (src); - } - $$ = $1 | $2; - } - ; - -modifier - : ABSTRACT - { - $$ = VALA_MODIFIER_ABSTRACT; - } - | OVERRIDE - { - $$ = VALA_MODIFIER_OVERRIDE; - } - | STATIC - { - $$ = VALA_MODIFIER_STATIC; - } - | VIRTUAL - { - $$ = VALA_MODIFIER_VIRTUAL; - } - | VOLATILE - { - $$ = VALA_MODIFIER_VOLATILE; - } - | INLINE - { - $$ = VALA_MODIFIER_INLINE; - } - ; - -opt_class_base - : /* empty */ - { - $$ = NULL; - } - | class_base - ; - -class_base - : COLON type_list - { - $$ = $2; - } - ; - -type_list - : type_name - { - $$ = g_list_append (NULL, $1); - } - | type_list COMMA type_name - { - $$ = g_list_append ($1, $3); - } - ; - -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 - : constant_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_class_add_constant (VALA_CLASS (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | field_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_class_add_field (VALA_CLASS (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | method_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_class_add_method (VALA_CLASS (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | property_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_class_add_property (VALA_CLASS (symbol_stack->data), $1, FALSE); - g_object_unref ($1); - } - } - | signal_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_class_add_signal (VALA_CLASS (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | constructor_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - if (vala_constructor_get_instance ($1)) { - vala_class_set_constructor (VALA_CLASS (symbol_stack->data), $1); - } else { - vala_class_set_static_constructor (VALA_CLASS (symbol_stack->data), $1); - } - g_object_unref ($1); - } - } - | destructor_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_class_set_destructor (VALA_CLASS (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | class_declaration - | struct_declaration - | enum_declaration - | delegate_declaration - ; - -constant_declaration - : comment opt_attributes opt_access_modifier CONST type variable_declarator SEMICOLON - { - ValaSourceReference *src = src_com(@5, $1); - $$ = vala_code_context_create_constant (context, vala_symbol_get_name (VALA_SYMBOL ($6)), $5, vala_variable_declarator_get_initializer ($6), src); - g_object_unref (src); - g_object_unref ($5); - g_object_unref ($6); - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - VALA_CODE_NODE($$)->attributes = $2; - } - ; - -field_declaration - : comment opt_attributes opt_access_modifier opt_modifiers type variable_declarator SEMICOLON - { - ValaSourceReference *src; - - src = src_com(@6, $1); - - if (VALA_IS_UNRESOLVED_TYPE ($5)) { - if (vala_data_type_get_is_ref ($5) || vala_data_type_get_is_out ($5)) { - vala_report_error (src, "`ref' and `out' may only be used for parameters."); - } - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_data_type_set_takes_ownership ($5, TRUE); - } - } - - $$ = vala_code_context_create_field (context, vala_symbol_get_name (VALA_SYMBOL ($6)), $5, vala_variable_declarator_get_initializer ($6), src); - g_object_unref (src); - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_field_set_instance ($$, FALSE); - } - if (($4 & VALA_MODIFIER_VOLATILE) == VALA_MODIFIER_VOLATILE) { - vala_field_set_is_volatile ($$, TRUE); - } - VALA_CODE_NODE($$)->attributes = $2; - g_object_unref ($5); - g_object_unref ($6); - } - ; - -comment - : - { - $$ = vala_parser_pop_comment (parser); - } - ; - -variable_declarators - : variable_declarator - { - $$ = g_list_append (NULL, $1); - } - | variable_declarators COMMA variable_declarator - { - $$ = g_list_append ($1, $3); - } - ; - -variable_declarator - : identifier - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_variable_declarator (context, $1, NULL, src); - g_object_unref (src); - g_free ($1); - } - | identifier ASSIGN variable_initializer - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_variable_declarator (context, $1, $3, src); - g_object_unref (src); - g_free ($1); - g_object_unref ($3); - } - ; - -initializer - : OPEN_BRACE opt_variable_initializer_list CLOSE_BRACE - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_initializer_list (context, src)); - g_object_unref (src); - - if ($2 != NULL) { - GList *l; - for (l = $2; l != NULL; l = l->next) { - vala_initializer_list_append (VALA_INITIALIZER_LIST ($$), l->data); - g_object_unref (l->data); - } - } - } - ; - -opt_variable_initializer_list - : /* empty */ - { - $$ = NULL; - } - | variable_initializer_list - ; - -variable_initializer_list - : variable_initializer - { - $$ = g_list_append (NULL, $1); - } - | variable_initializer_list COMMA variable_initializer - { - $$ = g_list_append ($1, $3); - } - ; - -variable_initializer - : expression - | initializer - ; - -method_declaration - : method_header method_body - { - ValaCodeNode *n = VALA_CODE_NODE ($1); - if (n != NULL) { - ValaAttribute *a = vala_code_node_get_attribute (n, "Import"); - gboolean imported; - if (a != NULL) { - imported = TRUE; - g_object_unref (a); - } else { - imported = FALSE; - } - $$ = $1; - vala_method_set_body ($$, $2); - - if ($2 != NULL) { - g_object_unref ($2); - /* method must not be imported, abstract or from a VAPI file */ - if (imported || vala_method_get_is_abstract ($1) || vala_source_file_get_pkg (current_source_file)) { - ValaSourceReference *sr = vala_code_node_get_source_reference (n); - vala_report_error (sr, "unexpected method body found"); - g_object_unref (sr); - } - } else { - /* only imported, abstract and VAPI methods are allowed to have no body */ - if (!imported && !vala_method_get_is_abstract ($1) && !vala_source_file_get_pkg (current_source_file)) { - ValaSourceReference *sr = vala_code_node_get_source_reference (n); - vala_report_error (sr, "expected method body got `;'"); - g_object_unref (sr); - } - } - } - } - | error method_body - { - $$ = NULL; - } - ; - -method_header - : comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration opt_requires_declarations opt_ensures_declarations - { - GList *l; - ValaSourceReference *src; - ValaModifier vmodifiers; - - src = src_com(@6, $1); - - if (VALA_IS_UNRESOLVED_TYPE ($5)) { - if (vala_data_type_get_is_ref ($5) || vala_data_type_get_is_out ($5)) { - vala_report_error (src, "`ref' and `out' may only be used for parameters."); - } - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_data_type_set_transfers_ownership ($5, TRUE); - } - } - - $$ = vala_code_context_create_method (context, $6, $5, src); - g_object_unref (src); - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_method_set_instance ($$, FALSE); - } - vmodifiers = $4 & (VALA_MODIFIER_ABSTRACT | VALA_MODIFIER_VIRTUAL | VALA_MODIFIER_OVERRIDE); - if (vmodifiers == 0) { - } else if (vmodifiers == VALA_MODIFIER_ABSTRACT) { - vala_method_set_is_abstract ($$, TRUE); - } else if (vmodifiers == VALA_MODIFIER_VIRTUAL) { - vala_method_set_is_virtual ($$, TRUE); - } else if (vmodifiers == VALA_MODIFIER_OVERRIDE) { - vala_method_set_overrides ($$, TRUE); - } else { - vala_report_error (vala_code_node_get_source_reference (VALA_CODE_NODE ($$)), "Only one of `abstract', `virtual', and `override' may be specified."); - vala_code_node_set_error (VALA_CODE_NODE ($$), TRUE); - } - if (($4 & VALA_MODIFIER_INLINE) == VALA_MODIFIER_INLINE) { - vala_method_set_is_inline ($$, TRUE); - } - VALA_CODE_NODE($$)->attributes = $2; - - for (l = $8; l != NULL; l = l->next) { - vala_method_add_parameter ($$, l->data); - g_object_unref (l->data); - } - if ($8 != NULL) { - g_list_free ($8); - } - - for (l = $10; l != NULL; l = l->next) { - vala_method_add_error_domain ($$, l->data); - g_object_unref (l->data); - } - if ($10 != NULL) { - g_list_free ($10); - } - - if ($11 != NULL) { - for (l = $11; l != NULL; l = l->next) { - vala_method_add_precondition ($$, l->data); - g_object_unref (l->data); - } - g_list_free ($11); - } - - if ($12 != NULL) { - for (l = $12; l != NULL; l = l->next) { - vala_method_add_postcondition ($$, l->data); - g_object_unref (l->data); - } - g_list_free ($12); - } - - g_object_unref ($5); - g_free ($6); - - if (vala_code_context_ignore_node (context, VALA_CODE_NODE ($$))) { - g_object_unref ($$); - $$ = NULL; - } - } - | comment opt_attributes opt_access_modifier opt_modifiers symbol_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration - { - GList *l; - - ValaSourceReference *src = src_com(@5, $1); - if (vala_unresolved_symbol_get_inner ($5) == NULL) { - $$ = VALA_METHOD (vala_code_context_create_creation_method (context, vala_unresolved_symbol_get_name ($5), NULL, src)); } else { - $$ = VALA_METHOD (vala_code_context_create_creation_method (context, vala_unresolved_symbol_get_name (vala_unresolved_symbol_get_inner ($5)), vala_unresolved_symbol_get_name ($5), src)); - } - g_object_unref ($5); - g_object_unref (src); - vala_method_set_instance ($$, FALSE); - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - VALA_CODE_NODE($$)->attributes = $2; - - if ($7 != NULL) { - for (l = $7; l != NULL; l = l->next) { - vala_method_add_parameter ($$, l->data); - g_object_unref (l->data); - } - g_list_free ($7); - } - - for (l = $9; l != NULL; l = l->next) { - vala_method_add_error_domain ($$, l->data); - g_object_unref (l->data); - } - if ($9 != NULL) { - g_list_free ($9); - } - } - ; - -method_body - : block - | SEMICOLON - { - $$ = NULL; - } - ; - -opt_formal_parameter_list - : /* empty */ - { - $$ = NULL; - } - | formal_parameter_list - ; - -formal_parameter_list - : fixed_parameters - | fixed_parameters COMMA ELLIPSIS - { - ValaSourceReference *src = src(@3); - $$ = g_list_append ($1, vala_code_context_create_formal_parameter_with_ellipsis (context, src)); - g_object_unref (src); - } - | ELLIPSIS - { - ValaSourceReference *src = src(@1); - $$ = g_list_append (NULL, vala_code_context_create_formal_parameter_with_ellipsis (context, src)); - g_object_unref (src); - } - ; - -fixed_parameters - : fixed_parameter - { - $$ = g_list_append (NULL, $1); - } - | fixed_parameters COMMA fixed_parameter - { - $$ = g_list_append ($1, $3); - } - ; - -opt_construct - : /* empty */ - { - $$ = FALSE; - } - | CONSTRUCT - { - $$ = TRUE; - } - ; - -fixed_parameter - : opt_attributes opt_construct type identifier - { - ValaSourceReference *src; - - src = src(@3); - if (VALA_IS_UNRESOLVED_TYPE ($3)) { - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) { - vala_data_type_set_takes_ownership ($3, TRUE); - } - - if (!vala_data_type_get_is_ref ($3) - && !vala_data_type_get_is_out ($3) - && !vala_data_type_get_transfers_ownership ($3)) { - /* take_ownership for in parameters that don't transfer ownership is not supported */ - vala_data_type_set_takes_ownership ($3, FALSE); - } - } - - $$ = vala_code_context_create_formal_parameter (context, $4, $3, src); - g_object_unref (src); - vala_formal_parameter_set_construct_parameter ($$, $2); - g_object_unref ($3); - g_free ($4); - - VALA_CODE_NODE($$)->attributes = $1; - } - | opt_attributes opt_construct type identifier ASSIGN expression - { - ValaSourceReference *src; - - src = src(@3); - if (VALA_IS_UNRESOLVED_TYPE ($3)) { - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) { - vala_data_type_set_takes_ownership ($3, TRUE); - } - - if (!vala_data_type_get_is_ref ($3) - && !vala_data_type_get_is_out ($3) - && !vala_data_type_get_transfers_ownership ($3)) { - /* take_ownership for in parameters that don't transfer ownership is not supported */ - vala_data_type_set_takes_ownership ($3, FALSE); - } - } - - $$ = vala_code_context_create_formal_parameter (context, $4, $3, src); - g_object_unref (src); - vala_formal_parameter_set_default_expression ($$, $6); - vala_formal_parameter_set_construct_parameter ($$, $2); - g_object_unref ($3); - g_free ($4); - g_object_unref ($6); - - VALA_CODE_NODE($$)->attributes = $1; - } - ; - -opt_throws_declaration - : /* empty */ - { - $$ = NULL; - } - | throws_declaration - ; - -throws_declaration - : THROWS type_list - { - $$ = $2; - } - ; - -opt_requires_declarations - : /* empty */ - { - $$ = NULL; - } - | requires_declarations - ; - -requires_declarations - : requires_declaration - { - $$ = g_list_append (NULL, $1); - } - | requires_declarations requires_declaration - { - $$ = g_list_append ($1, $2); - } - ; - -requires_declaration - : REQUIRES open_parens expression CLOSE_PARENS - { - $$ = $3; - } - ; - -opt_ensures_declarations - : /* empty */ - { - $$ = NULL; - } - | ensures_declarations - ; - -ensures_declarations - : ensures_declaration - { - $$ = g_list_append (NULL, $1); - } - | ensures_declarations ensures_declaration - { - $$ = g_list_append ($1, $2); - } - ; - -ensures_declaration - : ENSURES open_parens expression CLOSE_PARENS - { - $$ = $3; - } - ; - -property_declaration - : comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration opt_default_value CLOSE_BRACE - { - ValaSourceReference *src; - - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_data_type_set_takes_ownership ($5, TRUE); - } - - src = src_com(@5, $1); - $$ = vala_code_context_create_property (context, $6, $5, $8, $9, src); - g_object_unref (src); - - VALA_CODE_NODE($$)->attributes = $2; - - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - - g_object_unref ($5); - g_free ($6); - g_object_unref ($8); - if ($9 != NULL) { - g_object_unref ($9); - } - - if ($10 != NULL) { - vala_property_set_default_expression ($$, $10); - g_object_unref ($10); - } - - if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { - vala_property_set_is_abstract ($$, TRUE); - } - if (($4 & VALA_MODIFIER_VIRTUAL) == VALA_MODIFIER_VIRTUAL) { - vala_property_set_is_virtual ($$, TRUE); - } - if (($4 & VALA_MODIFIER_OVERRIDE) == VALA_MODIFIER_OVERRIDE) { - vala_property_set_overrides ($$, TRUE); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_property_set_instance ($$, FALSE); - } - } - | comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_BRACE set_accessor_declaration opt_get_accessor_declaration opt_default_value CLOSE_BRACE - { - ValaSourceReference *src; - - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_data_type_set_takes_ownership ($5, TRUE); - } - - src = src_com(@5, $1); - $$ = vala_code_context_create_property (context, $6, $5, $9, $8, src); - g_object_unref (src); - - VALA_CODE_NODE($$)->attributes = $2; - - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - - g_object_unref ($5); - g_free ($6); - g_object_unref ($8); - if ($9 != NULL) { - g_object_unref ($9); - } - - if ($10 != NULL) { - vala_property_set_default_expression ($$, $10); - g_object_unref ($10); - } - - if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { - vala_property_set_is_abstract ($$, TRUE); - } - if (($4 & VALA_MODIFIER_VIRTUAL) == VALA_MODIFIER_VIRTUAL) { - vala_property_set_is_virtual ($$, TRUE); - } - if (($4 & VALA_MODIFIER_OVERRIDE) == VALA_MODIFIER_OVERRIDE) { - vala_property_set_overrides ($$, TRUE); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_property_set_instance ($$, FALSE); - } - } - ; - -opt_get_accessor_declaration - : /* empty */ - { - $$ = NULL; - } - | get_accessor_declaration - ; - -get_accessor_declaration - : opt_attributes opt_access_modifier GET method_body - { - ValaSourceReference *src = src(@3); - $$ = vala_code_context_create_property_accessor (context, TRUE, FALSE, FALSE, $4, src); - g_object_unref (src); - if ($4 != NULL) { - g_object_unref ($4); - } - - if ($2 != -1) { - vala_property_accessor_set_access ($$, $2); - } else { - vala_property_accessor_set_access ($$, VALA_SYMBOL_ACCESSIBILITY_PUBLIC); - } - } - ; - -opt_set_accessor_declaration - : /* empty */ - { - $$ = NULL; - } - | set_accessor_declaration - ; - -set_accessor_declaration - : opt_attributes opt_access_modifier SET method_body - { - ValaSourceReference *src = src(@3); - $$ = vala_code_context_create_property_accessor (context, FALSE, TRUE, FALSE, $4, src); - g_object_unref (src); - if ($4 != NULL) { - g_object_unref ($4); - } - - if ($2 != -1) { - vala_property_accessor_set_access ($$, $2); - } else { - vala_property_accessor_set_access ($$, VALA_SYMBOL_ACCESSIBILITY_PUBLIC); - } - } - | opt_attributes opt_access_modifier SET CONSTRUCT method_body - { - ValaSourceReference *src = src(@3); - $$ = vala_code_context_create_property_accessor (context, FALSE, TRUE, TRUE, $5, src); - g_object_unref (src); - if ($5 != NULL) { - g_object_unref ($5); - } - - if ($2 != -1) { - vala_property_accessor_set_access ($$, $2); - } else { - vala_property_accessor_set_access ($$, VALA_SYMBOL_ACCESSIBILITY_PUBLIC); - } - } - | opt_attributes opt_access_modifier CONSTRUCT method_body - { - ValaSourceReference *src = src(@3); - $$ = vala_code_context_create_property_accessor (context, FALSE, FALSE, TRUE, $4, src); - g_object_unref (src); - if ($4 != NULL) { - g_object_unref ($4); - } - - if ($2 != -1) { - vala_property_accessor_set_access ($$, $2); - } else { - vala_property_accessor_set_access ($$, VALA_SYMBOL_ACCESSIBILITY_PUBLIC); - } - } - | opt_attributes opt_access_modifier CONSTRUCT SET method_body - { - ValaSourceReference *src = src(@3); - $$ = vala_code_context_create_property_accessor (context, FALSE, TRUE, TRUE, $5, src); - g_object_unref (src); - if ($5 != NULL) { - g_object_unref ($5); - } - - if ($2 != -1) { - vala_property_accessor_set_access ($$, $2); - } else { - vala_property_accessor_set_access ($$, VALA_SYMBOL_ACCESSIBILITY_PUBLIC); - } - } - ; - -opt_default_value - : /* empty */ - { - $$ = NULL; - } - | default_value - ; - -default_value - : DEFAULT OPEN_PARENS expression CLOSE_PARENS SEMICOLON - { - $$ = $3; - } - | DEFAULT ASSIGN expression SEMICOLON - { - $$ = $3; - } - ; - -signal_declaration - : comment opt_attributes opt_access_modifier SIGNAL type identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON - { - GList *l; - - ValaSourceReference *src = src_com(@6, $1); - $$ = vala_code_context_create_signal (context, $6, $5, src); - g_object_unref (src); - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL ($$), $3); - } - VALA_CODE_NODE($$)->attributes = $2; - - for (l = $8; l != NULL; l = l->next) { - vala_signal_add_parameter ($$, l->data); - g_object_unref (l->data); - } - if ($8 != NULL) { - g_list_free ($8); - } - - g_object_unref ($5); - g_free ($6); - } - ; - -constructor_declaration - : comment opt_attributes opt_access_modifier opt_modifiers CONSTRUCT block - { - ValaSourceReference *src = src_com(@5, $1); - $$ = vala_code_context_create_constructor (context, src); - g_object_unref (src); - vala_constructor_set_body ($$, $6); - g_object_unref ($6); - - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_constructor_set_instance ($$, FALSE); - } - } - ; - -destructor_declaration - : comment opt_attributes opt_access_modifier opt_modifiers TILDE identifier OPEN_PARENS CLOSE_PARENS block - { - ValaSourceReference *src = src_com(@6, $1); - $$ = vala_code_context_create_destructor (context, src); - g_object_unref (src); - vala_destructor_set_body ($$, $9); - - g_free ($6); - g_object_unref ($9); - } - ; - -struct_declaration - : comment opt_attributes opt_access_modifier STRUCT identifier opt_name_specifier opt_type_parameter_list opt_class_base - { - GList *l; - ValaSourceReference *src; - - char *name = $5; - - ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); - ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); - ValaSymbol *current_symbol; - - if ($6 != NULL) { - ValaSourceReference *ns_src = src(@5); - g_object_unref (parent_symbol); - parent_symbol = vala_scope_lookup (parent_scope, $5); - if (parent_symbol != NULL) { - if (check_is_namespace (parent_symbol, ns_src)) { - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); - } - } - } else { - parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $5, ns_src)); - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); - } - parent_scope = vala_symbol_get_scope (parent_symbol); - g_free ($5); - g_object_unref (ns_src); - - name = $6; - } - - src = src_com(@5, $1); - current_symbol = vala_scope_lookup (parent_scope, name); - if (current_symbol != NULL) { - if (check_is_struct (current_symbol, src)) { - // merge class declarations - } - } else { - current_symbol = VALA_SYMBOL (vala_code_context_create_struct (context, name, src)); - g_free (name); - g_object_unref (src); - - if (VALA_IS_CLASS (parent_symbol)) { - vala_class_add_struct (VALA_CLASS (parent_symbol), VALA_STRUCT (current_symbol)); - } else if (VALA_IS_INTERFACE (parent_symbol)) { - vala_interface_add_struct (VALA_INTERFACE (parent_symbol), VALA_STRUCT (current_symbol)); - } else if (VALA_IS_NAMESPACE (parent_symbol)) { - vala_namespace_add_struct (VALA_NAMESPACE (parent_symbol), VALA_STRUCT (current_symbol)); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE (current_symbol)); - } else { - g_assert_not_reached (); - } - - for (l = $7; l != NULL; l = l->next) { - vala_struct_add_type_parameter (VALA_STRUCT (current_symbol), l->data); - } - VALA_CODE_NODE(current_symbol)->attributes = $2; - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL (current_symbol), $3); - } - if ($8 != NULL) { - for (l = $8; l != NULL; l = l->next) { - vala_struct_add_base_type (VALA_STRUCT (current_symbol), l->data); - g_object_unref (l->data); - } - g_list_free ($8); - } - } - - g_object_unref (parent_symbol); - push_symbol (current_symbol); - } - struct_body - { - g_object_unref (pop_symbol ()); - } - ; - -struct_body - : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE - ; - -opt_struct_member_declarations - : /* empty */ - | struct_member_declarations - ; - -struct_member_declarations - : struct_member_declaration - | struct_member_declarations struct_member_declaration - ; - -struct_member_declaration - : constant_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_struct_add_constant (VALA_STRUCT (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | field_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - /* struct fields must not have initializers */ - ValaExpression *init = vala_field_get_initializer ($1); - if (init != NULL) { - ValaSourceReference *src = src(@1); - vala_report_error (src, "Unexpected field initializer found"); - g_object_unref (src); - } - vala_struct_add_field (VALA_STRUCT (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | method_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_struct_add_method (VALA_STRUCT (symbol_stack->data), $1); - g_object_unref ($1); - } - } - ; - -interface_declaration - : comment opt_attributes opt_access_modifier opt_modifiers INTERFACE identifier opt_name_specifier opt_type_parameter_list opt_class_base - { - ValaSourceReference *src; - char *name = $6; - - ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); - ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); - ValaInterface *iface; - - if ($7 != NULL) { - ValaSourceReference *ns_src = src(@6); - g_object_unref (parent_symbol); - parent_symbol = vala_scope_lookup (parent_scope, $6); - if (parent_symbol != NULL) { - if (check_is_namespace (parent_symbol, ns_src)) { - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); - } - } - } else { - parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $6, ns_src)); - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); - } - parent_scope = vala_symbol_get_scope (parent_symbol); - g_free ($6); - g_object_unref (ns_src); - - name = $7; - } - - src = src_com(@6, $1); - iface = vala_code_context_create_interface (context, name, src); - g_free (name); - g_object_unref (src); - - vala_namespace_add_interface (VALA_NAMESPACE (parent_symbol), iface); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE (iface)); - g_object_unref (parent_symbol); - - VALA_CODE_NODE (iface)->attributes = $2; - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL (iface), $3); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_interface_set_is_static (iface, TRUE); - } - if ($8 != NULL) { - GList *l; - for (l = $8; l != NULL; l = l->next) { - vala_interface_add_type_parameter (iface, l->data); - g_object_unref (l->data); - } - g_list_free ($8); - } - if ($9 != NULL) { - GList *l; - for (l = $9; l != NULL; l = l->next) { - vala_interface_add_prerequisite (iface, l->data); - g_object_unref (l->data); - } - g_list_free ($9); - } - - push_symbol (VALA_SYMBOL (iface)); - } - interface_body - { - g_object_unref (pop_symbol ()); - } - ; - -interface_body - : OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE - | SEMICOLON - { - vala_symbol_set_is_imported (symbol_stack->data, TRUE); - vala_interface_set_declaration_only (VALA_INTERFACE (symbol_stack->data), TRUE); - } - ; - -opt_interface_member_declarations - : /* empty */ - | interface_member_declarations - ; - -interface_member_declarations - : interface_member_declaration - | interface_member_declarations interface_member_declaration - ; - -interface_member_declaration - : method_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_interface_add_method (VALA_INTERFACE (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | field_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_interface_add_field (VALA_INTERFACE (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | property_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_interface_add_property (VALA_INTERFACE (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | signal_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_interface_add_signal (VALA_INTERFACE (symbol_stack->data), $1); - g_object_unref ($1); - } - } - | class_declaration - | struct_declaration - | enum_declaration - | delegate_declaration - ; - -enum_declaration - : comment opt_attributes opt_access_modifier ENUM identifier opt_name_specifier - { - ValaSourceReference *src; - - char *name = $5; - - ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); - ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); - ValaEnum *en; - - if ($6 != NULL) { - ValaSourceReference *ns_src = src(@5); - g_object_unref (parent_symbol); - parent_symbol = vala_scope_lookup (parent_scope, $5); - if (parent_symbol != NULL) { - if (check_is_namespace (parent_symbol, ns_src)) { - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); - } - } - } else { - parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $5, ns_src)); - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); - } - parent_scope = vala_symbol_get_scope (parent_symbol); - g_free ($5); - g_object_unref (ns_src); - - name = $6; - } - - src = src_com(@5, $1); - en = vala_code_context_create_enum (context, name, src); - g_free (name); - g_object_unref (src); - - if (VALA_IS_CLASS (parent_symbol)) { - vala_class_add_enum (VALA_CLASS (parent_symbol), en); - } else if (VALA_IS_INTERFACE (parent_symbol)) { - vala_interface_add_enum (VALA_INTERFACE (parent_symbol), en); - } else if (VALA_IS_NAMESPACE (parent_symbol)) { - vala_namespace_add_enum (VALA_NAMESPACE (parent_symbol), en); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE (en)); - } else { - g_assert_not_reached (); - } - g_object_unref (parent_symbol); - - VALA_CODE_NODE (en)->attributes = $2; - - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL (en), $3); - } - - push_symbol (VALA_SYMBOL (en)); - } - enum_body - { - g_object_unref (pop_symbol ()); - } - ; - -enum_body - : OPEN_BRACE opt_enum_member_declarations opt_enum_method_declarations CLOSE_BRACE - ; - -opt_enum_member_declarations - : /* empty */ - | enum_member_declarations opt_comma - ; - -enum_member_declarations - : enum_member_declaration - | enum_member_declarations COMMA enum_member_declaration - ; - -enum_member_declaration - : comment opt_attributes identifier - { - ValaSourceReference *src; - ValaEnumValue *ev; - - src = src_com(@3, $1); - ev = vala_code_context_create_enum_value (context, $3, src); - g_free ($3); - vala_enum_add_value (VALA_ENUM (symbol_stack->data), ev); - g_object_unref (ev); - } - | comment opt_attributes identifier ASSIGN expression - { - ValaSourceReference *src; - ValaEnumValue *ev; - - src = src_com(@3, $1); - ev = vala_code_context_create_enum_value_with_value (context, $3, $5, src); - g_free ($3); - g_object_unref ($5); - vala_enum_add_value (VALA_ENUM (symbol_stack->data), ev); - g_object_unref (ev); - } - ; - -opt_enum_method_declarations - : /* empty */ - | enum_method_declarations - ; - -enum_method_declarations - : SEMICOLON enum_method_declaration - | enum_method_declarations enum_method_declaration - ; - -enum_method_declaration - : method_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_enum_add_method (VALA_ENUM (symbol_stack->data), $1); - g_object_unref ($1); - } - } - ; - -errordomain_declaration - : comment opt_attributes opt_access_modifier ERRORDOMAIN identifier opt_name_specifier - { - ValaSourceReference *src; - - char *name = $5; - - ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); - ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); - ValaErrorDomain *edomain; - - if ($6 != NULL) { - ValaSourceReference *ns_src = src(@5); - g_object_unref (parent_symbol); - parent_symbol = vala_scope_lookup (parent_scope, $5); - if (parent_symbol != NULL) { - if (check_is_namespace (parent_symbol, ns_src)) { - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); - } - } - } else { - parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $5, ns_src)); - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); - } - parent_scope = vala_symbol_get_scope (parent_symbol); - g_free ($5); - g_object_unref (ns_src); - - name = $6; - } - - src = src_com(@5, $1); - edomain = vala_code_context_create_error_domain (context, name, src); - g_free (name); - g_object_unref (src); - - vala_namespace_add_error_domain (VALA_NAMESPACE (parent_symbol), edomain); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE (edomain)); - g_object_unref (parent_symbol); - - VALA_CODE_NODE (edomain)->attributes = $2; - - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL (edomain), $3); - } - - push_symbol (VALA_SYMBOL (edomain)); - } - errordomain_body - { - g_object_unref (pop_symbol ()); - } - ; - -errordomain_body - : OPEN_BRACE opt_errordomain_member_declarations opt_errordomain_method_declarations CLOSE_BRACE - ; - -opt_errordomain_member_declarations - : /* empty */ - | errordomain_member_declarations opt_comma - ; - -errordomain_member_declarations - : errordomain_member_declaration - | errordomain_member_declarations COMMA errordomain_member_declaration - ; - -errordomain_member_declaration - : opt_attributes identifier - { - ValaErrorCode *ec = vala_code_context_create_error_code (context, $2); - g_free ($2); - vala_error_domain_add_code (VALA_ERROR_DOMAIN (symbol_stack->data), ec); - g_object_unref (ec); - } - | opt_attributes identifier ASSIGN expression - { - ValaErrorCode *ec = vala_code_context_create_error_code_with_value (context, $2, $4); - g_free ($2); - g_object_unref ($4); - vala_error_domain_add_code (VALA_ERROR_DOMAIN (symbol_stack->data), ec); - g_object_unref (ec); - } - ; - -opt_errordomain_method_declarations - : /* empty */ - | errordomain_method_declarations - ; - -errordomain_method_declarations - : SEMICOLON errordomain_method_declaration - | errordomain_method_declarations errordomain_method_declaration - ; - -errordomain_method_declaration - : method_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_error_domain_add_method (VALA_ERROR_DOMAIN (symbol_stack->data), $1); - g_object_unref ($1); - } - } - ; - -delegate_declaration - : comment opt_attributes opt_access_modifier opt_modifiers DELEGATE type identifier opt_name_specifier opt_type_parameter_list OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration SEMICOLON - { - ValaSourceReference *src; - GList *l; - char *name = $7; - - ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); - ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); - ValaDelegate *cb; - - if ($8 != NULL) { - ValaSourceReference *ns_src = src(@7); - g_object_unref (parent_symbol); - parent_symbol = vala_scope_lookup (parent_scope, $7); - if (parent_symbol != NULL) { - if (check_is_namespace (parent_symbol, ns_src)) { - if (!vala_source_file_get_pkg (current_source_file)) { - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); - } - } - } else { - parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $7, ns_src)); - vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); - vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); - } - parent_scope = vala_symbol_get_scope (parent_symbol); - g_free ($7); - g_object_unref (ns_src); - - name = $8; - } - - src = src_com(@7, $1); - cb = vala_code_context_create_delegate (context, name, $6, src); - g_free (name); - g_object_unref ($6); - g_object_unref (src); - - if (VALA_IS_CLASS (parent_symbol)) { - vala_class_add_delegate (VALA_CLASS (parent_symbol), cb); - } else if (VALA_IS_INTERFACE (parent_symbol)) { - vala_interface_add_delegate (VALA_INTERFACE (parent_symbol), cb); - } else if (VALA_IS_NAMESPACE (parent_symbol)) { - vala_namespace_add_delegate (VALA_NAMESPACE (parent_symbol), cb); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE (cb)); - } else { - g_assert_not_reached (); - } - g_object_unref (parent_symbol); - - if ($3 != -1) { - vala_symbol_set_access (VALA_SYMBOL (cb), $3); - } - VALA_CODE_NODE (cb)->attributes = $2; - if (($4 & VALA_MODIFIER_STATIC) == 0) { - vala_delegate_set_instance (cb, TRUE); - } - - if ($9 != NULL) { - for (l = $9; l != NULL; l = l->next) { - vala_delegate_add_type_parameter (cb, l->data); - g_object_unref (l->data); - } - g_list_free ($9); - } - if ($11 != NULL) { - for (l = $11; l != NULL; l = l->next) { - vala_delegate_add_parameter (cb, l->data); - g_object_unref (l->data); - } - g_list_free ($11); - } - - g_object_unref (cb); - } - ; - -opt_attributes - : /* empty */ - { - $$ = NULL; - } - | attributes - ; - -attributes - : attribute_sections - ; - -attribute_sections - : attribute_section - | attribute_sections attribute_section - { - $$ = g_list_concat ($1, $2); - } - ; - -attribute_section - : OPEN_BRACKET attribute_list CLOSE_BRACKET - { - $$ = $2; - } - | OPEN_BRACKET error CLOSE_BRACKET - { - $$ = NULL; - } - ; - -attribute_list - : attribute - { - $$ = g_list_append (NULL, $1); - } - | attribute_list COMMA attribute - { - $$ = g_list_append ($1, $3); - } - ; - -attribute - : attribute_name - { - ValaSourceReference *src = src(@1); - $$ = vala_attribute_new ($1, src); - g_free ($1); - g_object_unref (src); - } - | attribute_name OPEN_PARENS opt_named_argument_list CLOSE_PARENS - { - GList *l; - - ValaSourceReference *src = src(@1); - $$ = vala_attribute_new ($1, src); - g_object_unref (src); - - for (l = $3; l != NULL; l = l->next) { - vala_attribute_add_argument ($$, l->data); - g_object_unref (l->data); - } - if ($3 != NULL) { - g_list_free ($3); - } - - g_free ($1); - } - ; - -attribute_name - : identifier - ; - -opt_named_argument_list - : /* empty */ - { - $$ = NULL; - } - | named_argument_list - ; - -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 - { - ValaSourceReference *src = src(@1); - $$ = vala_named_argument_new ($1, $3, src); - g_object_unref (src); - - g_free ($1); - g_object_unref ($3); - } - ; - -opt_type_parameter_list - : /* empty */ - { - $$ = NULL; - } - | type_parameter_list - ; - -type_parameter_list - : GENERIC_LT type_parameters OP_GT - { - $$ = $2; - } - ; - -type_parameters - : type_parameter - { - $$ = g_list_append (NULL, $1); - } - | type_parameters COMMA type_parameter - { - $$ = g_list_append ($1, $3); - } - ; - -type_parameter - : identifier - { - ValaSourceReference *src = src(@1); - $$ = vala_code_context_create_type_parameter (context, $1, src); - g_object_unref (src); - g_free ($1); - } - ; - -opt_type_argument_list - : /* empty */ - { - $$ = NULL; - } - | type_argument_list - ; - -type_argument_list - : GENERIC_LT type_arguments OP_GT - { - $$ = $2; - } - ; - -type_arguments - : type_argument - { - $$ = g_list_append (NULL, $1); - } - | type_arguments COMMA type_argument - { - $$ = g_list_append ($1, $3); - } - ; - -type_argument - : type - { - $$ = $1; - if (VALA_IS_UNRESOLVED_TYPE ($$)) { - if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($$))) { - vala_data_type_set_takes_ownership ($$, TRUE); - } - } - } - ; - -open_parens - : OPEN_PARENS - | OPEN_CAST_PARENS - ; - -member_name - : identifier opt_type_argument_list - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_member_access (context, NULL, $1, src)); - g_free ($1); - g_object_unref (src); - - if ($2 != NULL) { - GList *l; - for (l = $2; l != NULL; l = l->next) { - vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($2); - } - } - | member_name DOT identifier opt_type_argument_list - { - ValaSourceReference *src = src(@1); - $$ = VALA_EXPRESSION (vala_code_context_create_member_access (context, $1, $3, src)); - g_object_unref ($1); - g_free ($3); - g_object_unref (src); - - if ($4 != NULL) { - GList *l; - for (l = $4; l != NULL; l = l->next) { - vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data); - g_object_unref (l->data); - } - g_list_free ($4); - } - } - ; - -%% - -extern FILE *yyin; -extern int yylineno; - -static void -yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg) -{ - ValaSourceReference *source_reference = vala_source_reference_new (current_source_file, locp->first_line, locp->first_column, locp->last_line, locp->last_column); - vala_report_error (source_reference, (char *) msg); -} - -void -vala_parser_parse_file (ValaParser *parser, ValaSourceFile *source_file) -{ - current_source_file = source_file; - context = vala_source_file_get_context (current_source_file); - push_symbol (VALA_SYMBOL (vala_code_context_get_root (context))); - yyin = fopen (vala_source_file_get_filename (current_source_file), "r"); - if (yyin == NULL) { - printf ("Couldn't open source file: %s.\n", vala_source_file_get_filename (current_source_file)); - return; - } - - /* restart line counter on each file */ - yylineno = 1; - - yyparse (parser); - fclose (yyin); - yyin = NULL; -} - -static void push_symbol (ValaSymbol *symbol) { - symbol_stack = g_list_prepend (symbol_stack, symbol); - scope_stack = g_list_prepend (scope_stack, vala_symbol_get_scope (symbol)); -} - -static ValaSymbol *pop_symbol (void) { - ValaSymbol *sym = VALA_SYMBOL (symbol_stack->data); - symbol_stack = g_list_delete_link (symbol_stack, symbol_stack); - scope_stack = g_list_delete_link (scope_stack, scope_stack); - return sym; -} - -static gboolean check_is_namespace (ValaSymbol *symbol, ValaSourceReference *src) { - if (!VALA_IS_NAMESPACE (symbol)) { - char *sym_name = vala_symbol_get_full_name (symbol); - char *error_msg = g_strdup_printf ("`%s` already exists but is not a namespace", sym_name); - g_free (sym_name); - vala_report_error (src, error_msg); - g_free (error_msg); - return FALSE; - } - return TRUE; -} - -static gboolean check_is_class (ValaSymbol *symbol, ValaSourceReference *src) { - if (!VALA_IS_CLASS (symbol)) { - char *sym_name = vala_symbol_get_full_name (symbol); - char *error_msg = g_strdup_printf ("`%s` already exists but is not a class", sym_name); - g_free (sym_name); - vala_report_error (src, error_msg); - g_free (error_msg); - return FALSE; - } - return TRUE; -} - -static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src) { - if (!VALA_IS_STRUCT (symbol)) { - char *sym_name = vala_symbol_get_full_name (symbol); - char *error_msg = g_strdup_printf ("`%s` already exists but is not a struct", sym_name); - g_free (sym_name); - vala_report_error (src, error_msg); - g_free (error_msg); - return FALSE; - } - return TRUE; -} diff --git a/vala/scanner.l b/vala/scanner.l deleted file mode 100644 index 5d04ecd..0000000 --- a/vala/scanner.l +++ /dev/null @@ -1,209 +0,0 @@ -/* scanner.l - * - * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter - * Raffaele Sandrini - */ - -%{ -#include "vala.h" -#include "parser.h" - -#define YY_DECL int yylex (YYSTYPE *yylval_param, YYLTYPE *yylloc_param, ValaParser *parser) - -#define uploc { yylloc->first_column = yylloc->last_column + 1; yylloc->last_column += yyleng; } - -static gboolean file_comment = FALSE; -%} - -%option yylineno -%option bison-bridge -%option bison-locations -%option noyywrap -%option nounput - -%x IN_COMMENT - -space [ \t\n]* -ident [[:alnum:]_]+ -decimal_integer_literal (0|[1-9][[:digit:]]*) -real_literal [[:digit:]]+"."[[:digit:]]*{exponent_part}?{real_suffix}? -hex_digit [[:digit:]A-Fa-f] -octal_digit [0-7] -octal_integer_literal 0{octal_digit}+ -hexadecimal_integer_literal 0x{hex_digit}+ -exponent_part (e|E){sign}?[[:digit:]]+ -sign "+"|"-" -integer_suffix L|LL|U|UL|ULL -real_suffix F -single_character [^\'\\] -single_string_literal_character [^\"\\] -simple_escape_sequence \\[\'\"\?\\abfnrtv0] -hexadecimal_escape_sequence \\x{hex_digit}{hex_digit}?{hex_digit}?{hex_digit}? -character ({single_character}|{simple_escape_sequence}) -string_literal_character ({single_string_literal_character}|{simple_escape_sequence}) -character_literal \'{character}+\' -string_literal \"{string_literal_character}*\" -integer_literal ({decimal_integer_literal}|{hexadecimal_integer_literal}|{octal_integer_literal}){integer_suffix}? -literal ({integer_literal}|{real_literal}|{character_literal}|{string_literal}) - -type_name ("weak"{space})?({ident}".")?{ident} -generic_type {type_name}("<"{space}{type_name}("?"|"*"+)?(","{space}{type_name}("?"|"*"+)?)*">")?("?"|"*"+)? - -%% - -"/*" { uploc; file_comment = (yylineno == 1); BEGIN (IN_COMMENT); } -"*/" { uploc; BEGIN (INITIAL); yytext[yyleng - 2] = '\0'; vala_parser_push_comment (parser, yytext, file_comment); } -[^*\n]+ { uploc; yymore (); } -"*" { uploc; yymore (); } -\n { yylloc->first_line = yylloc->last_line = yylineno; yylloc->first_column = 1; yylloc->last_column = 0; yymore (); } - -"//".* { uploc; vala_parser_push_comment (parser, g_strdup (yytext + 2), FALSE); } - -"{" { uploc; return OPEN_BRACE; } -"}" { uploc; return CLOSE_BRACE; } -"("({space}"weak")?{space}{ident}("."{ident})?("<"({ident}".")?{ident}(","({ident}".")?{ident})*">")?("["{space}"]")*{space}")"{space}("("|{ident}|{literal}) { yyless (1); uploc; return OPEN_CAST_PARENS; } -"(" { uploc; return OPEN_PARENS; } -")" { uploc; return CLOSE_PARENS; } -"["{space}(","{space})*"]" { yyless (1); uploc; return OPEN_ARRAY_TYPE_BRACKET; } -"[" { uploc; return OPEN_BRACKET; } -"]" { uploc; return CLOSE_BRACKET; } -"..." { uploc; return ELLIPSIS; } -"." { uploc; return DOT; } -":" { uploc; return COLON; } -"," { uploc; return COMMA; } -";" { uploc; return SEMICOLON; } -"#" { uploc; return HASH; } -"?"{space}({ident}{space}("="|";")|"[") { yyless (1); uploc; return NULLABLE_INTERR; } -"?" { uploc; return INTERR; } - -"|=" { uploc; return ASSIGN_BITWISE_OR; } -"&=" { uploc; return ASSIGN_BITWISE_AND; } -"^=" { uploc; return ASSIGN_BITWISE_XOR; } -"+=" { uploc; return ASSIGN_ADD; } -"-=" { uploc; return ASSIGN_SUB; } -"*=" { uploc; return ASSIGN_MUL; } -"/=" { uploc; return ASSIGN_DIV; } -"%=" { uploc; return ASSIGN_PERCENT; } -"<<=" { uploc; return ASSIGN_SHIFT_LEFT; } -">>=" { uploc; return ASSIGN_SHIFT_RIGHT; } - -"++" { uploc; return OP_INC; } -"--" { uploc; return OP_DEC; } -"==" { uploc; return OP_EQ; } -"!=" { uploc; return OP_NE; } -"<<" { uploc; return OP_SHIFT_LEFT; } -">>" { uploc; return OP_SHIFT_RIGHT; } -"<=" { uploc; return OP_LE; } -">=" { uploc; return OP_GE; } -"=>" { uploc; return LAMBDA; } -"<"{space}{generic_type}{space}(","{space}{generic_type}{space})*">" { yyless (1); uploc; return GENERIC_LT; } -"<" { uploc; return OP_LT; } -">" { uploc; return OP_GT; } -"!" { uploc; return OP_NEG; } -"||" { uploc; return OP_OR; } -"|" { uploc; return BITWISE_OR; } -"&&" { uploc; return OP_AND; } -"&" { uploc; return BITWISE_AND; } -"^" { uploc; return CARRET; } -"~" { uploc; return TILDE; } - -"->" { uploc; return OP_PTR; } - -"=" { uploc; return ASSIGN; } -"+" { uploc; return PLUS; } -"-" { uploc; return MINUS; } -"*" { uploc; return STAR; } -"/" { uploc; return DIV; } -"%" { uploc; return PERCENT; } - -"@"[[:alnum:]_]+ { uploc; yylval->str = g_strdup (yytext + 1); return IDENTIFIER; } - -"abstract" { uploc; return ABSTRACT; } -"as" { uploc; return AS; } -"base" { uploc; return BASE; } -"break" { uploc; return BREAK; } -"case" { uploc; return CASE; } -"catch" { uploc; return CATCH; } -"class" { uploc; return CLASS; } -"const" { uploc; return CONST; } -"construct" { uploc; return CONSTRUCT; } -"continue" { uploc; return CONTINUE; } -"default" { uploc; return DEFAULT; } -"delegate" { uploc; return DELEGATE; } -"delete" { uploc; return DELETE; } -"do" { uploc; return DO; } -"else" { uploc; return ELSE; } -"ensures" { uploc; return ENSURES; } -"enum" { uploc; return ENUM; } -"errordomain" { uploc; return ERRORDOMAIN; } -"false" { uploc; return VALA_FALSE; } -"finally" { uploc; return FINALLY; } -"for" { uploc; return FOR; } -"foreach" { uploc; return FOREACH; } -"get" { uploc; return GET; } -"if" { uploc; return IF; } -"in" { uploc; return IN; } -"inline" { uploc; return INLINE; } -"interface" { uploc; return INTERFACE; } -"is" { uploc; return IS; } -"lock" { uploc; return LOCK; } -"namespace" { uploc; return NAMESPACE; } -"new" { uploc; return NEW; } -"null" { uploc; return VALA_NULL; } -"out" { uploc; return OUT; } -"override" { uploc; return OVERRIDE; } -"private" { uploc; return PRIVATE; } -"protected" { uploc; return PROTECTED; } -"public" { uploc; return PUBLIC; } -"ref" { uploc; return REF; } -"requires" { uploc; return REQUIRES; } -"set" { uploc; return SET; } -"signal" { uploc; return SIGNAL; } -"sizeof" { uploc; return SIZEOF; } -"static" { uploc; return STATIC; } -"struct" { uploc; return STRUCT; } -"switch" { uploc; return SWITCH; } -"return" { uploc; return RETURN; } -"this" { uploc; return THIS; } -"throw" { uploc; return THROW; } -"throws" { uploc; return THROWS; } -"true" { uploc; return VALA_TRUE; } -"try" { uploc; return TRY; } -"typeof" { uploc; return TYPEOF; } -"using" { uploc; return USING; } -"var" { uploc; return VAR; } -"virtual" { uploc; return VIRTUAL; } -"void" { uploc; return VOID; } -"volatile" { uploc; return VOLATILE; } -"weak" { uploc; return WEAK; } -"while" { uploc; return WHILE; } - -{real_literal} { uploc; yylval->str = g_strdup (yytext); return REAL_LITERAL; } -{integer_literal} { uploc; yylval->str = g_strdup (yytext); return INTEGER_LITERAL; } - -{character_literal} { uploc; yylval->str = g_strdup (yytext); return CHARACTER_LITERAL; } -{string_literal} { uploc; yylval->str = g_strdup (yytext); return STRING_LITERAL; } - -{ident} { uploc; yylval->str = g_strdup (yytext); return IDENTIFIER; } - -[ \t\r]+ { uploc; /* eat up whitespace */ } -[\n]+ { yylloc->first_line = yylloc->last_line = yylineno; yylloc->first_column = 1; yylloc->last_column = 0; } - -. { uploc; fprintf (stderr, "%d: syntax error: unexpected character ´%s´\n", yylloc->first_line, yytext); } diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala index 23ff065..5e62a7e 100644 --- a/vala/valaassignment.vala +++ b/vala/valaassignment.vala @@ -94,6 +94,7 @@ public class Vala.Assignment : Expression { } public enum Vala.AssignmentOperator { + NONE, SIMPLE, BITWISE_OR, BITWISE_AND, diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala index e60acc4..4ba7b0e 100644 --- a/vala/valabinaryexpression.vala +++ b/vala/valabinaryexpression.vala @@ -130,6 +130,7 @@ public class Vala.BinaryExpression : Expression { } public enum Vala.BinaryOperator { + NONE, PLUS, MINUS, MUL, diff --git a/vala/valaclass.vala b/vala/valaclass.vala index f760ebe..efb0865 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -193,10 +193,16 @@ public class Vala.Class : Typesymbol { */ public void add_method (Method! m) { if (m.instance || m is CreationMethod) { + if (m.this_parameter != null) { + m.scope.remove (m.this_parameter.name); + } m.this_parameter = new FormalParameter ("this", new ClassType (this)); m.scope.add (m.this_parameter.name, m.this_parameter); } if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) { + if (m.result_var != null) { + m.scope.remove (m.result_var.name); + } m.result_var = new VariableDeclarator ("result"); m.result_var.type_reference = m.return_type.copy (); m.scope.add (m.result_var.name, m.result_var); diff --git a/vala/valanamespace.vala b/vala/valanamespace.vala index c136523..ef31866 100644 --- a/vala/valanamespace.vala +++ b/vala/valanamespace.vala @@ -167,6 +167,60 @@ public class Vala.Namespace : Symbol { } /** + * Returns a copy of the list of enums. + * + * @return enum list + */ + public Collection get_enums () { + return new ReadOnlyCollection (enums); + } + + /** + * Returns a copy of the list of error domains. + * + * @return error domain list + */ + public Collection get_error_domains () { + return new ReadOnlyCollection (error_domains); + } + + /** + * Returns a copy of the list of fields. + * + * @return field list + */ + public Collection get_fields () { + return new ReadOnlyCollection (fields); + } + + /** + * Returns a copy of the list of constants. + * + * @return constant list + */ + public Collection get_constants () { + return new ReadOnlyCollection (constants); + } + + /** + * Returns a copy of the list of delegates. + * + * @return delegate list + */ + public Collection get_delegates () { + return new ReadOnlyCollection (delegates); + } + + /** + * Returns a copy of the list of methods. + * + * @return method list + */ + public Collection get_methods () { + return new ReadOnlyCollection (methods); + } + + /** * Adds the specified constant to this namespace. * * @param constant a constant diff --git a/vala/valaparser.vala b/vala/valaparser.vala index cc4039a..9b65799 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -1,6 +1,6 @@ /* valaparser.vala * - * Copyright (C) 2006-2007 Jürg Billeter + * Copyright (C) 2006-2008 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,14 +21,47 @@ */ using GLib; +using Gee; /** * Code visitor parsing all Vala source files. */ public class Vala.Parser : CodeVisitor { - private string comment; - private string _file_comment; - + Scanner scanner; + + CodeContext context; + + // token buffer + TokenInfo[] tokens; + // index of current token in buffer + int index; + // number of tokens in buffer + int size; + + string comment; + + const int BUFFER_SIZE = 32; + + struct TokenInfo { + public TokenType type; + public SourceLocation begin; + public SourceLocation end; + } + + enum ModifierFlags { + NONE, + ABSTRACT = 1 << 0, + CLASS = 1 << 1, + INLINE = 1 << 2, + OVERRIDE = 1 << 3, + STATIC = 1 << 4, + VIRTUAL = 1 << 5 + } + + construct { + tokens = new TokenInfo[BUFFER_SIZE]; + } + /** * Parse all source files in the specified code context and build a * code tree. @@ -36,57 +69,2608 @@ public class Vala.Parser : CodeVisitor { * @param context a code context */ public void parse (CodeContext! context) { + this.context = context; context.accept (this); } public override void visit_source_file (SourceFile! source_file) { if (source_file.filename.has_suffix (".vala") || source_file.filename.has_suffix (".vapi")) { parse_file (source_file); - source_file.comment = _file_comment; } + } - _file_comment = null; + inline bool next () { + index = (index + 1) % BUFFER_SIZE; + size--; + if (size <= 0) { + SourceLocation begin, end; + TokenType type = scanner.read_token (out begin, out end); + tokens[index].type = type; + tokens[index].begin = begin; + tokens[index].end = end; + size = 1; + } + return (tokens[index].type != TokenType.EOF); } - /** - * Adds the specified comment to the comment stack. - * - * @param comment_item a comment string - * @param file_comment true if file header comment, false otherwise - */ - public void push_comment (string! comment_item, bool file_comment) { - if (comment == null) { - comment = comment_item; + inline void prev () { + index = (index - 1 + BUFFER_SIZE) % BUFFER_SIZE; + size++; + assert (size <= BUFFER_SIZE); + } + + inline TokenType current () { + return tokens[index].type; + } + + inline bool accept (TokenType type) { + if (current () == type) { + next (); + return true; + } + return false; + } + + string get_error (string msg) { + var begin = get_location (); + next (); + Report.error (get_src (begin), "syntax error, " + msg); + return msg; + } + + inline bool expect (TokenType type) throws ParseError { + if (accept (type)) { + return true; + } + + throw new ParseError.SYNTAX (get_error ("expected %s".printf (type.to_string ()))); + } + + inline SourceLocation get_location () { + return tokens[index].begin; + } + + string get_last_string () { + int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE; + return ((string) tokens[last_index].begin.pos).ndup ((tokens[last_index].end.pos - tokens[last_index].begin.pos)); + } + + SourceReference get_src (SourceLocation begin) { + int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE; + + return new SourceReference (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column); + } + + SourceReference get_src_com (SourceLocation begin) { + int last_index = (index + BUFFER_SIZE - 1) % BUFFER_SIZE; + + var src = new SourceReference.with_comment (scanner.source_file, begin.line, begin.column, tokens[last_index].end.line, tokens[last_index].end.column, comment); + comment = null; + return src; + } + + void rollback (SourceLocation location) { + while (tokens[index].begin.pos != location.pos) { + prev (); + } + } + + void skip_identifier () throws ParseError { + // also accept keywords as identifiers where there is no conflict + switch (current ()) { + case TokenType.ABSTRACT: + case TokenType.AS: + case TokenType.BASE: + case TokenType.BREAK: + case TokenType.CASE: + case TokenType.CATCH: + case TokenType.CLASS: + case TokenType.CONST: + case TokenType.CONSTRUCT: + case TokenType.CONTINUE: + case TokenType.DEFAULT: + case TokenType.DELEGATE: + case TokenType.DELETE: + case TokenType.DO: + case TokenType.ELSE: + case TokenType.ENUM: + case TokenType.ENSURES: + case TokenType.ERRORDOMAIN: + case TokenType.FALSE: + case TokenType.FINALLY: + case TokenType.FOR: + case TokenType.FOREACH: + case TokenType.GET: + case TokenType.IDENTIFIER: + case TokenType.IF: + case TokenType.IN: + case TokenType.INLINE: + case TokenType.INTERFACE: + case TokenType.IS: + case TokenType.LOCK: + case TokenType.NAMESPACE: + case TokenType.NEW: + case TokenType.NULL: + case TokenType.OUT: + case TokenType.OVERRIDE: + case TokenType.PRIVATE: + case TokenType.PROTECTED: + case TokenType.PUBLIC: + case TokenType.REF: + case TokenType.REQUIRES: + case TokenType.RETURN: + case TokenType.SET: + case TokenType.SIGNAL: + case TokenType.SIZEOF: + case TokenType.STATIC: + case TokenType.STRUCT: + case TokenType.SWITCH: + case TokenType.THIS: + case TokenType.THROW: + case TokenType.THROWS: + case TokenType.TRUE: + case TokenType.TRY: + case TokenType.TYPEOF: + case TokenType.USING: + case TokenType.VAR: + case TokenType.VIRTUAL: + case TokenType.VOID: + case TokenType.VOLATILE: + case TokenType.WEAK: + case TokenType.WHILE: + next (); + return; + } + + throw new ParseError.SYNTAX (get_error ("expected identifier")); + } + + string parse_identifier () throws ParseError { + skip_identifier (); + return get_last_string (); + } + + Expression parse_literal () throws ParseError { + var begin = get_location (); + + switch (current ()) { + case TokenType.TRUE: + next (); + return context.create_boolean_literal (true, get_src (begin)); + case TokenType.FALSE: + next (); + return context.create_boolean_literal (false, get_src (begin)); + case TokenType.INTEGER_LITERAL: + next (); + return context.create_integer_literal (get_last_string (), get_src (begin)); + case TokenType.REAL_LITERAL: + next (); + return context.create_real_literal (get_last_string (), get_src (begin)); + case TokenType.CHARACTER_LITERAL: + next (); + return context.create_character_literal (get_last_string (), get_src (begin)); + case TokenType.STRING_LITERAL: + next (); + return context.create_string_literal (get_last_string (), get_src (begin)); + case TokenType.NULL: + next (); + return context.create_null_literal (get_src (begin)); + } + + throw new ParseError.SYNTAX (get_error ("expected literal")); + } + + public void parse_file (SourceFile source_file) { + scanner = new Scanner (source_file); + + index = -1; + size = 0; + + next (); + + try { + parse_using_directives (); + parse_declarations (context.root, true); + } catch (ParseError e) { + // already reported + } + + scanner = null; + } + + void skip_symbol_name () throws ParseError { + do { + skip_identifier (); + } while (accept (TokenType.DOT)); + } + + UnresolvedSymbol parse_symbol_name () throws ParseError { + var begin = get_location (); + UnresolvedSymbol sym = null; + do { + string name = parse_identifier (); + sym = new UnresolvedSymbol (sym, name, get_src (begin)); + } while (accept (TokenType.DOT)); + return sym; + } + + void skip_type () throws ParseError { + if (accept (TokenType.VOID)) { + while (accept (TokenType.STAR)) { + } + return; + } + accept (TokenType.REF); + accept (TokenType.OUT); + accept (TokenType.WEAK); + skip_symbol_name (); + skip_type_argument_list (); + while (accept (TokenType.STAR)) { + } + if (accept (TokenType.OPEN_BRACKET)) { + do { + if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) { + parse_expression (); + } + } while (accept (TokenType.COMMA)); + expect (TokenType.CLOSE_BRACKET); + } + accept (TokenType.OP_NEG); + accept (TokenType.INTERR); + accept (TokenType.HASH); + } + + DataType parse_type () throws ParseError { + var begin = get_location (); + + if (accept (TokenType.VOID)) { + DataType type = new VoidType (); + while (accept (TokenType.STAR)) { + type = new PointerType (type); + } + return type; + } + + bool is_ref = accept (TokenType.REF); + bool is_out = !is_ref && accept (TokenType.OUT); + + bool is_weak = accept (TokenType.WEAK); + + var sym = parse_symbol_name (); + var type_arg_list = parse_type_argument_list (false); + + int stars = 0; + while (accept (TokenType.STAR)) { + stars++; + } + + int array_rank = 0; + if (accept (TokenType.OPEN_BRACKET)) { + do { + array_rank++; + // support for stack-allocated arrays + // also required for decision between expression and declaration statement + if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) { + parse_expression (); + } + } + while (accept (TokenType.COMMA)); + expect (TokenType.CLOSE_BRACKET); + } + + // deprecated + accept (TokenType.OP_NEG); + + bool nullable = accept (TokenType.INTERR); + + bool transfers_ownership = accept (TokenType.HASH); + + var type = new UnresolvedType.from_symbol (sym, get_src (begin)); + if (type_arg_list != null) { + foreach (DataType type_arg in type_arg_list) { + type.add_type_argument (type_arg); + } + } + type.is_ref = is_ref; + type.is_out = is_out; + type.is_weak = is_weak; + type.pointer_level = stars; + type.array_rank = array_rank; + type.nullable = nullable; + type.requires_null_check = nullable; + type.transfers_ownership = transfers_ownership; + return type; + } + + Gee.List parse_argument_list () throws ParseError { + var list = new ArrayList (); + if (current () != TokenType.CLOSE_PARENS) { + do { + list.add (parse_expression ()); + } while (accept (TokenType.COMMA)); + } + return list; + } + + Expression parse_primary_expression () throws ParseError { + var begin = get_location (); + + Expression expr; + + switch (current ()) { + case TokenType.TRUE: + case TokenType.FALSE: + case TokenType.INTEGER_LITERAL: + case TokenType.REAL_LITERAL: + case TokenType.CHARACTER_LITERAL: + case TokenType.STRING_LITERAL: + case TokenType.NULL: + expr = parse_literal (); + break; + case TokenType.OPEN_PARENS: + expr = parse_tuple (); + break; + case TokenType.THIS: + expr = parse_this_access (); + break; + case TokenType.BASE: + expr = parse_base_access (); + break; + case TokenType.NEW: + expr = parse_object_or_array_creation_expression (); + break; + case TokenType.SIZEOF: + expr = parse_sizeof_expression (); + break; + case TokenType.TYPEOF: + expr = parse_typeof_expression (); + break; + default: + expr = parse_simple_name (); + break; + } + + // process primary expressions that start with an inner primary expression + bool found = true; + while (found) { + switch (current ()) { + case TokenType.DOT: + expr = parse_member_access (begin, expr); + break; + case TokenType.OP_PTR: + expr = parse_pointer_member_access (begin, expr); + break; + case TokenType.OPEN_PARENS: + expr = parse_invocation_expression (begin, expr); + break; + case TokenType.OPEN_BRACKET: + expr = parse_element_access (begin, expr); + break; + case TokenType.OP_INC: + expr = parse_post_increment_expression (begin, expr); + break; + case TokenType.OP_DEC: + expr = parse_post_decrement_expression (begin, expr); + break; + default: + found = false; + break; + } + } + + return expr; + } + + Expression parse_simple_name () throws ParseError { + var begin = get_location (); + string id = parse_identifier (); + var type_arg_list = parse_type_argument_list (true); + var expr = context.create_member_access (null, id, get_src (begin)); + if (type_arg_list != null) { + foreach (DataType type_arg in type_arg_list) { + expr.add_type_argument (type_arg); + } + } + return expr; + } + + Expression parse_tuple () throws ParseError { + var begin = get_location (); + expect (TokenType.OPEN_PARENS); + var expr_list = new ArrayList (); + if (current () != TokenType.CLOSE_PARENS) { + do { + expr_list.add (parse_expression ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + if (expr_list.size != 1) { + var tuple = new Tuple (); + foreach (Expression expr in expr_list) { + tuple.add_expression (expr); + } + return tuple; + } + return context.create_parenthesized_expression (expr_list.get (0), get_src (begin)); + } + + Expression parse_member_access (SourceLocation begin, Expression inner) throws ParseError { + expect (TokenType.DOT); + string id = parse_identifier (); + var type_arg_list = parse_type_argument_list (true); + var expr = context.create_member_access (inner, id, get_src (begin)); + if (type_arg_list != null) { + foreach (DataType type_arg in type_arg_list) { + expr.add_type_argument (type_arg); + } + } + return expr; + } + + Expression parse_pointer_member_access (SourceLocation begin, Expression inner) throws ParseError { + expect (TokenType.OP_PTR); + string id = parse_identifier (); + var type_arg_list = parse_type_argument_list (true); + var expr = context.create_member_access_pointer (inner, id, get_src (begin)); + if (type_arg_list != null) { + foreach (DataType type_arg in type_arg_list) { + expr.add_type_argument (type_arg); + } + } + return expr; + } + + Expression parse_invocation_expression (SourceLocation begin, Expression inner) throws ParseError { + expect (TokenType.OPEN_PARENS); + var arg_list = parse_argument_list (); + expect (TokenType.CLOSE_PARENS); + + var expr = context.create_invocation_expression (inner, get_src (begin)); + foreach (Expression arg in arg_list) { + expr.add_argument (arg); + } + return expr; + } + + Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError { + expect (TokenType.OPEN_BRACKET); + var index_list = parse_expression_list (); + expect (TokenType.CLOSE_BRACKET); + + var expr = context.create_element_access (inner, get_src (begin)); + foreach (Expression index in index_list) { + expr.append_index (index); + } + return expr; + } + + Gee.List parse_expression_list () throws ParseError { + var list = new ArrayList (); + do { + list.add (parse_expression ()); + } while (accept (TokenType.COMMA)); + return list; + } + + Expression parse_this_access () throws ParseError { + var begin = get_location (); + expect (TokenType.THIS); + return context.create_member_access (null, "this", get_src (begin)); + } + + Expression parse_base_access () throws ParseError { + var begin = get_location (); + expect (TokenType.BASE); + return context.create_base_access (get_src (begin)); + } + + Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError { + expect (TokenType.OP_INC); + return context.create_postfix_expression (inner, true, get_src (begin)); + } + + Expression parse_post_decrement_expression (SourceLocation begin, Expression inner) throws ParseError { + expect (TokenType.OP_DEC); + return context.create_postfix_expression (inner, false, get_src (begin)); + } + + Expression parse_object_or_array_creation_expression () throws ParseError { + var begin = get_location (); + expect (TokenType.NEW); + var member = parse_member_name (); + if (accept (TokenType.OPEN_PARENS)) { + return parse_object_creation_expression (begin, member); + } else if (accept (TokenType.OPEN_BRACKET)) { + return parse_array_creation_expression (begin, member); } else { - comment = "%s\n%s".printf (comment, comment_item); + throw new ParseError.SYNTAX (get_error ("expected ( or [")); } - if (file_comment) { - _file_comment = comment; - comment = null; + } + + Expression parse_object_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError { + member.creation_member = true; + var arg_list = parse_argument_list (); + expect (TokenType.CLOSE_PARENS); + var init_list = parse_object_initializer (); + + var expr = context.create_object_creation_expression (member, get_src (begin)); + foreach (Expression arg in arg_list) { + expr.add_argument (arg); } + foreach (MemberInitializer initializer in init_list) { + expr.add_member_initializer (initializer); + } + return expr; } - - /** - * Clears and returns the content of the comment stack. - * - * @return saved comment - */ - public string pop_comment () { - if (comment == null) { + + Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError { + bool size_specified = false; + var size_specifier_list = new ArrayList (); + do { + Expression size = null; + if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) { + size = parse_expression (); + size_specified = true; + } + size_specifier_list.add (size); + } while (accept (TokenType.COMMA)); + expect (TokenType.CLOSE_BRACKET); + InitializerList initializer = null; + if (current () == TokenType.OPEN_BRACE) { + initializer = parse_initializer (); + } + var expr = context.create_array_creation_expression (UnresolvedType.new_from_expression (member), size_specifier_list.size, initializer, get_src (begin)); + if (size_specified) { + foreach (Expression size in size_specifier_list) { + expr.append_size (size); + } + } + return expr; + } + + Gee.List parse_object_initializer () throws ParseError { + var list = new ArrayList (); + if (accept (TokenType.OPEN_BRACE)) { + do { + list.add (parse_member_initializer ()); + } while (accept (TokenType.COMMA)); + expect (TokenType.CLOSE_BRACE); + } + return list; + } + + MemberInitializer parse_member_initializer () throws ParseError { + var begin = get_location (); + string id = parse_identifier (); + expect (TokenType.ASSIGN); + var expr = parse_expression (); + + return new MemberInitializer (id, expr, get_src (begin)); + } + + Expression parse_sizeof_expression () throws ParseError { + var begin = get_location (); + expect (TokenType.SIZEOF); + expect (TokenType.OPEN_PARENS); + var type = parse_type (); + expect (TokenType.CLOSE_PARENS); + + return context.create_sizeof_expression (type, get_src (begin)); + } + + Expression parse_typeof_expression () throws ParseError { + var begin = get_location (); + expect (TokenType.TYPEOF); + expect (TokenType.OPEN_PARENS); + var type = parse_type (); + expect (TokenType.CLOSE_PARENS); + + return context.create_typeof_expression (type, get_src (begin)); + } + + UnaryOperator get_unary_operator (TokenType token_type) { + switch (token_type) { + case TokenType.PLUS: return UnaryOperator.PLUS; + case TokenType.MINUS: return UnaryOperator.MINUS; + case TokenType.OP_NEG: return UnaryOperator.LOGICAL_NEGATION; + case TokenType.TILDE: return UnaryOperator.BITWISE_COMPLEMENT; + case TokenType.OP_INC: return UnaryOperator.INCREMENT; + case TokenType.OP_DEC: return UnaryOperator.DECREMENT; + case TokenType.REF: return UnaryOperator.REF; + case TokenType.OUT: return UnaryOperator.OUT; + default: return UnaryOperator.NONE; + } + } + + Expression parse_unary_expression () throws ParseError { + var begin = get_location (); + var operator = get_unary_operator (current ()); + if (operator != UnaryOperator.NONE) { + next (); + var op = parse_unary_expression (); + return context.create_unary_expression (operator, op, get_src (begin)); + } + switch (current ()) { + case TokenType.HASH: + next (); + var op = parse_unary_expression (); + return context.create_reference_transfer_expression (op, get_src (begin)); + case TokenType.OPEN_PARENS: + next (); + switch (current ()) { + case TokenType.VOID: + case TokenType.IDENTIFIER: + var type = parse_type (); + if (accept (TokenType.CLOSE_PARENS)) { + // check follower to decide whether to create cast expression + switch (current ()) { + case TokenType.OP_NEG: + case TokenType.TILDE: + case TokenType.OPEN_PARENS: + case TokenType.TRUE: + case TokenType.FALSE: + case TokenType.INTEGER_LITERAL: + case TokenType.REAL_LITERAL: + case TokenType.CHARACTER_LITERAL: + case TokenType.STRING_LITERAL: + case TokenType.NULL: + case TokenType.THIS: + case TokenType.BASE: + case TokenType.NEW: + case TokenType.SIZEOF: + case TokenType.TYPEOF: + case TokenType.IDENTIFIER: + var inner = parse_unary_expression (); + return context.create_cast_expression (inner, type, get_src (begin), false); + } + } + break; + } + // no cast expression + rollback (begin); + break; + case TokenType.STAR: + next (); + var op = parse_unary_expression (); + return context.create_pointer_indirection (op, get_src (begin)); + case TokenType.BITWISE_AND: + next (); + var op = parse_unary_expression (); + return context.create_addressof_expression (op, get_src (begin)); + } + + return parse_primary_expression (); + } + + BinaryOperator get_binary_operator (TokenType token_type) { + switch (token_type) { + case TokenType.STAR: return BinaryOperator.MUL; + case TokenType.DIV: return BinaryOperator.DIV; + case TokenType.PERCENT: return BinaryOperator.MOD; + case TokenType.PLUS: return BinaryOperator.PLUS; + case TokenType.MINUS: return BinaryOperator.MINUS; + case TokenType.OP_LT: return BinaryOperator.LESS_THAN; + case TokenType.OP_GT: return BinaryOperator.GREATER_THAN; + case TokenType.OP_LE: return BinaryOperator.LESS_THAN_OR_EQUAL; + case TokenType.OP_GE: return BinaryOperator.GREATER_THAN_OR_EQUAL; + case TokenType.OP_EQ: return BinaryOperator.EQUALITY; + case TokenType.OP_NE: return BinaryOperator.INEQUALITY; + default: return BinaryOperator.NONE; + } + } + + Expression parse_multiplicative_expression () throws ParseError { + var begin = get_location (); + var left = parse_unary_expression (); + bool found = true; + while (found) { + var operator = get_binary_operator (current ()); + switch (operator) { + case BinaryOperator.MUL: + case BinaryOperator.DIV: + case BinaryOperator.MOD: + next (); + var right = parse_unary_expression (); + left = context.create_binary_expression (operator, left, right, get_src (begin)); + break; + default: + found = false; + break; + } + } + return left; + } + + Expression parse_additive_expression () throws ParseError { + var begin = get_location (); + var left = parse_multiplicative_expression (); + bool found = true; + while (found) { + var operator = get_binary_operator (current ()); + switch (operator) { + case BinaryOperator.PLUS: + case BinaryOperator.MINUS: + next (); + var right = parse_multiplicative_expression (); + left = context.create_binary_expression (operator, left, right, get_src (begin)); + break; + default: + found = false; + break; + } + } + return left; + } + + Expression parse_shift_expression () throws ParseError { + var begin = get_location (); + var left = parse_additive_expression (); + bool found = true; + while (found) { + switch (current ()) { + case TokenType.OP_SHIFT_LEFT: + next (); + var right = parse_additive_expression (); + left = context.create_binary_expression (BinaryOperator.SHIFT_LEFT, left, right, get_src (begin)); + break; + // don't use OP_SHIFT_RIGHT to support >> for nested generics + case TokenType.OP_GT: + char* first_gt_pos = tokens[index].begin.pos; + next (); + // only accept >> when there is no space between the two > signs + if (current () == TokenType.OP_GT && tokens[index].begin.pos == first_gt_pos + 1) { + next (); + var right = parse_additive_expression (); + left = context.create_binary_expression (BinaryOperator.SHIFT_RIGHT, left, right, get_src (begin)); + } else { + prev (); + found = false; + } + break; + default: + found = false; + break; + } + } + return left; + } + + Expression parse_relational_expression () throws ParseError { + var begin = get_location (); + var left = parse_shift_expression (); + bool found = true; + while (found) { + var operator = get_binary_operator (current ()); + switch (operator) { + case BinaryOperator.LESS_THAN: + case BinaryOperator.LESS_THAN_OR_EQUAL: + case BinaryOperator.GREATER_THAN_OR_EQUAL: + next (); + var right = parse_shift_expression (); + left = context.create_binary_expression (operator, left, right, get_src (begin)); + break; + case BinaryOperator.GREATER_THAN: + next (); + // ignore >> and >>= (two tokens due to generics) + if (current () != TokenType.OP_GT && current () != TokenType.OP_GE) { + var right = parse_shift_expression (); + left = context.create_binary_expression (operator, left, right, get_src (begin)); + } else { + prev (); + found = false; + } + break; + default: + switch (current ()) { + case TokenType.IS: + next (); + var type = parse_type (); + left = context.create_type_check (left, type, get_src (begin)); + break; + case TokenType.AS: + next (); + var type = parse_type (); + left = context.create_cast_expression (left, type, get_src (begin), true); + break; + default: + found = false; + break; + } + break; + } + } + return left; + } + + Expression parse_equality_expression () throws ParseError { + var begin = get_location (); + var left = parse_relational_expression (); + bool found = true; + while (found) { + var operator = get_binary_operator (current ()); + switch (operator) { + case BinaryOperator.EQUALITY: + case BinaryOperator.INEQUALITY: + next (); + var right = parse_relational_expression (); + left = context.create_binary_expression (operator, left, right, get_src (begin)); + break; + default: + found = false; + break; + } + } + return left; + } + + Expression parse_and_expression () throws ParseError { + var begin = get_location (); + var left = parse_equality_expression (); + while (accept (TokenType.BITWISE_AND)) { + var right = parse_equality_expression (); + left = context.create_binary_expression (BinaryOperator.BITWISE_AND, left, right, get_src (begin)); + } + return left; + } + + Expression parse_exclusive_or_expression () throws ParseError { + var begin = get_location (); + var left = parse_and_expression (); + while (accept (TokenType.CARRET)) { + var right = parse_and_expression (); + left = context.create_binary_expression (BinaryOperator.BITWISE_XOR, left, right, get_src (begin)); + } + return left; + } + + Expression parse_inclusive_or_expression () throws ParseError { + var begin = get_location (); + var left = parse_exclusive_or_expression (); + while (accept (TokenType.BITWISE_OR)) { + var right = parse_exclusive_or_expression (); + left = context.create_binary_expression (BinaryOperator.BITWISE_OR, left, right, get_src (begin)); + } + return left; + } + + Expression parse_in_expression () throws ParseError { + var begin = get_location (); + var left = parse_inclusive_or_expression (); + while (accept (TokenType.IN)) { + var right = parse_inclusive_or_expression (); + left = context.create_binary_expression (BinaryOperator.IN, left, right, get_src (begin)); + } + return left; + } + + Expression parse_conditional_and_expression () throws ParseError { + var begin = get_location (); + var left = parse_in_expression (); + while (accept (TokenType.OP_AND)) { + var right = parse_in_expression (); + left = context.create_binary_expression (BinaryOperator.AND, left, right, get_src (begin)); + } + return left; + } + + Expression parse_conditional_or_expression () throws ParseError { + var begin = get_location (); + var left = parse_conditional_and_expression (); + while (accept (TokenType.OP_OR)) { + var right = parse_conditional_and_expression (); + left = context.create_binary_expression (BinaryOperator.OR, left, right, get_src (begin)); + } + return left; + } + + Expression parse_conditional_expression () throws ParseError { + var begin = get_location (); + var condition = parse_conditional_or_expression (); + if (accept (TokenType.INTERR)) { + var true_expr = parse_expression (); + expect (TokenType.COLON); + var false_expr = parse_expression (); + return context.create_conditional_expression (condition, true_expr, false_expr, get_src (begin)); + } else { + return condition; + } + } + + Expression parse_lambda_expression () throws ParseError { + var begin = get_location (); + Gee.List params = new ArrayList (); + if (accept (TokenType.OPEN_PARENS)) { + if (current () != TokenType.CLOSE_PARENS) { + do { + params.add (parse_identifier ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + } else { + params.add (parse_identifier ()); + } + expect (TokenType.LAMBDA); + + LambdaExpression lambda; + if (current () == TokenType.OPEN_BRACE) { + var block = parse_block (); + lambda = context.create_lambda_expression_with_statement_body (block, get_src (begin)); + } else { + var expr = parse_expression (); + lambda = context.create_lambda_expression (expr, get_src (begin)); + } + foreach (string param in params) { + lambda.add_parameter (param); + } + return lambda; + } + + AssignmentOperator get_assignment_operator (TokenType token_type) { + switch (token_type) { + case TokenType.ASSIGN: return AssignmentOperator.SIMPLE; + case TokenType.ASSIGN_ADD: return AssignmentOperator.ADD; + case TokenType.ASSIGN_SUB: return AssignmentOperator.SUB; + case TokenType.ASSIGN_BITWISE_OR: return AssignmentOperator.BITWISE_OR; + case TokenType.ASSIGN_BITWISE_AND: return AssignmentOperator.BITWISE_AND; + case TokenType.ASSIGN_BITWISE_XOR: return AssignmentOperator.BITWISE_XOR; + case TokenType.ASSIGN_DIV: return AssignmentOperator.DIV; + case TokenType.ASSIGN_MUL: return AssignmentOperator.MUL; + case TokenType.ASSIGN_PERCENT: return AssignmentOperator.PERCENT; + case TokenType.ASSIGN_SHIFT_LEFT: return AssignmentOperator.SHIFT_LEFT; + default: return AssignmentOperator.NONE; + } + } + + Expression parse_expression () throws ParseError { + var begin = get_location (); + Expression expr = parse_conditional_expression (); + + if (current () == TokenType.LAMBDA) { + rollback (begin); + return parse_lambda_expression (); + } + + while (true) { + var operator = get_assignment_operator (current ()); + if (operator != AssignmentOperator.NONE) { + next (); + var rhs = parse_expression (); + expr = context.create_assignment (expr, rhs, operator); + } else if (current () == TokenType.OP_GT) { // >>= + char* first_gt_pos = tokens[index].begin.pos; + next (); + // only accept >>= when there is no space between the two > signs + if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) { + next (); + var rhs = parse_expression (); + expr = context.create_assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT); + } else { + prev (); + break; + } + } else { + break; + } + } + + return expr; + } + + Statement parse_statement () throws ParseError { + comment = scanner.pop_comment (); + switch (current ()) { + case TokenType.OPEN_BRACE: + return parse_block (); + case TokenType.SEMICOLON: + return parse_empty_statement (); + case TokenType.IF: + return parse_if_statement (); + case TokenType.SWITCH: + return parse_switch_statement (); + case TokenType.WHILE: + return parse_while_statement (); + case TokenType.DO: + return parse_do_statement (); + case TokenType.FOR: + return parse_for_statement (); + case TokenType.FOREACH: + return parse_foreach_statement (); + case TokenType.BREAK: + return parse_break_statement (); + case TokenType.CONTINUE: + return parse_continue_statement (); + case TokenType.RETURN: + return parse_return_statement (); + case TokenType.THROW: + return parse_throw_statement (); + case TokenType.TRY: + return parse_try_statement (); + case TokenType.LOCK: + return parse_lock_statement (); + case TokenType.DELETE: + return parse_delete_statement (); + case TokenType.VAR: + return parse_declaration_statement (); + case TokenType.OP_INC: + case TokenType.OP_DEC: + case TokenType.BASE: + case TokenType.THIS: + case TokenType.OPEN_PARENS: + case TokenType.STAR: + return parse_expression_statement (); + } + + if (is_expression ()) { + return parse_expression_statement (); + } else { + return parse_declaration_statement (); + } + } + + bool is_expression () throws ParseError { + var begin = get_location (); + + // decide between declaration and expression statement + skip_type (); + switch (current ()) { + // invocation expression + case TokenType.OPEN_PARENS: + // postfix increment + case TokenType.OP_INC: + // postfix decrement + case TokenType.OP_DEC: + // assignments + case TokenType.ASSIGN: + case TokenType.ASSIGN_ADD: + case TokenType.ASSIGN_BITWISE_AND: + case TokenType.ASSIGN_BITWISE_OR: + case TokenType.ASSIGN_BITWISE_XOR: + case TokenType.ASSIGN_DIV: + case TokenType.ASSIGN_MUL: + case TokenType.ASSIGN_PERCENT: + case TokenType.ASSIGN_SHIFT_LEFT: + case TokenType.ASSIGN_SUB: + case TokenType.OP_GT: // >>= + // member access + case TokenType.DOT: + // pointer member access + case TokenType.OP_PTR: + rollback (begin); + return true; + } + + rollback (begin); + return false; + } + + Block parse_embedded_statement () throws ParseError { + if (current () == TokenType.OPEN_BRACE) { + return parse_block (); + } + + comment = scanner.pop_comment (); + + var block = context.create_block (); + block.add_statement (parse_embedded_statement_without_block ()); + return block; + + } + + Statement parse_embedded_statement_without_block () throws ParseError { + switch (current ()) { + case TokenType.SEMICOLON: return parse_empty_statement (); + case TokenType.IF: return parse_if_statement (); + case TokenType.SWITCH: return parse_switch_statement (); + case TokenType.WHILE: return parse_while_statement (); + case TokenType.DO: return parse_do_statement (); + case TokenType.FOR: return parse_for_statement (); + case TokenType.FOREACH: return parse_foreach_statement (); + case TokenType.BREAK: return parse_break_statement (); + case TokenType.CONTINUE: return parse_continue_statement (); + case TokenType.RETURN: return parse_return_statement (); + case TokenType.THROW: return parse_throw_statement (); + case TokenType.TRY: return parse_try_statement (); + case TokenType.LOCK: return parse_lock_statement (); + case TokenType.DELETE: return parse_delete_statement (); + default: return parse_expression_statement (); + } + } + + Block parse_block () throws ParseError { + var begin = get_location (); + Gee.List list = new ArrayList (); + expect (TokenType.OPEN_BRACE); + var block = context.create_block (get_src_com (begin)); + while (current () != TokenType.CLOSE_BRACE) { + try { + var stmt = parse_statement (); + if (stmt == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in statement"); + } + block.add_statement (stmt); + } catch (ParseError e) { + if (recover () != RecoveryState.STATEMENT_BEGIN) { + // beginning of next declaration or end of file reached + // return what we have so far + return block; + } + } + } + if (!accept (TokenType.CLOSE_BRACE)) { + Report.error (new SourceReference (scanner.source_file, tokens[index].begin.line, tokens[index].begin.column, tokens[index].end.line, tokens[index].end.column), "expected `}'"); + } + + return block; + } + + Statement parse_empty_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.SEMICOLON); + return context.create_empty_statement (get_src_com (begin)); + } + + Statement parse_declaration_statement () throws ParseError { + var begin = get_location (); + var decl = parse_local_variable_declaration (); + expect (TokenType.SEMICOLON); + return context.create_declaration_statement (decl, get_src_com (begin)); + } + + LocalVariableDeclaration parse_local_variable_declaration () throws ParseError { + var begin = get_location (); + LocalVariableDeclaration decl; + if (accept (TokenType.VAR)) { + var declarators = parse_variable_declarators (); + decl = context.create_local_variable_declaration_var_type (get_src (begin)); + foreach (VariableDeclarator var_decl in declarators) { + decl.add_declarator (var_decl); + } + } else { + var type = parse_type (); + var declarators = parse_variable_declarators (); + if (!((UnresolvedType) type).is_weak) { + type.takes_ownership = true; + } + type.requires_null_check = false; + type.nullable = true; + decl = context.create_local_variable_declaration (type, get_src (begin)); + foreach (VariableDeclarator var_decl in declarators) { + var_decl.type_reference = type.copy (); + decl.add_declarator (var_decl); + } + } + return decl; + } + + Statement parse_expression_statement () throws ParseError { + var begin = get_location (); + var expr = parse_statement_expression (); + expect (TokenType.SEMICOLON); + return context.create_expression_statement (expr, get_src_com (begin)); + } + + Expression parse_statement_expression () throws ParseError { + // invocation expression, assignment, + // or pre/post increment/decrement expression + return parse_expression (); + } + + Statement parse_if_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.IF); + expect (TokenType.OPEN_PARENS); + var condition = parse_expression (); + expect (TokenType.CLOSE_PARENS); + var src = get_src_com (begin); + var true_stmt = parse_embedded_statement (); + Block false_stmt = null; + if (accept (TokenType.ELSE)) { + false_stmt = parse_embedded_statement (); + } + return context.create_if_statement (condition, true_stmt, false_stmt, src); + } + + Statement parse_switch_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.SWITCH); + expect (TokenType.OPEN_PARENS); + var condition = parse_expression (); + expect (TokenType.CLOSE_PARENS); + var stmt = context.create_switch_statement (condition, get_src_com (begin)); + expect (TokenType.OPEN_BRACE); + while (current () != TokenType.CLOSE_BRACE) { + var section = context.create_switch_section (get_src_com (begin)); + do { + if (accept (TokenType.CASE)) { + section.add_label (context.create_switch_label (parse_expression (), get_src_com (begin))); + } else { + expect (TokenType.DEFAULT); + section.add_label (context.create_switch_label_with_default (get_src_com (begin))); + } + expect (TokenType.COLON); + } while (current () == TokenType.CASE || current () == TokenType.DEFAULT); + while (current () != TokenType.CLOSE_BRACE + && current () != TokenType.CASE + && current () != TokenType.DEFAULT) { + section.add_statement (parse_statement ()); + } + stmt.add_section (section); + } + expect (TokenType.CLOSE_BRACE); + return stmt; + } + + Statement parse_while_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.WHILE); + expect (TokenType.OPEN_PARENS); + var condition = parse_expression (); + expect (TokenType.CLOSE_PARENS); + var body = parse_embedded_statement (); + return context.create_while_statement (condition, body, get_src_com (begin)); + } + + Statement parse_do_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.DO); + var body = parse_embedded_statement (); + expect (TokenType.WHILE); + expect (TokenType.OPEN_PARENS); + var condition = parse_expression (); + expect (TokenType.CLOSE_PARENS); + expect (TokenType.SEMICOLON); + return context.create_do_statement (body, condition, get_src_com (begin)); + } + + Statement parse_for_statement () throws ParseError { + var begin = get_location (); + Block block = null; + expect (TokenType.FOR); + expect (TokenType.OPEN_PARENS); + var initializer_list = new ArrayList (); + if (!accept (TokenType.SEMICOLON)) { + bool is_expr; + switch (current ()) { + case TokenType.VAR: + is_expr = false; + break; + case TokenType.OP_INC: + case TokenType.OP_DEC: + is_expr = true; + break; + default: + is_expr = is_expression (); + break; + } + + if (is_expr) { + do { + initializer_list.add (parse_statement_expression ()); + } while (accept (TokenType.COMMA)); + expect (TokenType.SEMICOLON); + } else { + block = context.create_block (get_src (begin)); + block.add_statement (parse_declaration_statement ()); + } + } + Expression condition = null; + if (current () != TokenType.SEMICOLON) { + condition = parse_expression (); + } + expect (TokenType.SEMICOLON); + var iterator_list = new ArrayList (); + if (current () != TokenType.CLOSE_PARENS) { + do { + iterator_list.add (parse_statement_expression ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + var src = get_src_com (begin); + var body = parse_embedded_statement (); + var stmt = context.create_for_statement (condition, body, src); + foreach (Expression init in initializer_list) { + stmt.add_initializer (init); + } + foreach (Expression iter in iterator_list) { + stmt.add_iterator (iter); + } + if (block != null) { + block.add_statement (stmt); + return block; + } else { + return stmt; + } + } + + Statement parse_foreach_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.FOREACH); + expect (TokenType.OPEN_PARENS); + var type = parse_type (); + var unresolved_type = type as UnresolvedType; + if (unresolved_type != null && !unresolved_type.is_weak) { + unresolved_type.takes_ownership = true; + } + string id = parse_identifier (); + expect (TokenType.IN); + var collection = parse_expression (); + expect (TokenType.CLOSE_PARENS); + var src = get_src_com (begin); + var body = parse_embedded_statement (); + return context.create_foreach_statement (type, id, collection, body, src); + } + + Statement parse_break_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.BREAK); + expect (TokenType.SEMICOLON); + return context.create_break_statement (get_src_com (begin)); + } + + Statement parse_continue_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.CONTINUE); + expect (TokenType.SEMICOLON); + return context.create_continue_statement (get_src_com (begin)); + } + + Statement parse_return_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.RETURN); + Expression expr = null; + if (current () != TokenType.SEMICOLON) { + expr = parse_expression (); + } + expect (TokenType.SEMICOLON); + return context.create_return_statement (expr, get_src_com (begin)); + } + + Statement parse_throw_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.THROW); + var expr = parse_expression (); + expect (TokenType.SEMICOLON); + return context.create_throw_statement (expr, get_src_com (begin)); + } + + Statement parse_try_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.TRY); + var try_block = parse_block (); + Block finally_clause = null; + var catch_clauses = new ArrayList (); + if (current () == TokenType.CATCH) { + parse_catch_clauses (catch_clauses); + if (current () == TokenType.FINALLY) { + finally_clause = parse_finally_clause (); + } + } else { + finally_clause = parse_finally_clause (); + } + var stmt = context.create_try_statement (try_block, finally_clause, get_src_com (begin)); + foreach (CatchClause clause in catch_clauses) { + stmt.add_catch_clause (clause); + } + return stmt; + } + + void parse_catch_clauses (Gee.List catch_clauses) throws ParseError { + while (accept (TokenType.CATCH)) { + var begin = get_location (); + DataType type = null; + string id = null; + if (accept (TokenType.OPEN_PARENS)) { + type = parse_type (); + id = parse_identifier (); + expect (TokenType.CLOSE_PARENS); + } + var block = parse_block (); + catch_clauses.add (context.create_catch_clause (type, id, block, get_src (begin))); + } + } + + Block parse_finally_clause () throws ParseError { + expect (TokenType.FINALLY); + return parse_block (); + } + + Statement parse_lock_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.LOCK); + expect (TokenType.OPEN_PARENS); + var expr = parse_expression (); + expect (TokenType.CLOSE_PARENS); + var stmt = parse_embedded_statement (); + return context.create_lock_statement (expr, stmt, get_src_com (begin)); + } + + Statement parse_delete_statement () throws ParseError { + var begin = get_location (); + expect (TokenType.DELETE); + var expr = parse_expression (); + expect (TokenType.SEMICOLON); + return context.create_delete_statement (expr, get_src_com (begin)); + } + + Gee.List parse_attributes () throws ParseError { + if (current () != TokenType.OPEN_BRACKET) { return null; } + var attrs = new ArrayList (); + while (accept (TokenType.OPEN_BRACKET)) { + do { + var begin = get_location (); + string id = parse_identifier (); + var attr = new Attribute (id, get_src (begin)); + if (accept (TokenType.OPEN_PARENS)) { + if (current () != TokenType.CLOSE_PARENS) { + do { + begin = get_location (); + string id = parse_identifier (); + expect (TokenType.ASSIGN); + var expr = parse_expression (); + attr.add_argument (new NamedArgument (id, expr, get_src (begin))); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + } + attrs.add (attr); + } while (accept (TokenType.COMMA)); + expect (TokenType.CLOSE_BRACKET); + } + return attrs; + } + + void set_attributes (CodeNode node, Gee.List attributes) { + if (attributes != null) { + foreach (Attribute attr in attributes) { + node.attributes.append (attr); + } + } + } + + Symbol parse_declaration () throws ParseError { + comment = scanner.pop_comment (); + var attrs = parse_attributes (); - String result = new String (comment); - comment = null; + var begin = get_location (); - weak string index; - while ((index = result.str.chr (-1, '\t')) != null) { - result.erase (result.str.pointer_to_offset (index), 1); - } + TokenType last_keyword = current (); - return result.str; - } + while (is_declaration_keyword (current ())) { + last_keyword = current (); + next (); + } - [Import ()] - public void parse_file (SourceFile! source_file); + switch (current ()) { + case TokenType.CONSTRUCT: + rollback (begin); + return parse_constructor_declaration (attrs); + case TokenType.TILDE: + rollback (begin); + return parse_destructor_declaration (attrs); + default: + skip_type (); + switch (current ()) { + case TokenType.OPEN_BRACE: + case TokenType.SEMICOLON: + case TokenType.COLON: + rollback (begin); + switch (last_keyword) { + case TokenType.CLASS: return parse_class_declaration (attrs); + case TokenType.ENUM: return parse_enum_declaration (attrs); + case TokenType.ERRORDOMAIN: return parse_errordomain_declaration (attrs); + case TokenType.INTERFACE: return parse_interface_declaration (attrs); + case TokenType.NAMESPACE: return parse_namespace_declaration (attrs); + case TokenType.STRUCT: return parse_struct_declaration (attrs); + } + break; + case TokenType.OPEN_PARENS: + rollback (begin); + return parse_creation_method_declaration (attrs); + default: + skip_type (); // might contain type parameter list + switch (current ()) { + case TokenType.OPEN_PARENS: + rollback (begin); + switch (last_keyword) { + case TokenType.DELEGATE: return parse_delegate_declaration (attrs); + case TokenType.SIGNAL: return parse_signal_declaration (attrs); + default: return parse_method_declaration (attrs); + } + case TokenType.ASSIGN: + case TokenType.SEMICOLON: + rollback (begin); + switch (last_keyword) { + case TokenType.CONST: return parse_constant_declaration (attrs); + default: return parse_field_declaration (attrs); + } + case TokenType.OPEN_BRACE: + rollback (begin); + return parse_property_declaration (attrs); + } + break; + } + break; + } + + throw new ParseError.SYNTAX (get_error ("expected declaration")); + } + + void parse_declarations (Symbol parent, bool root = false) throws ParseError { + if (!root) { + expect (TokenType.OPEN_BRACE); + } + while (current () != TokenType.CLOSE_BRACE && current () != TokenType.EOF) { + try { + if (parent is Namespace) { + parse_namespace_member ((Namespace) parent); + } else if (parent is Class) { + parse_class_member ((Class) parent); + } else if (parent is Struct) { + parse_struct_member ((Struct) parent); + } else if (parent is Interface) { + parse_interface_member ((Interface) parent); + } + } catch (ParseError e) { + int r; + do { + r = recover (); + } while (r == RecoveryState.STATEMENT_BEGIN); + if (r == RecoveryState.EOF) { + return; + } + } + } + if (!root) { + if (!accept (TokenType.CLOSE_BRACE)) { + Report.error (new SourceReference (scanner.source_file, tokens[index].begin.line, tokens[index].begin.column, tokens[index].end.line, tokens[index].end.column), "expected `}'"); + } + } + } + + enum RecoveryState { + EOF, + DECLARATION_BEGIN, + STATEMENT_BEGIN + } + + RecoveryState recover () { + while (current () != TokenType.EOF) { + switch (current ()) { + case TokenType.ABSTRACT: + case TokenType.CLASS: + case TokenType.CONST: + case TokenType.CONSTRUCT: + case TokenType.DELEGATE: + case TokenType.ENUM: + case TokenType.ERRORDOMAIN: + case TokenType.INLINE: + case TokenType.INTERFACE: + case TokenType.NAMESPACE: + case TokenType.OVERRIDE: + case TokenType.PRIVATE: + case TokenType.PROTECTED: + case TokenType.PUBLIC: + case TokenType.SIGNAL: + case TokenType.STATIC: + case TokenType.STRUCT: + case TokenType.VIRTUAL: + case TokenType.VOLATILE: + return RecoveryState.DECLARATION_BEGIN; + case TokenType.BREAK: + case TokenType.CONTINUE: + case TokenType.DELETE: + case TokenType.DO: + case TokenType.FOR: + case TokenType.FOREACH: + case TokenType.IF: + case TokenType.LOCK: + case TokenType.RETURN: + case TokenType.SWITCH: + case TokenType.THROW: + case TokenType.TRY: + case TokenType.VAR: + case TokenType.WHILE: + return RecoveryState.STATEMENT_BEGIN; + default: + next (); + break; + } + } + return RecoveryState.EOF; + } + + Namespace parse_namespace_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + expect (TokenType.NAMESPACE); + var sym = parse_symbol_name (); + var ns = context.create_namespace (sym.name, get_src_com (begin)); + ns.pkg = scanner.source_file.pkg; + set_attributes (ns, attrs); + parse_declarations (ns); + return ns; + } + + void parse_namespace_member (Namespace ns) throws ParseError { + var sym = parse_declaration (); + if (sym is Namespace) { + if (ns.scope.lookup (sym.name) is Namespace) { + // merge if namespace already exists + var old_ns = (Namespace) ns.scope.lookup (sym.name); + var new_ns = (Namespace) sym; + if (!new_ns.pkg) { + old_ns.pkg = false; + } + foreach (Class cl in new_ns.get_classes ()) { + if (old_ns.scope.lookup (cl.name) is Class) { + // merge + var old_class = (Class) old_ns.scope.lookup (cl.name); + foreach (DataType base_type in cl.get_base_types ()) { + old_class.add_base_type (base_type); + } + foreach (Field f in cl.get_fields ()) { + old_class.add_field (f); + } + foreach (Method m in cl.get_methods ()) { + if (m == cl.default_construction_method && old_class.default_construction_method != null) { + // ignore secondary default creation method + continue; + } + old_class.add_method (m); + } + if (cl.constructor != null) { + old_class.constructor = cl.constructor; + } + scanner.source_file.remove_node (cl); + } else { + old_ns.add_class (cl); + } + } + foreach (Struct st in new_ns.get_structs ()) { + old_ns.add_struct (st); + } + foreach (Interface iface in new_ns.get_interfaces ()) { + old_ns.add_interface (iface); + } + foreach (Delegate d in new_ns.get_delegates ()) { + old_ns.add_delegate (d); + } + foreach (Enum en in new_ns.get_enums ()) { + old_ns.add_enum (en); + } + foreach (ErrorDomain ed in new_ns.get_error_domains ()) { + old_ns.add_error_domain (ed); + } + foreach (Constant c in new_ns.get_constants ()) { + old_ns.add_constant (c); + } + foreach (Field f in new_ns.get_fields ()) { + old_ns.add_field (f); + } + foreach (Method m in new_ns.get_methods ()) { + old_ns.add_method (m); + } + } else { + context.root.add_namespace ((Namespace) sym); + } + } else if (sym is Class) { + ns.add_class ((Class) sym); + } else if (sym is Interface) { + ns.add_interface ((Interface) sym); + } else if (sym is Struct) { + ns.add_struct ((Struct) sym); + } else if (sym is Enum) { + ns.add_enum ((Enum) sym); + } else if (sym is ErrorDomain) { + ns.add_error_domain ((ErrorDomain) sym); + } else if (sym is Delegate) { + ns.add_delegate ((Delegate) sym); + } else if (sym is Method) { + var method = (Method) sym; + method.instance = false; + ns.add_method (method); + } else if (sym is Field) { + var field = (Field) sym; + field.instance = false; + ns.add_field (field); + } else if (sym is Constant) { + ns.add_constant ((Constant) sym); + } else if (sym == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in declaration"); + } else { + Report.error (sym.source_reference, "unexpected declaration in namespace"); + } + scanner.source_file.add_node (sym); + } + + void parse_using_directives () throws ParseError { + while (accept (TokenType.USING)) { + var begin = get_location (); + + do { + var begin = get_location (); + var sym = parse_symbol_name (); + var ns_ref = new NamespaceReference (sym.name, get_src (begin)); + scanner.source_file.add_using_directive (ns_ref); + } while (accept (TokenType.COMMA)); + expect (TokenType.SEMICOLON); + } + } + + Symbol parse_class_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + var flags = parse_type_declaration_modifiers (); + expect (TokenType.CLASS); + var sym = parse_symbol_name (); + var type_param_list = parse_type_parameter_list (); + var base_types = new ArrayList (); + if (accept (TokenType.COLON)) { + do { + base_types.add (parse_type ()); + } while (accept (TokenType.COMMA)); + } + + var cl = context.create_class (sym.name, get_src_com (begin)); + cl.access = access; + if (ModifierFlags.ABSTRACT in flags) { + cl.is_abstract = true; + } + if (ModifierFlags.STATIC in flags) { + cl.is_static = true; + } + set_attributes (cl, attrs); + foreach (TypeParameter type_param in type_param_list) { + cl.add_type_parameter (type_param); + } + foreach (DataType base_type in base_types) { + cl.add_base_type (base_type); + } + + parse_declarations (cl); + + // ensure there is always a default construction method + if (!scanner.source_file.pkg + && !cl.is_abstract + && !cl.is_static + && cl.default_construction_method == null) { + var m = context.create_creation_method (cl.name, null, cl.source_reference); + m.instance = false; + m.access = SymbolAccessibility.PUBLIC; + m.body = context.create_block (cl.source_reference); + cl.add_method (m); + } + + Symbol result = cl; + while (sym.inner != null) { + sym = sym.inner; + var ns = context.create_namespace (sym.name, cl.source_reference); + ns.pkg = scanner.source_file.pkg; + if (result is Namespace) { + ns.add_namespace ((Namespace) result); + } else { + ns.add_class ((Class) result); + scanner.source_file.add_node (result); + } + result = ns; + } + return result; + } + + void parse_class_member (Class cl) throws ParseError { + var sym = parse_declaration (); + if (sym is Class) { + cl.add_class ((Class) sym); + } else if (sym is Struct) { + cl.add_struct ((Struct) sym); + } else if (sym is Enum) { + cl.add_enum ((Enum) sym); + } else if (sym is Delegate) { + cl.add_delegate ((Delegate) sym); + } else if (sym is Method) { + cl.add_method ((Method) sym); + } else if (sym is Signal) { + cl.add_signal ((Signal) sym); + } else if (sym is Field) { + cl.add_field ((Field) sym); + } else if (sym is Constant) { + cl.add_constant ((Constant) sym); + } else if (sym is Property) { + cl.add_property ((Property) sym); + } else if (sym is Constructor) { + var c = (Constructor) sym; + if (c.instance) { + cl.constructor = c; + } else { + cl.static_constructor = c; + } + } else if (sym is Destructor) { + cl.destructor = (Destructor) sym; + } else if (sym == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in declaration"); + } else { + Report.error (sym.source_reference, "unexpected declaration in class"); + } + } + + Constant parse_constant_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + parse_member_declaration_modifiers (); + expect (TokenType.CONST); + var type = parse_type (); + string id = parse_identifier (); + Expression initializer = null; + if (accept (TokenType.ASSIGN)) { + initializer = parse_variable_initializer (); + } + expect (TokenType.SEMICOLON); + var c = context.create_constant (id, type, initializer, get_src_com (begin)); + c.access = access; + set_attributes (c, attrs); + return c; + } + + Field parse_field_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + var flags = parse_member_declaration_modifiers (); + var type = parse_type (); + var unresolved_type = type as UnresolvedType; + if (unresolved_type != null && !unresolved_type.is_weak) { + unresolved_type.takes_ownership = true; + } + string id = parse_identifier (); + var f = context.create_field (id, type, null, get_src_com (begin)); + f.access = access; + set_attributes (f, attrs); + if (ModifierFlags.STATIC in flags) { + f.instance = false; + } + if (accept (TokenType.ASSIGN)) { + f.initializer = parse_expression (); + } + expect (TokenType.SEMICOLON); + return f; + } + + Gee.List parse_variable_declarators () throws ParseError { + var list = new ArrayList (); + do { + var var_decl = parse_variable_declarator (); + list.add (var_decl); + } while (accept (TokenType.COMMA)); + return list; + } + + VariableDeclarator parse_variable_declarator () throws ParseError { + var begin = get_location (); + string id = parse_identifier (); + Expression initializer = null; + if (accept (TokenType.ASSIGN)) { + initializer = parse_variable_initializer (); + } + return context.create_variable_declarator (id, initializer, get_src (begin)); + } + + InitializerList parse_initializer () throws ParseError { + var begin = get_location (); + expect (TokenType.OPEN_BRACE); + var initializer = context.create_initializer_list (get_src (begin)); + if (current () != TokenType.CLOSE_BRACE) { + do { + initializer.append (parse_variable_initializer ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_BRACE); + return initializer; + } + + Expression parse_variable_initializer () throws ParseError { + if (current () == TokenType.OPEN_BRACE) { + return parse_initializer (); + } else { + return parse_expression (); + } + } + + Method parse_method_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + var flags = parse_member_declaration_modifiers (); + var type = parse_type (); + var unresolved_type = type as UnresolvedType; + if (unresolved_type != null && !unresolved_type.is_weak) { + unresolved_type.transfers_ownership = true; + } + string id = parse_identifier (); + parse_type_parameter_list (); + var method = context.create_method (id, type, get_src_com (begin)); + method.access = access; + set_attributes (method, attrs); + if (ModifierFlags.STATIC in flags) { + method.instance = false; + } + if (ModifierFlags.ABSTRACT in flags) { + method.is_abstract = true; + } + if (ModifierFlags.VIRTUAL in flags) { + method.is_virtual = true; + } + if (ModifierFlags.OVERRIDE in flags) { + method.overrides = true; + } + if (ModifierFlags.INLINE in flags) { + method.is_inline = true; + } + expect (TokenType.OPEN_PARENS); + if (current () != TokenType.CLOSE_PARENS) { + do { + method.add_parameter (parse_parameter ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + if (accept (TokenType.THROWS)) { + do { + method.add_error_domain (parse_type ()); + } while (accept (TokenType.COMMA)); + } + if (!accept (TokenType.SEMICOLON)) { + method.body = parse_block (); + } + return method; + } + + Property parse_property_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + var flags = parse_member_declaration_modifiers (); + var type = parse_type (); + if (!((UnresolvedType) type).is_weak) { + type.takes_ownership = true; + } + string id = parse_identifier (); + var prop = context.create_property (id, type, null, null, get_src_com (begin)); + prop.access = access; + set_attributes (prop, attrs); + if (ModifierFlags.ABSTRACT in flags) { + prop.is_abstract = true; + } + if (ModifierFlags.VIRTUAL in flags) { + prop.is_virtual = true; + } + if (ModifierFlags.OVERRIDE in flags) { + prop.overrides = true; + } + expect (TokenType.OPEN_BRACE); + while (current () != TokenType.CLOSE_BRACE) { + if (accept (TokenType.DEFAULT)) { + if (prop.default_expression != null) { + throw new ParseError.SYNTAX (get_error ("property default value already defined")); + } + if (accept (TokenType.OPEN_PARENS)) { + // deprecated + prop.default_expression = parse_expression (); + expect (TokenType.CLOSE_PARENS); + } else { + expect (TokenType.ASSIGN); + prop.default_expression = parse_expression (); + } + expect (TokenType.SEMICOLON); + } else { + parse_attributes (); + var accessor_access = parse_access_modifier (SymbolAccessibility.PUBLIC); + if (accept (TokenType.GET)) { + if (prop.get_accessor != null) { + throw new ParseError.SYNTAX (get_error ("property get accessor already defined")); + } + Block block = null; + if (!accept (TokenType.SEMICOLON)) { + block = parse_block (); + } + prop.get_accessor = context.create_property_accessor (true, false, false, block, get_src (begin)); + prop.get_accessor.access = accessor_access; + } else { + bool writable, _construct; + if (accept (TokenType.SET)) { + writable = true; + _construct = accept (TokenType.CONSTRUCT); + } else if (accept (TokenType.CONSTRUCT)) { + _construct = true; + writable = accept (TokenType.SET); + } else { + throw new ParseError.SYNTAX (get_error ("expected get, set, or construct")); + } + if (prop.set_accessor != null) { + throw new ParseError.SYNTAX (get_error ("property set accessor already defined")); + } + Block block = null; + if (!accept (TokenType.SEMICOLON)) { + block = parse_block (); + } + prop.set_accessor = context.create_property_accessor (false, writable, _construct, block, get_src (begin)); + prop.set_accessor.access = accessor_access; + } + } + } + expect (TokenType.CLOSE_BRACE); + return prop; + } + + Signal parse_signal_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + parse_access_modifier (); + parse_member_declaration_modifiers (); + expect (TokenType.SIGNAL); + var type = parse_type (); + string id = parse_identifier (); + var sig = context.create_signal (id, type, get_src_com (begin)); + set_attributes (sig, attrs); + expect (TokenType.OPEN_PARENS); + if (current () != TokenType.CLOSE_PARENS) { + do { + var param = parse_parameter (); + sig.add_parameter (param); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + expect (TokenType.SEMICOLON); + return sig; + } + + Constructor parse_constructor_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var flags = parse_member_declaration_modifiers (); + expect (TokenType.CONSTRUCT); + var c = context.create_constructor (get_src_com (begin)); + if (ModifierFlags.STATIC in flags) { + c.instance = false; + } + c.body = parse_block (); + return c; + } + + Destructor parse_destructor_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + expect (TokenType.TILDE); + parse_identifier (); + expect (TokenType.OPEN_PARENS); + expect (TokenType.CLOSE_PARENS); + var d = context.create_destructor (get_src_com (begin)); + d.body = parse_block (); + return d; + } + + Symbol parse_struct_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + parse_type_declaration_modifiers (); + expect (TokenType.STRUCT); + var sym = parse_symbol_name (); + var base_types = new ArrayList (); + if (accept (TokenType.COLON)) { + do { + base_types.add (parse_type ()); + } while (accept (TokenType.COMMA)); + } + var st = context.create_struct (sym.name, get_src_com (begin)); + st.access = access; + set_attributes (st, attrs); + foreach (DataType base_type in base_types) { + st.add_base_type (base_type); + } + + parse_declarations (st); + + Symbol result = st; + while (sym.inner != null) { + sym = sym.inner; + var ns = context.create_namespace (sym.name, st.source_reference); + ns.pkg = scanner.source_file.pkg; + if (result is Namespace) { + ns.add_namespace ((Namespace) result); + } else { + ns.add_struct ((Struct) result); + scanner.source_file.add_node (result); + } + result = ns; + } + return result; + } + + void parse_struct_member (Struct st) throws ParseError { + var sym = parse_declaration (); + if (sym is Method) { + st.add_method ((Method) sym); + } else if (sym is Field) { + st.add_field ((Field) sym); + } else if (sym is Constant) { + st.add_constant ((Constant) sym); + } else if (sym == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in declaration"); + } else { + Report.error (sym.source_reference, "unexpected declaration in struct"); + } + } + + Symbol parse_interface_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + parse_type_declaration_modifiers (); + expect (TokenType.INTERFACE); + var sym = parse_symbol_name (); + var type_param_list = parse_type_parameter_list (); + var base_types = new ArrayList (); + if (accept (TokenType.COLON)) { + do { + base_types.add (parse_type ()); + } while (accept (TokenType.COMMA)); + } + var iface = context.create_interface (sym.name, get_src_com (begin)); + iface.access = access; + set_attributes (iface, attrs); + foreach (TypeParameter type_param in type_param_list) { + iface.add_type_parameter (type_param); + } + foreach (DataType base_type in base_types) { + iface.add_prerequisite (base_type); + } + + parse_declarations (iface); + + Symbol result = iface; + while (sym.inner != null) { + sym = sym.inner; + var ns = context.create_namespace (sym.name, iface.source_reference); + ns.pkg = scanner.source_file.pkg; + if (result is Namespace) { + ns.add_namespace ((Namespace) result); + } else { + ns.add_interface ((Interface) result); + scanner.source_file.add_node (result); + } + result = ns; + } + return result; + } + + void parse_interface_member (Interface iface) throws ParseError { + var sym = parse_declaration (); + if (sym is Class) { + iface.add_class ((Class) sym); + } else if (sym is Struct) { + iface.add_struct ((Struct) sym); + } else if (sym is Enum) { + iface.add_enum ((Enum) sym); + } else if (sym is Delegate) { + iface.add_delegate ((Delegate) sym); + } else if (sym is Method) { + iface.add_method ((Method) sym); + } else if (sym is Signal) { + iface.add_signal ((Signal) sym); + } else if (sym is Field) { + iface.add_field ((Field) sym); + } else if (sym is Property) { + iface.add_property ((Property) sym); + } else if (sym == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in declaration"); + } else { + Report.error (sym.source_reference, "unexpected declaration in interface"); + } + } + + Symbol parse_enum_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + parse_type_declaration_modifiers (); + expect (TokenType.ENUM); + var sym = parse_symbol_name (); + var en = context.create_enum (sym.name, get_src_com (begin)); + en.access = access; + set_attributes (en, attrs); + + expect (TokenType.OPEN_BRACE); + do { + if (current () == TokenType.CLOSE_BRACE) { + // allow trailing comma + break; + } + string id = parse_identifier (); + var ev = context.create_enum_value (id, get_src (begin)); + if (accept (TokenType.ASSIGN)) { + ev.value = parse_expression (); + } + en.add_value (ev); + } while (accept (TokenType.COMMA)); + if (accept (TokenType.SEMICOLON)) { + // enum methods + while (current () != TokenType.CLOSE_BRACE) { + var sym = parse_declaration (); + if (sym is Method) { + en.add_method ((Method) sym); + } else if (sym == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in declaration"); + } else { + Report.error (sym.source_reference, "unexpected declaration in enum"); + } + } + } + expect (TokenType.CLOSE_BRACE); + + Symbol result = en; + while (sym.inner != null) { + sym = sym.inner; + var ns = context.create_namespace (sym.name, en.source_reference); + ns.pkg = scanner.source_file.pkg; + if (result is Namespace) { + ns.add_namespace ((Namespace) result); + } else { + ns.add_enum ((Enum) result); + scanner.source_file.add_node (result); + } + result = ns; + } + return result; + } + + Symbol parse_errordomain_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + parse_type_declaration_modifiers (); + expect (TokenType.ERRORDOMAIN); + var sym = parse_symbol_name (); + var ed = context.create_error_domain (sym.name, get_src_com (begin)); + ed.access = access; + set_attributes (ed, attrs); + + expect (TokenType.OPEN_BRACE); + do { + if (current () == TokenType.CLOSE_BRACE) { + // allow trailing comma + break; + } + string id = parse_identifier (); + var ec = context.create_error_code (id); + if (accept (TokenType.ASSIGN)) { + ec.value = parse_expression (); + } + ed.add_code (ec); + } while (accept (TokenType.COMMA)); + if (accept (TokenType.SEMICOLON)) { + // errordomain methods + while (current () != TokenType.CLOSE_BRACE) { + var sym = parse_declaration (); + if (sym is Method) { + ed.add_method ((Method) sym); + } else if (sym == null) { + // workaround for current limitation of exception handling + throw new ParseError.SYNTAX ("syntax error in declaration"); + } else { + Report.error (sym.source_reference, "unexpected declaration in errordomain"); + } + } + } + expect (TokenType.CLOSE_BRACE); + + Symbol result = ed; + while (sym.inner != null) { + sym = sym.inner; + var ns = context.create_namespace (sym.name, ed.source_reference); + ns.pkg = scanner.source_file.pkg; + if (result is Namespace) { + ns.add_namespace ((Namespace) result); + } else { + ns.add_error_domain ((ErrorDomain) result); + scanner.source_file.add_node (result); + } + result = ns; + } + return result; + } + + SymbolAccessibility parse_access_modifier (SymbolAccessibility default_access = SymbolAccessibility.PRIVATE) { + switch (current ()) { + case TokenType.PRIVATE: + next (); + return SymbolAccessibility.PRIVATE; + case TokenType.PROTECTED: + next (); + return SymbolAccessibility.PROTECTED; + case TokenType.PUBLIC: + next (); + return SymbolAccessibility.PUBLIC; + default: + return default_access; + } + } + + ModifierFlags parse_type_declaration_modifiers () { + ModifierFlags flags = 0; + while (true) { + switch (current ()) { + case TokenType.ABSTRACT: + next (); + flags |= ModifierFlags.ABSTRACT; + break; + case TokenType.STATIC: + next (); + flags |= ModifierFlags.STATIC; + break; + default: + return flags; + } + } + return flags; + } + + ModifierFlags parse_member_declaration_modifiers () { + ModifierFlags flags = 0; + while (true) { + switch (current ()) { + case TokenType.ABSTRACT: + next (); + flags |= ModifierFlags.ABSTRACT; + break; + case TokenType.CLASS: + next (); + flags |= ModifierFlags.CLASS; + break; + case TokenType.INLINE: + next (); + flags |= ModifierFlags.INLINE; + break; + case TokenType.OVERRIDE: + next (); + flags |= ModifierFlags.OVERRIDE; + break; + case TokenType.STATIC: + next (); + flags |= ModifierFlags.STATIC; + break; + case TokenType.VIRTUAL: + next (); + flags |= ModifierFlags.VIRTUAL; + break; + default: + return flags; + } + } + return flags; + } + + FormalParameter parse_parameter () throws ParseError { + var attrs = parse_attributes (); + var begin = get_location (); + if (accept (TokenType.ELLIPSIS)) { + // varargs + return context.create_formal_parameter_with_ellipsis (get_src (begin)); + } + bool construct_param = accept (TokenType.CONSTRUCT); + var type = parse_type (); + var ut = type as UnresolvedType; + if (ut != null) { + if (!ut.is_weak) { + ut.takes_ownership = true; + } + if (!ut.is_ref && !ut.is_out && !ut.transfers_ownership) { + // take_ownership for in parameters that don't transfer ownership is not supported + ut.takes_ownership = false; + } + } + string id = parse_identifier (); + var param = context.create_formal_parameter (id, type, get_src (begin)); + set_attributes (param, attrs); + param.construct_parameter = construct_param; + if (accept (TokenType.ASSIGN)) { + param.default_expression = parse_expression (); + } + return param; + } + + CreationMethod parse_creation_method_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + parse_member_declaration_modifiers (); + var sym = parse_symbol_name (); + CreationMethod method; + if (sym.inner == null) { + method = context.create_creation_method (sym.name, null, get_src_com (begin)); + } else { + method = context.create_creation_method (sym.inner.name, sym.name, get_src_com (begin)); + } + expect (TokenType.OPEN_PARENS); + if (current () != TokenType.CLOSE_PARENS) { + do { + method.add_parameter (parse_parameter ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + if (accept (TokenType.THROWS)) { + do { + method.add_error_domain (parse_type ()); + } while (accept (TokenType.COMMA)); + } + method.access = access; + set_attributes (method, attrs); + method.instance = false; + if (!accept (TokenType.SEMICOLON)) { + method.body = parse_block (); + } + return method; + } + + Symbol parse_delegate_declaration (Gee.List attrs) throws ParseError { + var begin = get_location (); + var access = parse_access_modifier (); + var flags = parse_member_declaration_modifiers (); + expect (TokenType.DELEGATE); + var type = parse_type (); + var sym = parse_symbol_name (); + var type_param_list = parse_type_parameter_list (); + var d = context.create_delegate (sym.name, type, get_src_com (begin)); + d.access = access; + set_attributes (d, attrs); + if (!(ModifierFlags.STATIC in flags)) { + d.instance = true; + } + foreach (TypeParameter type_param in type_param_list) { + d.add_type_parameter (type_param); + } + expect (TokenType.OPEN_PARENS); + if (current () != TokenType.CLOSE_PARENS) { + do { + d.add_parameter (parse_parameter ()); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.CLOSE_PARENS); + if (accept (TokenType.THROWS)) { + do { + parse_type (); + } while (accept (TokenType.COMMA)); + } + expect (TokenType.SEMICOLON); + + Symbol result = d; + while (sym.inner != null) { + sym = sym.inner; + var ns = context.create_namespace (sym.name, d.source_reference); + ns.pkg = scanner.source_file.pkg; + if (result is Namespace) { + ns.add_namespace ((Namespace) result); + } else { + ns.add_delegate ((Delegate) result); + scanner.source_file.add_node (result); + } + result = ns; + } + return result; + } + + Gee.List parse_type_parameter_list () throws ParseError { + var list = new ArrayList (); + if (accept (TokenType.OP_LT)) { + do { + var begin = get_location (); + string id = parse_identifier (); + list.add (context.create_type_parameter (id, get_src (begin))); + } while (accept (TokenType.COMMA)); + expect (TokenType.OP_GT); + } + return list; + } + + void skip_type_argument_list () throws ParseError { + if (accept (TokenType.OP_LT)) { + do { + skip_type (); + } while (accept (TokenType.COMMA)); + expect (TokenType.OP_GT); + } + } + + // try to parse type argument list + Gee.List parse_type_argument_list (bool maybe_expression) throws ParseError { + var begin = get_location (); + if (accept (TokenType.OP_LT)) { + var list = new ArrayList (); + do { + switch (current ()) { + case TokenType.VOID: + case TokenType.WEAK: + case TokenType.IDENTIFIER: + var type = parse_type (); + if (!((UnresolvedType) type).is_weak) { + type.takes_ownership = true; + } + list.add (type); + break; + default: + rollback (begin); + return null; + } + } while (accept (TokenType.COMMA)); + if (!accept (TokenType.OP_GT)) { + rollback (begin); + return null; + } + if (maybe_expression) { + // check follower to decide whether to keep type argument list + switch (current ()) { + case TokenType.OPEN_PARENS: + case TokenType.CLOSE_PARENS: + case TokenType.CLOSE_BRACKET: + case TokenType.COLON: + case TokenType.SEMICOLON: + case TokenType.COMMA: + case TokenType.DOT: + case TokenType.INTERR: + case TokenType.OP_EQ: + case TokenType.OP_NE: + // keep type argument list + break; + default: + // interpret tokens as expression + rollback (begin); + return null; + } + } + return list; + } + return null; + } + + MemberAccess parse_member_name () throws ParseError { + var begin = get_location (); + MemberAccess expr = null; + do { + string id = parse_identifier (); + var type_arg_list = parse_type_argument_list (false); + expr = context.create_member_access (expr, id, get_src (begin)); + if (type_arg_list != null) { + foreach (DataType type_arg in type_arg_list) { + expr.add_type_argument (type_arg); + } + } + } while (accept (TokenType.DOT)); + return expr; + } + + bool is_declaration_keyword (TokenType type) { + switch (type) { + case TokenType.ABSTRACT: + case TokenType.CLASS: + case TokenType.CONST: + case TokenType.DELEGATE: + case TokenType.ENUM: + case TokenType.ERRORDOMAIN: + case TokenType.INLINE: + case TokenType.INTERFACE: + case TokenType.NAMESPACE: + case TokenType.OVERRIDE: + case TokenType.PRIVATE: + case TokenType.PROTECTED: + case TokenType.PUBLIC: + case TokenType.SIGNAL: + case TokenType.STATIC: + case TokenType.STRUCT: + case TokenType.VIRTUAL: + case TokenType.VOLATILE: + return true; + default: + return false; + } + } } + +public errordomain Vala.ParseError { + FAILED, + SYNTAX +} + diff --git a/vala/valascanner.vala b/vala/valascanner.vala new file mode 100644 index 0000000..761a89f --- /dev/null +++ b/vala/valascanner.vala @@ -0,0 +1,774 @@ +/* valascanner.vala + * + * Copyright (C) 2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; +using Gee; + +/** + * Lexical scanner for Vala source files. + */ +public class Vala.Scanner : Object { + public SourceFile source_file { get; construct; } + + char* begin; + char* current; + char* end; + + int line; + int column; + + string _comment; + + public Scanner (SourceFile source_file) { + this.source_file = source_file; + } + + construct { + begin = source_file.get_mapped_contents (); + end = begin + source_file.get_mapped_length (); + + current = begin; + + line = 1; + column = 1; + } + + bool is_ident_char (char c) { + return (c.isalnum () || c == '_'); + } + + TokenType get_identifier_or_keyword (char* begin, int len) { + switch (len) { + case 2: + switch (begin[0]) { + case 'a': + if (matches (begin, "as")) return TokenType.AS; + break; + case 'd': + if (matches (begin, "do")) return TokenType.DO; + break; + case 'i': + switch (begin[1]) { + case 'f': + return TokenType.IF; + case 'n': + return TokenType.IN; + case 's': + return TokenType.IS; + } + break; + } + break; + case 3: + switch (begin[0]) { + case 'f': + if (matches (begin, "for")) return TokenType.FOR; + break; + case 'g': + if (matches (begin, "get")) return TokenType.GET; + break; + case 'n': + if (matches (begin, "new")) return TokenType.NEW; + break; + case 'o': + if (matches (begin, "out")) return TokenType.OUT; + break; + case 'r': + if (matches (begin, "ref")) return TokenType.REF; + break; + case 's': + if (matches (begin, "set")) return TokenType.SET; + break; + case 't': + if (matches (begin, "try")) return TokenType.TRY; + break; + case 'v': + if (matches (begin, "var")) return TokenType.VAR; + break; + } + break; + case 4: + switch (begin[0]) { + case 'b': + if (matches (begin, "base")) return TokenType.BASE; + break; + case 'c': + if (matches (begin, "case")) return TokenType.CASE; + break; + case 'e': + switch (begin[1]) { + case 'l': + if (matches (begin, "else")) return TokenType.ELSE; + break; + case 'n': + if (matches (begin, "enum")) return TokenType.ENUM; + break; + } + break; + case 'l': + if (matches (begin, "lock")) return TokenType.LOCK; + break; + case 'n': + if (matches (begin, "null")) return TokenType.NULL; + break; + case 't': + switch (begin[1]) { + case 'h': + if (matches (begin, "this")) return TokenType.THIS; + break; + case 'r': + if (matches (begin, "true")) return TokenType.TRUE; + break; + } + break; + case 'v': + if (matches (begin, "void")) return TokenType.VOID; + break; + case 'w': + if (matches (begin, "weak")) return TokenType.WEAK; + break; + } + break; + case 5: + switch (begin[0]) { + case 'b': + if (matches (begin, "break")) return TokenType.BREAK; + break; + case 'c': + switch (begin[1]) { + case 'a': + if (matches (begin, "catch")) return TokenType.CATCH; + break; + case 'l': + if (matches (begin, "class")) return TokenType.CLASS; + break; + case 'o': + if (matches (begin, "const")) return TokenType.CONST; + break; + } + break; + case 'f': + if (matches (begin, "false")) return TokenType.FALSE; + break; + case 't': + if (matches (begin, "throw")) return TokenType.THROW; + break; + case 'u': + if (matches (begin, "using")) return TokenType.USING; + break; + case 'w': + if (matches (begin, "while")) return TokenType.WHILE; + break; + } + break; + case 6: + switch (begin[0]) { + case 'd': + if (matches (begin, "delete")) return TokenType.DELETE; + break; + case 'i': + if (matches (begin, "inline")) return TokenType.INLINE; + break; + case 'p': + if (matches (begin, "public")) return TokenType.PUBLIC; + break; + case 'r': + if (matches (begin, "return")) return TokenType.RETURN; + break; + case 's': + switch (begin[1]) { + case 'i': + switch (begin[2]) { + case 'g': + if (matches (begin, "signal")) return TokenType.SIGNAL; + break; + case 'z': + if (matches (begin, "sizeof")) return TokenType.SIZEOF; + break; + } + break; + case 't': + switch (begin[2]) { + case 'a': + if (matches (begin, "static")) return TokenType.STATIC; + break; + case 'r': + if (matches (begin, "struct")) return TokenType.STRUCT; + break; + } + break; + case 'w': + if (matches (begin, "switch")) return TokenType.SWITCH; + break; + } + break; + case 't': + switch (begin[1]) { + case 'h': + if (matches (begin, "throws")) return TokenType.THROWS; + break; + case 'y': + if (matches (begin, "typeof")) return TokenType.TYPEOF; + break; + } + break; + } + break; + case 7: + switch (begin[0]) { + case 'd': + if (matches (begin, "default")) return TokenType.DEFAULT; + break; + case 'e': + if (matches (begin, "ensures")) return TokenType.ENSURES; + break; + case 'f': + switch (begin[1]) { + case 'i': + if (matches (begin, "finally")) return TokenType.FINALLY; + break; + case 'o': + if (matches (begin, "foreach")) return TokenType.FOREACH; + break; + } + break; + case 'p': + if (matches (begin, "private")) return TokenType.PRIVATE; + break; + case 'v': + if (matches (begin, "virtual")) return TokenType.VIRTUAL; + break; + } + break; + case 8: + switch (begin[0]) { + case 'a': + if (matches (begin, "abstract")) return TokenType.ABSTRACT; + break; + case 'c': + if (matches (begin, "continue")) return TokenType.CONTINUE; + break; + case 'd': + if (matches (begin, "delegate")) return TokenType.DELEGATE; + break; + case 'o': + if (matches (begin, "override")) return TokenType.OVERRIDE; + break; + case 'r': + if (matches (begin, "requires")) return TokenType.REQUIRES; + break; + case 'v': + if (matches (begin, "volatile")) return TokenType.VOLATILE; + break; + } + break; + case 9: + switch (begin[0]) { + case 'c': + if (matches (begin, "construct")) return TokenType.CONSTRUCT; + break; + case 'i': + if (matches (begin, "interface")) return TokenType.INTERFACE; + break; + case 'n': + if (matches (begin, "namespace")) return TokenType.NAMESPACE; + break; + case 'p': + if (matches (begin, "protected")) return TokenType.PROTECTED; + break; + } + break; + case 11: + if (matches (begin, "errordomain")) return TokenType.ERRORDOMAIN; + break; + } + return TokenType.IDENTIFIER; + } + + public TokenType read_token (out SourceLocation token_begin, out SourceLocation token_end) { + space (); + + TokenType type; + char* begin = current; + token_begin.pos = begin; + token_begin.line = line; + token_begin.column = column; + + int token_length_in_chars = -1; + + if (current >= end) { + type = TokenType.EOF; + } else if (current[0].isalpha () || current[0] == '_') { + int len = 0; + while (current < end && is_ident_char (current[0])) { + current++; + len++; + } + type = get_identifier_or_keyword (begin, len); + } else if (current[0] == '@') { + token_begin.pos++; // @ is not part of the identifier + current++; + int len = 0; + while (current < end && is_ident_char (current[0])) { + current++; + len++; + } + type = TokenType.IDENTIFIER; + } else if (current[0].isdigit ()) { + while (current < end && current[0].isdigit ()) { + current++; + } + type = TokenType.INTEGER_LITERAL; + if (current < end && current[0].tolower () == 'l') { + current++; + if (current < end && current[0].tolower () == 'l') { + current++; + } + } else if (current < end && current[0].tolower () == 'u') { + current++; + if (current < end && current[0].tolower () == 'l') { + current++; + if (current < end && current[0].tolower () == 'l') { + current++; + } + } + } else if (current < end && current[0] == '.') { + current++; + while (current < end && current[0].isdigit ()) { + current++; + } + if (current < end && current[0].tolower () == 'e') { + current++; + if (current < end && (current[0] == '+' || current[0] == '-')) { + current++; + } + while (current < end && current[0].isdigit ()) { + current++; + } + } + if (current < end && current[0].tolower () == 'f') { + current++; + } + type = TokenType.REAL_LITERAL; + } else if (current < end && current == begin + 1 + && begin[0] == '0' && begin[1] == 'x' && begin[2].isxdigit ()) { + // hexadecimal integer literal + current++; + while (current < end && current[0].isxdigit ()) { + current++; + } + } else if (current < end && is_ident_char (current[0])) { + // allow identifiers to start with a digit + // as long as they contain at least one char + while (current < end && is_ident_char (current[0])) { + current++; + } + type = TokenType.IDENTIFIER; + } + } else { + switch (current[0]) { + case '{': + type = TokenType.OPEN_BRACE; + current++; + break; + case '}': + type = TokenType.CLOSE_BRACE; + current++; + break; + case '(': + type = TokenType.OPEN_PARENS; + current++; + break; + case ')': + type = TokenType.CLOSE_PARENS; + current++; + break; + case '[': + type = TokenType.OPEN_BRACKET; + current++; + break; + case ']': + type = TokenType.CLOSE_BRACKET; + current++; + break; + case '.': + type = TokenType.DOT; + current++; + if (current < end - 1) { + if (current[0] == '.' && current[1] == '.') { + type = TokenType.ELLIPSIS; + current += 2; + } + } + break; + case ':': + type = TokenType.COLON; + current++; + break; + case ',': + type = TokenType.COMMA; + current++; + break; + case ';': + type = TokenType.SEMICOLON; + current++; + break; + case '#': + type = TokenType.HASH; + current++; + break; + case '?': + type = TokenType.INTERR; + current++; + break; + case '|': + type = TokenType.BITWISE_OR; + current++; + if (current < end) { + switch (current[0]) { + case '=': + type = TokenType.ASSIGN_BITWISE_OR; + current++; + break; + case '|': + type = TokenType.OP_OR; + current++; + break; + } + } + break; + case '&': + type = TokenType.BITWISE_AND; + current++; + if (current < end) { + switch (current[0]) { + case '=': + type = TokenType.ASSIGN_BITWISE_AND; + current++; + break; + case '&': + type = TokenType.OP_AND; + current++; + break; + } + } + break; + case '^': + type = TokenType.CARRET; + current++; + if (current < end && current[0] == '=') { + type = TokenType.ASSIGN_BITWISE_XOR; + current++; + } + break; + case '~': + type = TokenType.TILDE; + current++; + break; + case '=': + type = TokenType.ASSIGN; + current++; + if (current < end) { + switch (current[0]) { + case '=': + type = TokenType.OP_EQ; + current++; + break; + case '>': + type = TokenType.LAMBDA; + current++; + break; + } + } + break; + case '<': + type = TokenType.OP_LT; + current++; + if (current < end) { + switch (current[0]) { + case '=': + type = TokenType.OP_LE; + current++; + break; + case '<': + type = TokenType.OP_SHIFT_LEFT; + current++; + if (current < end && current[0] == '=') { + type = TokenType.ASSIGN_SHIFT_LEFT; + current++; + } + break; + } + } + break; + case '>': + type = TokenType.OP_GT; + current++; + if (current < end && current[0] == '=') { + type = TokenType.OP_GE; + current++; + } + break; + case '!': + type = TokenType.OP_NEG; + current++; + if (current < end && current[0] == '=') { + type = TokenType.OP_NE; + current++; + } + break; + case '+': + type = TokenType.PLUS; + current++; + if (current < end) { + switch (current[0]) { + case '=': + type = TokenType.ASSIGN_ADD; + current++; + break; + case '+': + type = TokenType.OP_INC; + current++; + break; + } + } + break; + case '-': + type = TokenType.MINUS; + current++; + if (current < end) { + switch (current[0]) { + case '=': + type = TokenType.ASSIGN_SUB; + current++; + break; + case '-': + type = TokenType.OP_DEC; + current++; + break; + case '>': + type = TokenType.OP_PTR; + current++; + break; + } + } + break; + case '*': + type = TokenType.STAR; + current++; + if (current < end && current[0] == '=') { + type = TokenType.ASSIGN_MUL; + current++; + } + break; + case '/': + type = TokenType.DIV; + current++; + if (current < end && current[0] == '=') { + type = TokenType.ASSIGN_DIV; + current++; + } + break; + case '%': + type = TokenType.PERCENT; + current++; + if (current < end && current[0] == '=') { + type = TokenType.ASSIGN_PERCENT; + current++; + } + break; + case '\'': + case '"': + if (begin[0] == '\'') { + type = TokenType.CHARACTER_LITERAL; + } else { + type = TokenType.STRING_LITERAL; + } + token_length_in_chars = 2; + current++; + while (current < end && current[0] != begin[0]) { + if (current[0] == '\\') { + current++; + token_length_in_chars++; + if (current < end && current[0] == 'x') { + // hexadecimal escape character + current++; + token_length_in_chars++; + while (current < end && current[0].isxdigit ()) { + current++; + token_length_in_chars++; + } + } else { + current++; + token_length_in_chars++; + } + } else if (current[0] == '\n') { + break; + } else { + unichar u = ((string) current).get_char_validated ((long) (end - current)); + if (u != (unichar) (-1)) { + current += u.to_utf8 (null); + token_length_in_chars++; + } else { + Report.error (new SourceReference (source_file, line, column + token_length_in_chars, line, column + token_length_in_chars), "invalid UTF-8 character"); + } + } + } + if (current < end && current[0] != '\n') { + current++; + } else { + Report.error (new SourceReference (source_file, line, column + token_length_in_chars, line, column + token_length_in_chars), "syntax error, expected %c".printf (begin[0])); + } + break; + default: + unichar u = ((string) current).get_char_validated ((long) (end - current)); + if (u != (unichar) (-1)) { + current += u.to_utf8 (null); + Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, unexpected character"); + } else { + current++; + Report.error (new SourceReference (source_file, line, column, line, column), "invalid UTF-8 character"); + } + column++; + return read_token (out token_begin, out token_end); + } + } + + if (token_length_in_chars < 0) { + column += (int) (current - begin); + } else { + column += token_length_in_chars; + } + + token_end.pos = current; + token_end.line = line; + token_end.column = column - 1; + + return type; + } + + bool matches (char* begin, string keyword) { + char* keyword_array = keyword; + long len = keyword.len (); + for (int i = 0; i < len; i++) { + if (begin[i] != keyword_array[i]) { + return false; + } + } + return true; + } + + bool whitespace () { + bool found = false; + while (current < end && current[0].isspace ()) { + if (current[0] == '\n') { + line++; + column = 0; + } + found = true; + current++; + column++; + } + return found; + } + + bool comment () { + if (current > end - 2 + || current[0] != '/' + || (current[1] != '/' && current[1] != '*')) { + return false; + } + + if (current[1] == '/') { + // single-line comment + current += 2; + char* begin = current; + // skip until end of line or end of file + while (current < end && current[0] != '\n') { + current++; + } + push_comment (((string) begin).ndup ((long) (current - begin)), line == 1); + } else { + // delimited comment + current += 2; + char* begin = current; + int begin_line = line; + while (current < end - 1 + && (current[0] != '*' || current[1] != '/')) { + if (current[0] == '\n') { + line++; + column = 0; + } + current++; + column++; + } + if (current == end - 1) { + Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, expected */"); + return true; + } + push_comment (((string) begin).ndup ((long) (current - begin)), begin_line == 1); + current += 2; + column += 2; + } + + return true; + } + + void space () { + while (whitespace () || comment ()) { + } + } + + void push_comment (string! comment_item, bool file_comment) { + if (_comment == null) { + _comment = comment_item; + } else { + _comment = "%s\n%s".printf (_comment, comment_item); + } + if (file_comment) { + source_file.comment = _comment; + _comment = null; + } + } + + /** + * Clears and returns the content of the comment stack. + * + * @return saved comment + */ + public string pop_comment () { + if (_comment == null) { + return null; + } + + var result = new StringBuilder (_comment); + _comment = null; + + weak string index; + while ((index = result.str.chr (-1, '\t')) != null) { + result.erase (result.str.pointer_to_offset (index), 1); + } + + return result.str; + } +} + diff --git a/vala/valascope.vala b/vala/valascope.vala index a223ba4..d2ae791 100644 --- a/vala/valascope.vala +++ b/vala/valascope.vala @@ -60,7 +60,7 @@ public class Vala.Scope : Object { symbol_table = new HashMap (str_hash, str_equal); } else if (lookup (name) != null) { owner.error = true; - Report.error (owner.source_reference, "`%s' already contains a definition for `%s'".printf (owner.get_full_name (), name)); + Report.error (sym.source_reference, "`%s' already contains a definition for `%s'".printf (owner.get_full_name (), name)); return; } @@ -68,7 +68,11 @@ public class Vala.Scope : Object { } sym.owner = this; } - + + public void remove (string name) { + symbol_table.remove (name); + } + /** * Returns the symbol stored in the symbol table with the specified * name. diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala index db955a6..ddb7aef 100644 --- a/vala/valasourcefile.vala +++ b/vala/valasourcefile.vala @@ -87,6 +87,8 @@ public class Vala.SourceFile : Object { private Gee.ArrayList source_array = null; + private MappedFile mapped_file = null; + /** * Creates a new source file. * @@ -124,6 +126,10 @@ public class Vala.SourceFile : Object { nodes.add (node); } + public void remove_node (CodeNode! node) { + nodes.remove (node); + } + /** * Returns a copy of the list of code nodes. * @@ -396,6 +402,17 @@ public class Vala.SourceFile : Object { } } + public char* get_mapped_contents () { + if (mapped_file == null) { + mapped_file = new MappedFile (filename, false); + } + + return mapped_file.get_contents (); + } + + public size_t get_mapped_length () { + return mapped_file.get_length (); + } } public enum Vala.SourceFileDependencyType { diff --git a/vala/valasourcelocation.vala b/vala/valasourcelocation.vala new file mode 100644 index 0000000..374a683 --- /dev/null +++ b/vala/valasourcelocation.vala @@ -0,0 +1,39 @@ +/* valasourcelocation.vala + * + * Copyright (C) 2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +/** + * Represents a position in a source file. + */ +public struct Vala.SourceLocation { + public char* pos; + public int line; + public int column; + + public SourceLocation (char* _pos, int _line, int _column) { + pos = _pos; + line = _line; + column = _column; + } +} + diff --git a/vala/valatokentype.vala b/vala/valatokentype.vala new file mode 100644 index 0000000..5a50847 --- /dev/null +++ b/vala/valatokentype.vala @@ -0,0 +1,256 @@ +/* valatokentype.vala + * + * Copyright (C) 2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +public enum Vala.TokenType { + NONE, + ABSTRACT, + AS, + ASSIGN, + ASSIGN_ADD, + ASSIGN_BITWISE_AND, + ASSIGN_BITWISE_OR, + ASSIGN_BITWISE_XOR, + ASSIGN_DIV, + ASSIGN_MUL, + ASSIGN_PERCENT, + ASSIGN_SHIFT_LEFT, + ASSIGN_SUB, + BASE, + BITWISE_AND, + BITWISE_OR, + BREAK, + CARRET, + CASE, + CATCH, + CHARACTER_LITERAL, + CLASS, + CLOSE_BRACE, + CLOSE_BRACKET, + CLOSE_PARENS, + COLON, + COMMA, + CONST, + CONSTRUCT, + CONTINUE, + DEFAULT, + DELEGATE, + DELETE, + DIV, + DO, + DOT, + ELLIPSIS, + ELSE, + ENUM, + ENSURES, + ERRORDOMAIN, + EOF, + FALSE, + FINALLY, + FOR, + FOREACH, + GET, + HASH, + IDENTIFIER, + IF, + IN, + INLINE, + INTEGER_LITERAL, + INTERFACE, + INTERR, + IS, + LAMBDA, + LOCK, + MINUS, + NAMESPACE, + NEW, + NULL, + OUT, + OP_AND, + OP_DEC, + OP_EQ, + OP_GE, + OP_GT, + OP_INC, + OP_LE, + OP_LT, + OP_NE, + OP_NEG, + OP_OR, + OP_PTR, + OP_SHIFT_LEFT, + OPEN_BRACE, + OPEN_BRACKET, + OPEN_PARENS, + OVERRIDE, + PERCENT, + PLUS, + PRIVATE, + PROTECTED, + PUBLIC, + REAL_LITERAL, + REF, + REQUIRES, + RETURN, + SEMICOLON, + SET, + SIGNAL, + SIZEOF, + STAR, + STATIC, + STRING_LITERAL, + STRUCT, + SWITCH, + THIS, + THROW, + THROWS, + TILDE, + TRUE, + TRY, + TYPEOF, + USING, + VAR, + VIRTUAL, + VOID, + VOLATILE, + WEAK, + WHILE; + + public weak string to_string () { + switch (this) { + case ABSTRACT: return "`abstract'"; + case AS: return "`as'"; + case ASSIGN: return "`='"; + case ASSIGN_ADD: return "`+='"; + case ASSIGN_BITWISE_AND: return "`&='"; + case ASSIGN_BITWISE_OR: return "`|='"; + case ASSIGN_BITWISE_XOR: return "`^='"; + case ASSIGN_DIV: return "`/='"; + case ASSIGN_MUL: return "`*='"; + case ASSIGN_PERCENT: return "`%='"; + case ASSIGN_SHIFT_LEFT: return "`<<='"; + case ASSIGN_SUB: return "`-='"; + case BASE: return "`base'"; + case BITWISE_AND: return "`&'"; + case BITWISE_OR: return "`|'"; + case BREAK: return "`break'"; + case CARRET: return "`^'"; + case CASE: return "`case'"; + case CATCH: return "`catch'"; + case CHARACTER_LITERAL: return "character literal"; + case CLASS: return "`class'"; + case CLOSE_BRACE: return "`}'"; + case CLOSE_BRACKET: return "`]'"; + case CLOSE_PARENS: return "`)'"; + case COLON: return "`:'"; + case COMMA: return "`,'"; + case CONST: return "`const'"; + case CONSTRUCT: return "`construct'"; + case CONTINUE: return "`continue'"; + case DEFAULT: return "`default'"; + case DELEGATE: return "`delegate'"; + case DELETE: return "`delete'"; + case DIV: return "`/'"; + case DO: return "`do'"; + case DOT: return "`.'"; + case ELLIPSIS: return "`...'"; + case ELSE: return "`else'"; + case ENUM: return "`enum'"; + case ENSURES: return "`ensures'"; + case ERRORDOMAIN: return "`errordomain'"; + case EOF: return "end of file"; + case FALSE: return "`false'"; + case FINALLY: return "`finally'"; + case FOR: return "`for'"; + case FOREACH: return "`foreach'"; + case GET: return "`get'"; + case HASH: return "`hash'"; + case IDENTIFIER: return "identifier"; + case IF: return "`if'"; + case IN: return "`in'"; + case INLINE: return "`inline'"; + case INTEGER_LITERAL: return "integer literal"; + case INTERFACE: return "`interface'"; + case INTERR: return "`?'"; + case IS: return "`is'"; + case LAMBDA: return "`=>'"; + case LOCK: return "`lock'"; + case MINUS: return "`-'"; + case NAMESPACE: return "`namespace'"; + case NEW: return "`new'"; + case NULL: return "`null'"; + case OUT: return "`out'"; + case OP_AND: return "`&&'"; + case OP_DEC: return "`--'"; + case OP_EQ: return "`=='"; + case OP_GE: return "`>='"; + case OP_GT: return "`>'"; + case OP_INC: return "`++'"; + case OP_LE: return "`<='"; + case OP_LT: return "`<'"; + case OP_NE: return "`!='"; + case OP_NEG: return "`!'"; + case OP_OR: return "`||'"; + case OP_PTR: return "`->'"; + case OP_SHIFT_LEFT: return "`<<'"; + case OPEN_BRACE: return "`{'"; + case OPEN_BRACKET: return "`['"; + case OPEN_PARENS: return "`('"; + case OVERRIDE: return "`override'"; + case PERCENT: return "`%'"; + case PLUS: return "`+'"; + case PRIVATE: return "`private'"; + case PROTECTED: return "`protected'"; + case PUBLIC: return "`public'"; + case REAL_LITERAL: return "real literal"; + case REF: return "`ref'"; + case REQUIRES: return "`requires'"; + case RETURN: return "`return'"; + case SEMICOLON: return "`;'"; + case SET: return "`set'"; + case SIGNAL: return "`signal'"; + case SIZEOF: return "`sizeof'"; + case STAR: return "`*'"; + case STATIC: return "`static'"; + case STRING_LITERAL: return "string literal"; + case STRUCT: return "`struct'"; + case SWITCH: return "`switch'"; + case THIS: return "`this'"; + case THROW: return "`throw'"; + case THROWS: return "`throws'"; + case TILDE: return "`~'"; + case TRUE: return "`true'"; + case TRY: return "`try'"; + case TYPEOF: return "`typeof'"; + case USING: return "`using'"; + case VAR: return "`var'"; + case VIRTUAL: return "`virtual'"; + case VOID: return "`void'"; + case VOLATILE: return "`volatile'"; + case WEAK: return "`weak'"; + case WHILE: return "`while'"; + default: return "unknown token"; + } + } +} + diff --git a/vala/valatuple.vala b/vala/valatuple.vala new file mode 100644 index 0000000..fc05984 --- /dev/null +++ b/vala/valatuple.vala @@ -0,0 +1,47 @@ +/* valatuple.vala + * + * Copyright (C) 2006-2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; +using Gee; + +/** + * Represents a fixed-length sequence of expressions in the source code. + */ +public class Vala.Tuple : Expression { + private Gee.List expression_list = new ArrayList (); + + public Tuple () { + } + + public void add_expression (Expression expr) { + expression_list.add (expr); + } + + public Gee.List get_expressions () { + return expression_list; + } + + public override bool is_pure () { + return false; + } +} + diff --git a/vala/valaunaryexpression.vala b/vala/valaunaryexpression.vala index 5b34458..cc6c964 100644 --- a/vala/valaunaryexpression.vala +++ b/vala/valaunaryexpression.vala @@ -103,6 +103,7 @@ public class Vala.UnaryExpression : Expression { } public enum Vala.UnaryOperator { + NONE, PLUS, MINUS, LOGICAL_NEGATION, diff --git a/vala/valaunresolvedtype.vala b/vala/valaunresolvedtype.vala index 97207bb..5330051 100644 --- a/vala/valaunresolvedtype.vala +++ b/vala/valaunresolvedtype.vala @@ -122,4 +122,8 @@ public class Vala.UnresolvedType : DataType { return result; } + + public override string to_string () { + return unresolved_symbol.to_string (); + } } -- 2.7.4