%{ // // cs-parser.jay: The Parser for the C# compiler // // Authors: Miguel de Icaza (miguel@gnome.org) // Ravi Pratap (ravi@ximian.com) // Marek Safar (marek.safar@gmail.com) // // Dual Licensed under the terms of the GNU GPL and the MIT X11 license // // (C) 2001 Ximian, Inc (http://www.ximian.com) // (C) 2004-2011 Novell, Inc // Copyright 2011-2012 Xamarin Inc. // using System.Text; using System.IO; using System; using System.Collections.Generic; namespace Mono.CSharp { /// /// The C# Parser /// public class CSharpParser { [Flags] enum ParameterModifierType { Ref = 1 << 1, Out = 1 << 2, This = 1 << 3, Params = 1 << 4, Arglist = 1 << 5, DefaultValue = 1 << 6, All = Ref | Out | This | Params | Arglist | DefaultValue, PrimaryConstructor = Ref | Out | Params | DefaultValue } static readonly object ModifierNone = 0; NamespaceContainer current_namespace; TypeContainer current_container; TypeDefinition current_type; PropertyBase current_property; EventProperty current_event; EventField current_event_field; FieldBase current_field; /// /// Current block is used to add statements as we find /// them. /// Block current_block; BlockVariable current_variable; Delegate current_delegate; AnonymousMethodExpression current_anonymous_method; /// /// This is used by the unary_expression code to resolve /// a name against a parameter. /// // FIXME: This is very ugly and it's very hard to reset it correctly // on all places, especially when some parameters are autogenerated. ParametersCompiled current_local_parameters; bool parsing_anonymous_method; bool async_block; /// /// An out-of-band stack. /// Stack oob_stack; /// /// Controls the verbosity of the errors produced by the parser /// int yacc_verbose_flag; /// /// Used by the interactive shell, flags whether EOF was reached /// and an error was produced /// public bool UnexpectedEOF; /// /// The current file. /// readonly CompilationSourceFile file; /// /// Temporary Xml documentation cache. /// For enum types, we need one more temporary store. /// string tmpComment; string enumTypeComment; /// Current attribute target string current_attr_target; ParameterModifierType valid_param_mod; bool default_parameter_used; /// When using the interactive parser, this holds the /// resulting expression public Class InteractiveResult; // // Keeps track of global data changes to undo on parser error // public Undo undo; bool? interactive_async; Stack linq_clause_blocks; ModuleContainer module; readonly CompilerContext compiler; readonly LanguageVersion lang_version; readonly bool doc_support; readonly CompilerSettings settings; readonly Report report; // // Instead of allocating carrier array everytime we // share the bucket for very common constructs which can never // be recursive // List parameters_bucket; // // Full AST support members // LocationsBag lbag; List> mod_locations; Stack location_stack; %} %token EOF %token NONE /* This token is never returned by our lexer */ %token ERROR // This is used not by the parser, but by the tokenizer. // do not remove. /* *These are the C# keywords */ %token FIRST_KEYWORD %token ABSTRACT %token AS %token ADD %token BASE %token BOOL %token BREAK %token BYTE %token CASE %token CATCH %token CHAR %token CHECKED %token CLASS %token CONST %token CONTINUE %token DECIMAL %token DEFAULT %token DELEGATE %token DO %token DOUBLE %token ELSE %token ENUM %token EVENT %token EXPLICIT %token EXTERN %token FALSE %token FINALLY %token FIXED %token FLOAT %token FOR %token FOREACH %token GOTO %token IF %token IMPLICIT %token IN %token INT %token INTERFACE %token INTERNAL %token IS %token LOCK %token LONG %token NAMESPACE %token NEW %token NULL %token OBJECT %token OPERATOR %token OUT %token OVERRIDE %token PARAMS %token PRIVATE %token PROTECTED %token PUBLIC %token READONLY %token REF %token RETURN %token REMOVE %token SBYTE %token SEALED %token SHORT %token SIZEOF %token STACKALLOC %token STATIC %token STRING %token STRUCT %token SWITCH %token THIS %token THROW %token TRUE %token TRY %token TYPEOF %token UINT %token ULONG %token UNCHECKED %token UNSAFE %token USHORT %token USING %token VIRTUAL %token VOID %token VOLATILE %token WHERE %token WHILE %token ARGLIST %token PARTIAL %token ARROW %token FROM %token FROM_FIRST %token JOIN %token ON %token EQUALS %token SELECT %token GROUP %token BY %token LET %token ORDERBY %token ASCENDING %token DESCENDING %token INTO %token INTERR_NULLABLE %token EXTERN_ALIAS %token REFVALUE %token REFTYPE %token MAKEREF %token ASYNC %token AWAIT %token INTERR_OPERATOR %token WHEN %token INTERPOLATED_STRING %token INTERPOLATED_STRING_END /* C# keywords which are not really keywords */ %token GET %token SET %left LAST_KEYWORD /* C# single character operators/punctuation. */ %token OPEN_BRACE %token CLOSE_BRACE %token OPEN_BRACKET %token CLOSE_BRACKET %token OPEN_PARENS %token CLOSE_PARENS %token DOT %token COMMA %token COLON %token SEMICOLON %token TILDE %token PLUS %token MINUS %token BANG %token ASSIGN %token OP_LT %token OP_GT %token BITWISE_AND %token BITWISE_OR %token STAR %token PERCENT %token DIV %token CARRET %token INTERR /* C# multi-character operators. */ %token DOUBLE_COLON %token OP_INC %token OP_DEC %token OP_SHIFT_LEFT %token OP_SHIFT_RIGHT %token OP_LE %token OP_GE %token OP_EQ %token OP_NE %token OP_AND %token OP_OR %token OP_MULT_ASSIGN %token OP_DIV_ASSIGN %token OP_MOD_ASSIGN %token OP_ADD_ASSIGN %token OP_SUB_ASSIGN %token OP_SHIFT_LEFT_ASSIGN %token OP_SHIFT_RIGHT_ASSIGN %token OP_AND_ASSIGN %token OP_XOR_ASSIGN %token OP_OR_ASSIGN %token OP_PTR %token OP_COALESCING /* Generics <,> tokens */ %token OP_GENERICS_LT %token OP_GENERICS_LT_DECL %token OP_GENERICS_GT %token LITERAL %token IDENTIFIER %token OPEN_PARENS_LAMBDA %token OPEN_PARENS_CAST %token GENERIC_DIMENSION %token DEFAULT_COLON %token OPEN_BRACKET_EXPR // Make the parser go into eval mode parsing (statements and compilation units). %token EVAL_STATEMENT_PARSER %token EVAL_COMPILATION_UNIT_PARSER %token EVAL_USING_DECLARATIONS_UNIT_PARSER %token DOC_SEE // // This token is generated to trigger the completion engine at this point // %token GENERATE_COMPLETION // // This token is return repeatedly after the first GENERATE_COMPLETION // token is produced and before the final EOF // %token COMPLETE_COMPLETION /* Add precedence rules to solve dangling else s/r conflict */ %nonassoc IF %nonassoc ELSE /* Define the operator tokens and their precedences */ %right ASSIGN %right OP_COALESCING %right INTERR %left OP_OR %left OP_AND %left BITWISE_OR %left BITWISE_AND %left OP_SHIFT_LEFT OP_SHIFT_RIGHT %left PLUS MINUS %left STAR DIV PERCENT %right BANG CARRET UMINUS %nonassoc OP_INC OP_DEC %left OPEN_PARENS %left OPEN_BRACKET OPEN_BRACE %left DOT %start compilation_unit %% compilation_unit : outer_declaration opt_EOF { Lexer.check_incorrect_doc_comment (); } | interactive_parsing { Lexer.CompleteOnEOF = false; } opt_EOF | documentation_parsing ; outer_declaration : opt_extern_alias_directives opt_using_directives | opt_extern_alias_directives opt_using_directives namespace_or_type_declarations opt_attributes { if ($4 != null) { Attributes attrs = (Attributes) $4; report.Error (1730, attrs.Attrs [0].Location, "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); current_namespace.UnattachedAttributes = attrs; } } | opt_extern_alias_directives opt_using_directives attribute_sections { Attributes attrs = (Attributes) $3; if (attrs != null) { foreach (var a in attrs.Attrs) { if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") continue; if (a.ExplicitTarget == null) report.Error (-1671, a.Location, "Global attributes must have attribute target specified"); } } module.AddAttributes ((Attributes) $3, current_namespace); } | error { if (yyToken == Token.EXTERN_ALIAS) report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); else Error_SyntaxError (yyToken); } ; opt_EOF : /* empty */ | EOF ; extern_alias_directives : extern_alias_directive | extern_alias_directives extern_alias_directive ; extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON { var lt = (LocatedToken) $2; string s = lt.Value; if (s != "alias") { syntax_error (lt.Location, "`alias' expected"); } else { if (lang_version == LanguageVersion.ISO_1) FeatureIsNotAvailable (lt.Location, "external alias"); lt = (LocatedToken) $3; if (lt.Value == QualifiedAliasMember.GlobalAlias) { RootNamespace.Error_GlobalNamespaceRedefined (report, lt.Location); } var na = new UsingExternAlias (new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)); current_namespace.AddUsing (na); lbag.AddLocation (na, GetLocation ($2), GetLocation ($4)); } } | EXTERN_ALIAS error { Error_SyntaxError (yyToken); } ; using_directives : using_directive | using_directives using_directive ; using_directive : using_namespace { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } ; using_namespace : USING opt_static namespace_or_type_expr SEMICOLON { UsingClause uc; if ($2 != null) { if (lang_version <= LanguageVersion.V_5) FeatureIsNotAvailable (GetLocation ($2), "using static"); uc = new UsingType ((ATypeNameExpression) $3, GetLocation ($1)); lbag.AddLocation (uc, GetLocation ($2), GetLocation ($4)); } else { uc = new UsingNamespace ((ATypeNameExpression) $3, GetLocation ($1)); lbag.AddLocation (uc, GetLocation ($4)); } current_namespace.AddUsing (uc); } | USING opt_static IDENTIFIER ASSIGN namespace_or_type_expr SEMICOLON { var lt = (LocatedToken) $3; if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { report.Warning (440, 2, lt.Location, "An alias named `global' will not be used when resolving `global::'. The global namespace will be used instead"); } if ($2 != null) { report.Error (8085, GetLocation ($2), "A `using static' directive cannot be used to declare an alias"); } var un = new UsingAliasNamespace (new SimpleMemberName (lt.Value, lt.Location), (ATypeNameExpression) $5, GetLocation ($1)); current_namespace.AddUsing (un); lbag.AddLocation (un, GetLocation ($4), GetLocation ($6)); } | USING error { Error_SyntaxError (yyToken); $$ = null; } ; opt_static : | STATIC ; // // Strictly speaking, namespaces don't have attributes but // we parse global attributes along with namespace declarations and then // detach them // namespace_declaration : opt_attributes NAMESPACE namespace_name { Attributes attrs = (Attributes) $1; var name = (MemberName) $3; if (attrs != null) { bool valid_global_attrs = true; if ((current_namespace.DeclarationFound || current_namespace != file)) { valid_global_attrs = false; } else { foreach (var a in attrs.Attrs) { if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") continue; valid_global_attrs = false; break; } } if (!valid_global_attrs) report.Error (1671, name.Location, "A namespace declaration cannot have modifiers or attributes"); } module.AddAttributes (attrs, current_namespace); var ns = new NamespaceContainer (name, current_namespace); current_namespace.AddTypeContainer (ns); current_container = current_namespace = ns; } OPEN_BRACE { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon_error { if ($11 != null) lbag.AddLocation (current_container, GetLocation ($2), GetLocation ($5), GetLocation ($10), GetLocation ($11)); else lbag.AddLocation (current_container, GetLocation ($2), GetLocation ($5), GetLocation ($10)); current_container = current_namespace = current_namespace.Parent; } | opt_attributes NAMESPACE namespace_name { report.Error (1514, lexer.Location, "Unexpected symbol `{0}', expecting `.' or `{{'", GetSymbolName (yyToken)); var name = (MemberName) $3; var ns = new NamespaceContainer (name, current_namespace); lbag.AddLocation (ns, GetLocation ($2)); current_namespace.AddTypeContainer (ns); } ; opt_semicolon_error : /* empty */ | SEMICOLON | error { Error_SyntaxError (yyToken); $$ = null; } ; namespace_name : IDENTIFIER { var lt = (LocatedToken) $1; $$ = new MemberName (lt.Value, lt.Location); } | namespace_name DOT IDENTIFIER { var lt = (LocatedToken) $3; $$ = new MemberName ((MemberName) $1, lt.Value, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | error { Error_SyntaxError (yyToken); $$ = new MemberName ("", lexer.Location); } ; opt_semicolon : /* empty */ | SEMICOLON ; opt_comma : /* empty */ | COMMA ; opt_using_directives : /* empty */ | using_directives ; opt_extern_alias_directives : /* empty */ | extern_alias_directives ; opt_namespace_or_type_declarations : /* empty */ | namespace_or_type_declarations ; namespace_or_type_declarations : namespace_or_type_declaration | namespace_or_type_declarations namespace_or_type_declaration ; namespace_or_type_declaration : type_declaration { if ($1 != null) { TypeContainer ds = (TypeContainer)$1; if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ report.Error (1527, ds.Location, "Namespace elements cannot be explicitly declared as private, protected or protected internal"); } // Here is a trick, for explicit attributes we don't know where they belong to until // we parse succeeding declaration hence we parse them as normal and re-attach them // when we know whether they are global (assembly:, module:) or local (type:). if (ds.OptAttributes != null) { ds.OptAttributes.ConvertGlobalAttributes (ds, current_namespace, !current_namespace.DeclarationFound && current_namespace == file); } } current_namespace.DeclarationFound = true; } | namespace_declaration { current_namespace.DeclarationFound = true; } | attribute_sections CLOSE_BRACE { current_namespace.UnattachedAttributes = (Attributes) $1; report.Error (1518, lexer.Location, "Attributes must be attached to class, delegate, enum, interface or struct"); lexer.putback ('}'); } ; type_declaration : class_declaration | struct_declaration | interface_declaration | enum_declaration | delegate_declaration // // Enable this when we have handled all errors, because this acts as a generic fallback // // | error { // Console.WriteLine ("Token=" + yyToken); // report.Error (1518, GetLocation ($1), "Expected class, struct, interface, enum or delegate"); // } ; // // Attributes // opt_attributes : /* empty */ | attribute_sections ; attribute_sections : attribute_section { var sect = (List) $1; $$ = new Attributes (sect); } | attribute_sections attribute_section { Attributes attrs = $1 as Attributes; var sect = (List) $2; if (attrs == null) attrs = new Attributes (sect); else if (sect != null) attrs.AddAttributes (sect); $$ = attrs; } ; attribute_section : OPEN_BRACKET { PushLocation (GetLocation ($1)); lexer.parsing_attribute_section = true; } attribute_section_cont { lexer.parsing_attribute_section = false; $$ = $3; } ; attribute_section_cont : attribute_target COLON { current_attr_target = (string) $1; if (current_attr_target == "assembly" || current_attr_target == "module") { Lexer.check_incorrect_doc_comment (); } } attribute_list opt_comma CLOSE_BRACKET { // when attribute target is invalid if (current_attr_target == string.Empty) $$ = new List (0); else $$ = $4; lbag.InsertLocation ($$, 0, PopLocation ()); if ($5 != null) { lbag.AddLocation ($$, GetLocation ($2), GetLocation ($5), GetLocation ($6)); } else { lbag.AddLocation ($$, GetLocation ($2), GetLocation ($6)); } current_attr_target = null; lexer.parsing_attribute_section = false; } | attribute_list opt_comma CLOSE_BRACKET { $$ = $1; lbag.InsertLocation ($$, 0, PopLocation ()); if ($2 != null) { lbag.AddLocation ($$, GetLocation($2), GetLocation ($3)); } else { lbag.AddLocation ($$, GetLocation($3)); } } | IDENTIFIER error { Error_SyntaxError (yyToken); var lt = (LocatedToken) $1; var tne = new SimpleName (lt.Value, null, lt.Location); $$ = new List () { new Attribute (null, tne, null, GetLocation ($1), false) }; } | error { if (CheckAttributeTarget (yyToken, GetTokenName (yyToken), GetLocation ($1)).Length > 0) Error_SyntaxError (yyToken); $$ = null; } ; attribute_target : IDENTIFIER { var lt = (LocatedToken) $1; $$ = CheckAttributeTarget (yyToken, lt.Value, lt.Location); } | EVENT { $$ = "event"; } | RETURN { $$ = "return"; } ; attribute_list : attribute { $$ = new List (4) { (Attribute) $1 }; } | attribute_list COMMA attribute { var attrs = (List) $1; if (attrs != null) { attrs.Add ((Attribute) $3); lbag.AppendTo (attrs, GetLocation ($2)); } $$ = attrs; } ; attribute : attribute_name { ++lexer.parsing_block; } opt_attribute_arguments { --lexer.parsing_block; var tne = (ATypeNameExpression) $1; if (tne.HasTypeArguments) { report.Error (404, tne.Location, "Attributes cannot be generic"); } $$ = new Attribute (current_attr_target, tne, (Arguments[]) $3, GetLocation ($1), lexer.IsEscapedIdentifier (tne)); } ; attribute_name : namespace_or_type_expr ; opt_attribute_arguments : /* empty */ { $$ = null; } | OPEN_PARENS attribute_arguments CLOSE_PARENS { $$ = $2; } ; attribute_arguments : /* empty */ { $$ = null; } | positional_or_named_argument { Arguments a = new Arguments (4); a.Add ((Argument) $1); $$ = new Arguments [] { a, null }; } | named_attribute_argument { Arguments a = new Arguments (4); a.Add ((Argument) $1); $$ = new Arguments [] { null, a }; } | attribute_arguments COMMA positional_or_named_argument { Arguments[] o = (Arguments[]) $1; if (o [1] != null) { report.Error (1016, ((Argument) $3).Expr.Location, "Named attribute arguments must appear after the positional arguments"); o [0] = new Arguments (4); } Arguments args = ((Arguments) o [0]); if (args.Count > 0 && !($3 is NamedArgument) && args [args.Count - 1] is NamedArgument) Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); } | attribute_arguments COMMA named_attribute_argument { Arguments[] o = (Arguments[]) $1; if (o [1] == null) { o [1] = new Arguments (4); } ((Arguments) o [1]).Add ((Argument) $3); } ; positional_or_named_argument : expression { $$ = new Argument ((Expression) $1); } | named_argument | error { Error_SyntaxError (yyToken); $$ = null; } ; named_attribute_argument : IDENTIFIER ASSIGN { ++lexer.parsing_block; } expression { --lexer.parsing_block; var lt = (LocatedToken) $1; $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4); lbag.AddLocation ($$, GetLocation($2)); } ; named_argument : identifier_inside_body COLON opt_named_modifier named_argument_expr { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (GetLocation ($1), "named argument"); // Avoid boxing in common case (no modifier) var arg_mod = $3 == null ? Argument.AType.None : (Argument.AType) $3; var lt = (LocatedToken) $1; $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod); lbag.AddLocation ($$, GetLocation($2)); } ; named_argument_expr : expression_or_error // | declaration_expression ; opt_named_modifier : /* empty */ { $$ = null; } | REF { $$ = Argument.AType.Ref; } | OUT { $$ = Argument.AType.Out; } ; opt_class_member_declarations : /* empty */ | class_member_declarations ; class_member_declarations : class_member_declaration { lexer.parsing_modifiers = true; lexer.parsing_block = 0; } | class_member_declarations class_member_declaration { lexer.parsing_modifiers = true; lexer.parsing_block = 0; } ; class_member_declaration : constant_declaration | field_declaration | method_declaration | property_declaration | event_declaration | indexer_declaration | operator_declaration | constructor_declaration | primary_constructor_body | destructor_declaration | type_declaration | attributes_without_members | incomplete_member | error { report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", GetSymbolName (yyToken)); $$ = null; lexer.parsing_generic_declaration = false; } ; primary_constructor_body : OPEN_BRACE { current_local_parameters = current_type.PrimaryConstructorParameters; if (current_local_parameters == null) { report.Error (9010, GetLocation ($1), "Primary constructor body is not allowed"); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; } ++lexer.parsing_block; start_block (GetLocation ($1)); } opt_statement_list block_end { current_local_parameters = null; var t = current_type as ClassOrStruct; if (t != null) { var b = (ToplevelBlock) $4; if (t.PrimaryConstructorBlock != null) { report.Error (8041, b.StartLocation, "Primary constructor already has a body"); } else { t.PrimaryConstructorBlock = b; } } } ; struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT { } type_declaration_name { lexer.ConstraintsParsing = true; valid_param_mod = ParameterModifierType.PrimaryConstructor; push_current_container (new Struct (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3); } opt_primary_parameters opt_class_base opt_type_parameter_constraints_clauses { valid_param_mod = 0; lexer.ConstraintsParsing = false; if ($8 != null) current_type.PrimaryConstructorParameters = (ParametersCompiled) $8; if ($10 != null) current_container.SetConstraints ((List) $10); if (doc_support) current_container.PartialContainer.DocComment = Lexer.consume_doc_comment (); lbag.AddMember (current_container, mod_locations, GetLocation ($4)); lexer.parsing_modifiers = true; } OPEN_BRACE { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } opt_class_member_declarations CLOSE_BRACE { --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } opt_semicolon { if ($16 == null) { lbag.AppendToMember (current_container, GetLocation ($12), GetLocation ($15)); } else { lbag.AppendToMember (current_container, GetLocation ($12), GetLocation ($15), GetLocation ($17)); } $$ = pop_current_class (); } | opt_attributes opt_modifiers opt_partial STRUCT error { Error_SyntaxError (yyToken); } ; constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER { var lt = (LocatedToken) $5; var mod = (Modifiers) $2; current_field = new Const (current_type, (FullNamedExpression) $4, mod, new MemberName (lt.Value, lt.Location), (Attributes) $1); current_type.AddMember (current_field); if ((mod & Modifiers.STATIC) != 0) { report.Error (504, current_field.Location, "The constant `{0}' cannot be marked static", current_field.GetSignatureForError ()); } $$ = current_field; } constant_initializer opt_constant_declarators SEMICOLON { if (doc_support) { current_field.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } current_field.Initializer = (ConstInitializer) $7; lbag.AddMember (current_field, mod_locations, GetLocation ($3), GetLocation ($9)); current_field = null; } | opt_attributes opt_modifiers CONST type error { Error_SyntaxError (yyToken); current_type.AddMember (new Const (current_type, (FullNamedExpression) $4, (Modifiers) $2, MemberName.Null, (Attributes) $1)); } ; opt_constant_declarators : /* empty */ | constant_declarators ; constant_declarators : constant_declarator { current_field.AddDeclarator ((FieldDeclarator) $1); } | constant_declarators constant_declarator { current_field.AddDeclarator ((FieldDeclarator) $2); } ; constant_declarator : COMMA IDENTIFIER constant_initializer { var lt = (LocatedToken) $2; $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); lbag.AddLocation ($$, GetLocation ($1)); } ; constant_initializer : ASSIGN { ++lexer.parsing_block; } constant_initializer_expr { --lexer.parsing_block; $$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); } | error { report.Error (145, lexer.Location, "A const field requires a value to be provided"); $$ = null; } ; constant_initializer_expr : constant_expression | array_initializer ; field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER { lexer.parsing_generic_declaration = false; FullNamedExpression type = (FullNamedExpression) $3; if (type.Type != null && type.Type.Kind == MemberKind.Void) report.Error (670, GetLocation ($3), "Fields cannot have void type"); var lt = (LocatedToken) $4; current_field = new Field (current_type, type, (Modifiers) $2, new MemberName (lt.Value, lt.Location), (Attributes) $1); current_type.AddField (current_field); $$ = current_field; } opt_field_initializer opt_field_declarators SEMICOLON { if (doc_support) { current_field.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } lbag.AddMember (current_field, mod_locations, GetLocation ($8)); $$ = current_field; current_field = null; } | opt_attributes opt_modifiers FIXED simple_type IDENTIFIER { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($3), "fixed size buffers"); var lt = (LocatedToken) $5; current_field = new FixedField (current_type, (FullNamedExpression) $4, (Modifiers) $2, new MemberName (lt.Value, lt.Location), (Attributes) $1); current_type.AddField (current_field); } fixed_field_size opt_fixed_field_declarators SEMICOLON { if (doc_support) { current_field.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } current_field.Initializer = (ConstInitializer) $7; lbag.AddMember (current_field, mod_locations, GetLocation ($9)); $$ = current_field; current_field = null; } | opt_attributes opt_modifiers FIXED simple_type error SEMICOLON { report.Error (1641, GetLocation ($5), "A fixed size buffer field must have the array size specifier after the field name"); } ; opt_field_initializer : /* empty */ | ASSIGN { ++lexer.parsing_block; current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; start_block (GetLocation ($1)); } variable_initializer { --lexer.parsing_block; current_field.Initializer = (Expression) $3; lbag.AppendToMember (current_field, GetLocation ($1)); end_block (lexer.Location); current_local_parameters = null; } ; opt_field_declarators : /* empty */ | field_declarators ; field_declarators : field_declarator { current_field.AddDeclarator ((FieldDeclarator) $1); } | field_declarators field_declarator { current_field.AddDeclarator ((FieldDeclarator) $2); } ; field_declarator : COMMA IDENTIFIER { var lt = (LocatedToken) $2; $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); lbag.AddLocation ($$, GetLocation ($1)); } | COMMA IDENTIFIER ASSIGN { ++lexer.parsing_block; } variable_initializer { --lexer.parsing_block; var lt = (LocatedToken) $2; $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } ; opt_fixed_field_declarators : /* empty */ | fixed_field_declarators ; fixed_field_declarators : fixed_field_declarator { current_field.AddDeclarator ((FieldDeclarator) $1); } | fixed_field_declarators fixed_field_declarator { current_field.AddDeclarator ((FieldDeclarator) $2); } ; fixed_field_declarator : COMMA IDENTIFIER fixed_field_size { var lt = (LocatedToken) $2; $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); lbag.AddLocation ($$, GetLocation ($1)); } ; fixed_field_size : OPEN_BRACKET { ++lexer.parsing_block; } expression CLOSE_BRACKET { --lexer.parsing_block; $$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($4)); } | OPEN_BRACKET error { report.Error (443, lexer.Location, "Value or constant expected"); $$ = null; } ; variable_initializer : expression | array_initializer | error { // It has to be here for the parent to safely restore artificial block Error_SyntaxError (yyToken); $$ = null; } ; method_declaration : method_header { if (doc_support) Lexer.doc_state = XmlCommentState.NotAllowed; // Was added earlier in the case of body being eof for full ast } method_body_expression_block { Method method = (Method) $1; method.Block = (ToplevelBlock) $3; async_block = false; if (method.Block == null) { method.ParameterInfo.CheckParameters (method); if ((method.ModFlags & Modifiers.ASYNC) != 0) { report.Error (1994, method.Location, "`{0}': The async modifier can only be used with methods that have a body", method.GetSignatureForError ()); } } else { if (current_container.Kind == MemberKind.Interface) { report.Error (531, method.Location, "`{0}': interface members cannot have a definition", method.GetSignatureForError ()); } } current_local_parameters = null; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } ; method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS { valid_param_mod = ParameterModifierType.All; } opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; MemberName name = (MemberName) $4; current_local_parameters = (ParametersCompiled) $7; var method = Method.Create (current_type, (FullNamedExpression) $3, (Modifiers) $2, name, current_local_parameters, (Attributes) $1); current_type.AddMember (method); async_block = (method.ModFlags & Modifiers.ASYNC) != 0; if (doc_support) method.DocComment = Lexer.consume_doc_comment (); lbag.AddMember (method, mod_locations, GetLocation ($5), GetLocation ($8)); $$ = method; lexer.ConstraintsParsing = true; } opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; if ($10 != null) { var method = (Method) $9; method.SetConstraints ((List) $10); } $$ = $9; } | opt_attributes opt_modifiers PARTIAL VOID { lexer.parsing_generic_declaration = true; } method_declaration_name OPEN_PARENS { lexer.parsing_generic_declaration = false; valid_param_mod = ParameterModifierType.All; } opt_formal_parameter_list CLOSE_PARENS { lexer.ConstraintsParsing = true; } opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; valid_param_mod = 0; MemberName name = (MemberName) $6; current_local_parameters = (ParametersCompiled) $9; var modifiers = (Modifiers) $2; modifiers |= Modifiers.PARTIAL; var method = Method.Create (current_type, new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)), modifiers, name, current_local_parameters, (Attributes) $1); current_type.AddMember (method); async_block = (method.ModFlags & Modifiers.ASYNC) != 0; if ($12 != null) method.SetConstraints ((List) $12); if (doc_support) method.DocComment = Lexer.consume_doc_comment (); StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($3)); lbag.AddMember (method, mod_locations, GetLocation ($7), GetLocation ($10)); $$ = method; } | opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { MemberName name = (MemberName) $5; report.Error (1585, name.Location, "Member modifier `{0}' must precede the member type and name", ModifiersExtensions.Name ((Modifiers) $4)); var method = Method.Create (current_type, (FullNamedExpression) $3, 0, name, (ParametersCompiled) $7, (Attributes) $1); current_type.AddMember (method); current_local_parameters = (ParametersCompiled) $7; if (doc_support) method.DocComment = Lexer.consume_doc_comment (); $$ = method; } | opt_attributes opt_modifiers member_type method_declaration_name error { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.Undefined; MemberName name = (MemberName) $4; var method = Method.Create (current_type, (FullNamedExpression) $3, (Modifiers) $2, name, current_local_parameters, (Attributes) $1); current_type.AddMember (method); if (doc_support) method.DocComment = Lexer.consume_doc_comment (); $$ = method; } ; method_body_expression_block : method_body | expression_block ; method_body : block | SEMICOLON { $$ = null; } ; expression_block : ARROW { if (lang_version < LanguageVersion.V_6) { FeatureIsNotAvailable (GetLocation ($1), "expression bodied members"); } ++lexer.parsing_block; start_block (GetLocation ($1)); } expression SEMICOLON { lexer.parsing_block = 0; current_block.AddStatement (new ContextualReturn ((Expression) $3)); var b = end_block (GetLocation ($4)); b.IsCompilerGenerated = true; $$ = b; } ; opt_formal_parameter_list : /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } | formal_parameter_list ; formal_parameter_list : fixed_parameters { var pars_list = (List) $1; $$ = new ParametersCompiled (pars_list.ToArray ()); } | fixed_parameters COMMA parameter_array { var pars_list = (List) $1; pars_list.Add ((Parameter) $3); $$ = new ParametersCompiled (pars_list.ToArray ()); } | fixed_parameters COMMA arglist_modifier { var pars_list = (List) $1; pars_list.Add (new ArglistParameter (GetLocation ($3))); $$ = new ParametersCompiled (pars_list.ToArray (), true); } | parameter_array COMMA error { if ($1 != null) report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list"); $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); } | fixed_parameters COMMA parameter_array COMMA error { if ($3 != null) report.Error (231, ((Parameter) $3).Location, "A params parameter must be the last parameter in a formal parameter list"); var pars_list = (List) $1; pars_list.Add (new ArglistParameter (GetLocation ($3))); $$ = new ParametersCompiled (pars_list.ToArray (), true); } | arglist_modifier COMMA error { report.Error (257, GetLocation ($1), "An __arglist parameter must be the last parameter in a formal parameter list"); $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); } | fixed_parameters COMMA ARGLIST COMMA error { report.Error (257, GetLocation ($3), "An __arglist parameter must be the last parameter in a formal parameter list"); var pars_list = (List) $1; pars_list.Add (new ArglistParameter (GetLocation ($3))); $$ = new ParametersCompiled (pars_list.ToArray (), true); } | parameter_array { $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); } | arglist_modifier { $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); } | error { Error_SyntaxError (yyToken); $$ = ParametersCompiled.EmptyReadOnlyParameters; } ; fixed_parameters : fixed_parameter { parameters_bucket.Clear (); Parameter p = (Parameter) $1; parameters_bucket.Add (p); default_parameter_used = p.HasDefaultValue; $$ = parameters_bucket; } | fixed_parameters COMMA fixed_parameter { var pars = (List) $1; Parameter p = (Parameter) $3; if (p != null) { if (p.HasExtensionMethodModifier) report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); else if (!p.HasDefaultValue && default_parameter_used) report.Error (1737, p.Location, "Optional parameter cannot precede required parameters"); default_parameter_used |= p.HasDefaultValue; pars.Add (p); lbag.AddLocation (p, GetLocation ($2)); } $$ = $1; } ; fixed_parameter : opt_attributes opt_parameter_modifier parameter_type identifier_inside_body { var lt = (LocatedToken) $4; $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); } | opt_attributes opt_parameter_modifier parameter_type identifier_inside_body OPEN_BRACKET CLOSE_BRACKET { var lt = (LocatedToken) $4; report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); } | attribute_sections error { Error_SyntaxError (yyToken); Location l = GetLocation ($2); $$ = new Parameter (null, null, Parameter.Modifier.NONE, (Attributes) $1, l); } | opt_attributes opt_parameter_modifier parameter_type error { Error_SyntaxError (yyToken); Location l = GetLocation ($4); $$ = new Parameter ((FullNamedExpression) $3, null, (Parameter.Modifier) $2, (Attributes) $1, l); } | opt_attributes opt_parameter_modifier parameter_type identifier_inside_body ASSIGN { ++lexer.parsing_block; } constant_expression { --lexer.parsing_block; if (lang_version <= LanguageVersion.V_3) { FeatureIsNotAvailable (GetLocation ($5), "optional parameter"); } Parameter.Modifier mod = (Parameter.Modifier) $2; if (mod != Parameter.Modifier.NONE) { switch (mod) { case Parameter.Modifier.REF: case Parameter.Modifier.OUT: report.Error (1741, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", Parameter.GetModifierSignature (mod)); break; case Parameter.Modifier.This: report.Error (1743, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", Parameter.GetModifierSignature (mod)); break; default: throw new NotImplementedException (mod.ToString ()); } mod = Parameter.Modifier.NONE; } if ((valid_param_mod & ParameterModifierType.DefaultValue) == 0) report.Error (1065, GetLocation ($5), "Optional parameter is not valid in this context"); var lt = (LocatedToken) $4; $$ = new Parameter ((FullNamedExpression) $3, lt.Value, mod, (Attributes) $1, lt.Location); lbag.AddLocation ($$, GetLocation ($5)); if ($7 != null) ((Parameter) $$).DefaultValue = new DefaultParameterValueExpression ((Expression) $7); } ; opt_parameter_modifier : /* empty */ { $$ = Parameter.Modifier.NONE; } | parameter_modifiers ; parameter_modifiers : parameter_modifier { $$ = $1; } | parameter_modifiers parameter_modifier { Parameter.Modifier p2 = (Parameter.Modifier)$2; Parameter.Modifier mod = (Parameter.Modifier)$1 | p2; if (((Parameter.Modifier)$1 & p2) == p2) { Error_DuplicateParameterModifier (lexer.Location, p2); } else { switch (mod & ~Parameter.Modifier.This) { case Parameter.Modifier.REF: report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); break; case Parameter.Modifier.OUT: report.Error (1102, lexer.Location, "The parameter modifiers `this' and `out' cannot be used altogether"); break; default: report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); break; } } $$ = mod; } ; parameter_modifier : REF { if ((valid_param_mod & ParameterModifierType.Ref) == 0) Error_ParameterModifierNotValid ("ref", GetLocation ($1)); $$ = Parameter.Modifier.REF; } | OUT { if ((valid_param_mod & ParameterModifierType.Out) == 0) Error_ParameterModifierNotValid ("out", GetLocation ($1)); $$ = Parameter.Modifier.OUT; } | THIS { if ((valid_param_mod & ParameterModifierType.This) == 0) Error_ParameterModifierNotValid ("this", GetLocation ($1)); if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "extension methods"); $$ = Parameter.Modifier.This; } ; parameter_array : opt_attributes params_modifier type IDENTIFIER { var lt = (LocatedToken) $4; $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); } | opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression { report.Error (1751, GetLocation ($2), "Cannot specify a default value for a parameter array"); var lt = (LocatedToken) $4; $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); } | opt_attributes params_modifier type error { Error_SyntaxError (yyToken); $$ = new ParamsParameter ((FullNamedExpression) $3, null, (Attributes) $1, Location.Null); } ; params_modifier : PARAMS { if ((valid_param_mod & ParameterModifierType.Params) == 0) report.Error (1670, (GetLocation ($1)), "The `params' modifier is not allowed in current context"); } | PARAMS parameter_modifier { Parameter.Modifier mod = (Parameter.Modifier)$2; if ((mod & Parameter.Modifier.This) != 0) { report.Error (1104, GetLocation ($1), "The parameter modifiers `this' and `params' cannot be used altogether"); } else { report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref or out"); } } | PARAMS params_modifier { Error_DuplicateParameterModifier (GetLocation ($1), Parameter.Modifier.PARAMS); } ; arglist_modifier : ARGLIST { if ((valid_param_mod & ParameterModifierType.Arglist) == 0) report.Error (1669, GetLocation ($1), "__arglist is not valid in this context"); } ; property_declaration : opt_attributes opt_modifiers member_type member_declaration_name { lexer.parsing_generic_declaration = false; if (doc_support) tmpComment = Lexer.consume_doc_comment (); } OPEN_BRACE { var type = (FullNamedExpression) $3; current_property = new Property (current_type, type, (Modifiers) $2, (MemberName) $4, (Attributes) $1); if (type.Type != null && type.Type.Kind == MemberKind.Void) report.Error (547, GetLocation ($3), "`{0}': property or indexer cannot have void type", current_property.GetSignatureForError ()); current_type.AddMember (current_property); lbag.AddMember (current_property, mod_locations, GetLocation ($6)); lexer.PropertyParsing = true; } accessor_declarations { lexer.PropertyParsing = false; if (doc_support) current_property.DocComment = ConsumeStoredComment (); } CLOSE_BRACE { lbag.AppendToMember (current_property, GetLocation ($10)); lexer.parsing_modifiers = true; } opt_property_initializer { current_property = null; } | opt_attributes opt_modifiers member_type member_declaration_name { lexer.parsing_generic_declaration = false; if (doc_support) tmpComment = Lexer.consume_doc_comment (); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; } expression_block { var type = (FullNamedExpression) $3; var property = new Property (current_type, type, (Modifiers) $2, (MemberName) $4, (Attributes) $1); property.Get = new Property.GetMethod (property, Modifiers.COMPILER_GENERATED, null, property.Location); property.Get.Block = (ToplevelBlock) $6; if (current_container.Kind == MemberKind.Interface) { report.Error (531, property.Get.Block.StartLocation, "`{0}': interface members cannot have a definition", property.GetSignatureForError ()); } if (type.Type != null && type.Type.Kind == MemberKind.Void) report.Error (547, GetLocation ($3), "`{0}': property or indexer cannot have void type", property.GetSignatureForError ()); if (doc_support) property.DocComment = ConsumeStoredComment (); current_type.AddMember (property); current_local_parameters = null; } ; opt_property_initializer : /* empty */ | ASSIGN { ++lexer.parsing_block; current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; start_block (GetLocation ($1)); } property_initializer SEMICOLON { --lexer.parsing_block; ((Property)current_property).Initializer = (Expression) $3; lbag.AppendToMember (current_property, GetLocation ($1), GetLocation ($4)); end_block (GetLocation ($4)); current_local_parameters = null; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } ; property_initializer : expression | array_initializer ; indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET { valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; } opt_formal_parameter_list CLOSE_BRACKET { valid_param_mod = 0; var type = (FullNamedExpression) $3; Indexer indexer = new Indexer (current_type, type, (MemberName) $4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1); current_property = indexer; current_type.AddIndexer (indexer); lbag.AddMember (current_property, mod_locations, GetLocation ($5), GetLocation ($8)); if (type.Type != null && type.Type.Kind == MemberKind.Void) report.Error (620, GetLocation ($3), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ()); if (indexer.ParameterInfo.IsEmpty) { report.Error (1551, GetLocation ($5), "Indexers must have at least one parameter"); } if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } lexer.PropertyParsing = true; current_local_parameters = (ParametersCompiled) $7; } indexer_body { lexer.PropertyParsing = false; current_local_parameters = null; if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) ((Indexer) current_property).ParameterInfo.CheckParameters (current_property); if (doc_support) current_property.DocComment = ConsumeStoredComment (); current_property = null; } ; indexer_body : OPEN_BRACE accessor_declarations CLOSE_BRACE { lbag.AppendToMember (current_property, GetLocation ($1), GetLocation ($3)); } | expression_block { current_property.Get = new Indexer.GetIndexerMethod (current_property, Modifiers.COMPILER_GENERATED, current_local_parameters, null, current_property.Location); current_property.Get.Block = (ToplevelBlock) $1; } ; accessor_declarations : get_accessor_declaration | get_accessor_declaration accessor_declarations | set_accessor_declaration | set_accessor_declaration accessor_declarations | error { if (yyToken == Token.CLOSE_BRACE) { report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); } else { if (yyToken == Token.SEMICOLON) report.Error (1597, lexer.Location, "Semicolon after method or accessor block is not valid"); else report.Error (1014, GetLocation ($1), "A get or set accessor expected"); } } ; get_accessor_declaration : opt_attributes opt_modifiers GET { if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); } if (current_property.Get != null) { report.Error (1007, GetLocation ($3), "Property accessor already defined"); } if (current_property is Indexer) { current_property.Get = new Indexer.GetIndexerMethod (current_property, (Modifiers) $2, ((Indexer)current_property).ParameterInfo.Clone (), (Attributes) $1, GetLocation ($3)); } else { current_property.Get = new Property.GetMethod (current_property, (Modifiers) $2, (Attributes) $1, GetLocation ($3)); } current_local_parameters = current_property.Get.ParameterInfo; lbag.AddMember (current_property.Get, mod_locations); lexer.PropertyParsing = false; } accessor_body { if ($5 != null) { current_property.Get.Block = (ToplevelBlock) $5; if (current_container.Kind == MemberKind.Interface) { report.Error (531, current_property.Get.Block.StartLocation, "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); } } current_local_parameters = null; lexer.PropertyParsing = true; if (doc_support) if (Lexer.doc_state == XmlCommentState.Error) Lexer.doc_state = XmlCommentState.NotAllowed; } ; set_accessor_declaration : opt_attributes opt_modifiers SET { if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); } if (current_property.Set != null) { report.Error (1007, GetLocation ($3), "Property accessor already defined"); } if (current_property is Indexer) { current_property.Set = new Indexer.SetIndexerMethod (current_property, (Modifiers) $2, ParametersCompiled.MergeGenerated (compiler, ((Indexer)current_property).ParameterInfo, true, new Parameter ( current_property.TypeExpression, "value", Parameter.Modifier.NONE, null, GetLocation ($3)), null), (Attributes) $1, GetLocation ($3)); } else { current_property.Set = new Property.SetMethod (current_property, (Modifiers) $2, ParametersCompiled.CreateImplicitParameter (current_property.TypeExpression, GetLocation ($3)), (Attributes) $1, GetLocation ($3)); } current_local_parameters = current_property.Set.ParameterInfo; lbag.AddMember (current_property.Set, mod_locations); lexer.PropertyParsing = false; } accessor_body { if ($5 != null) { current_property.Set.Block = (ToplevelBlock) $5; if (current_container.Kind == MemberKind.Interface) { report.Error (531, current_property.Set.Block.StartLocation, "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); } } current_local_parameters = null; lexer.PropertyParsing = true; if (doc_support && Lexer.doc_state == XmlCommentState.Error) Lexer.doc_state = XmlCommentState.NotAllowed; } ; accessor_body : block | SEMICOLON { // TODO: lbag $$ = null; } | error { Error_SyntaxError (1043, yyToken, "Invalid accessor body"); $$ = null; } ; interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE { } type_declaration_name { lexer.ConstraintsParsing = true; push_current_container (new Interface (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3); lbag.AddMember (current_container, mod_locations, GetLocation ($4)); } opt_class_base opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; if ($9 != null) current_container.SetConstraints ((List) $9); if (doc_support) { current_container.PartialContainer.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } lexer.parsing_modifiers = true; } OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE { --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } opt_semicolon { if ($15 == null) { lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13)); } else { lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13), GetLocation ($15)); } $$ = pop_current_class (); } | opt_attributes opt_modifiers opt_partial INTERFACE error { Error_SyntaxError (yyToken); } ; opt_interface_member_declarations : /* empty */ | interface_member_declarations ; interface_member_declarations : interface_member_declaration { lexer.parsing_modifiers = true; lexer.parsing_block = 0; } | interface_member_declarations interface_member_declaration { lexer.parsing_modifiers = true; lexer.parsing_block = 0; } ; interface_member_declaration : constant_declaration { report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); } | field_declaration { report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); } | method_declaration | property_declaration | event_declaration | indexer_declaration | operator_declaration { report.Error (567, GetLocation ($1), "Interfaces cannot contain operators"); } | constructor_declaration { report.Error (526, GetLocation ($1), "Interfaces cannot contain contructors"); } | type_declaration { report.Error (524, GetLocation ($1), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); } ; operator_declaration : opt_attributes opt_modifiers operator_declarator { } method_body_expression_block { OperatorDeclaration decl = (OperatorDeclaration) $3; if (decl != null) { Operator op = new Operator ( current_type, decl.optype, decl.ret_type, (Modifiers) $2, current_local_parameters, (ToplevelBlock) $5, (Attributes) $1, decl.location); if (op.Block == null) op.ParameterInfo.CheckParameters (op); if (doc_support) { op.DocComment = tmpComment; Lexer.doc_state = XmlCommentState.Allowed; } // Note again, checking is done in semantic analysis current_type.AddOperator (op); lbag.AddMember (op, mod_locations, lbag.GetLocations (decl)); } current_local_parameters = null; } ; operator_type : type_expression_or_array | VOID { report.Error (590, GetLocation ($1), "User-defined operators cannot return void"); $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); } ; operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS { valid_param_mod = ParameterModifierType.DefaultValue; if ((Operator.OpType) $3 == Operator.OpType.Is) valid_param_mod |= ParameterModifierType.Out; } opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; Location loc = GetLocation ($2); Operator.OpType op = (Operator.OpType) $3; current_local_parameters = (ParametersCompiled)$6; int p_count = current_local_parameters.Count; if (p_count == 1) { if (op == Operator.OpType.Addition) op = Operator.OpType.UnaryPlus; else if (op == Operator.OpType.Subtraction) op = Operator.OpType.UnaryNegation; } if (IsUnaryOperator (op)) { if (p_count == 2) { report.Error (1020, loc, "Overloadable binary operator expected"); } else if (p_count != 1) { report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", Operator.GetName (op)); } } else if (op == Operator.OpType.Is) { // TODO: Special checks for is operator } else { if (p_count == 1) { report.Error (1019, loc, "Overloadable unary operator expected"); } else if (p_count != 2) { report.Error (1534, loc, "Overloaded binary operator `{0}' takes two parameters", Operator.GetName (op)); } } if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; } $$ = new OperatorDeclaration (op, (FullNamedExpression) $1, loc); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3), GetLocation ($4), GetLocation ($7)); } | conversion_operator_declarator ; overloadable_operator // Unary operators: : BANG { $$ = Operator.OpType.LogicalNot; } | TILDE { $$ = Operator.OpType.OnesComplement; } | OP_INC { $$ = Operator.OpType.Increment; } | OP_DEC { $$ = Operator.OpType.Decrement; } | TRUE { $$ = Operator.OpType.True; } | FALSE { $$ = Operator.OpType.False; } // Unary and binary: | PLUS { $$ = Operator.OpType.Addition; } | MINUS { $$ = Operator.OpType.Subtraction; } // Binary: | STAR { $$ = Operator.OpType.Multiply; } | DIV { $$ = Operator.OpType.Division; } | PERCENT { $$ = Operator.OpType.Modulus; } | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; } | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; } | CARRET { $$ = Operator.OpType.ExclusiveOr; } | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; } | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; } | OP_EQ { $$ = Operator.OpType.Equality; } | OP_NE { $$ = Operator.OpType.Inequality; } | OP_GT { $$ = Operator.OpType.GreaterThan; } | OP_LT { $$ = Operator.OpType.LessThan; } | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; } | OP_LE { $$ = Operator.OpType.LessThanOrEqual; } | IS { if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($1), "is user operator"); $$ = Operator.OpType.Is; } ; conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS { valid_param_mod = ParameterModifierType.DefaultValue; } opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; Location loc = GetLocation ($2); current_local_parameters = (ParametersCompiled)$6; if (current_local_parameters.Count != 1) { report.Error (1535, loc, "Overloaded unary operator `implicit' takes one parameter"); } if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; } $$ = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) $3, loc); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); } | EXPLICIT OPERATOR type OPEN_PARENS { valid_param_mod = ParameterModifierType.DefaultValue; } opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; Location loc = GetLocation ($2); current_local_parameters = (ParametersCompiled)$6; if (current_local_parameters.Count != 1) { report.Error (1535, loc, "Overloaded unary operator `explicit' takes one parameter"); } if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; } $$ = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) $3, loc); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); } | IMPLICIT error { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; $$ = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation ($1)); } | EXPLICIT error { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; $$ = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation ($1)); } ; constructor_declaration : constructor_declarator constructor_body { Constructor c = (Constructor) $1; c.Block = (ToplevelBlock) $2; if (doc_support) c.DocComment = ConsumeStoredComment (); current_local_parameters = null; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } ; constructor_declarator : opt_attributes opt_modifiers IDENTIFIER { if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } valid_param_mod = ParameterModifierType.All; } OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; current_local_parameters = (ParametersCompiled) $6; var lt = (LocatedToken) $3; var mods = (Modifiers) $2; var c = new Constructor (current_type, lt.Value, mods, (Attributes) $1, current_local_parameters, lt.Location); if (lt.Value != current_container.MemberName.Name) { report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); } else if ((mods & Modifiers.STATIC) != 0) { if (!current_local_parameters.IsEmpty) { report.Error (132, c.Location, "`{0}': The static constructor must be parameterless", c.GetSignatureForError ()); } if ((mods & Modifiers.AccessibilityMask) != 0){ report.Error (515, c.Location, "`{0}': static constructor cannot have an access modifier", c.GetSignatureForError ()); } } else { if (current_type.Kind == MemberKind.Struct && current_local_parameters.IsEmpty) { report.Error (568, c.Location, "Structs cannot contain explicit parameterless constructors"); } } current_type.AddConstructor (c); lbag.AddMember (c, mod_locations, GetLocation ($5), GetLocation ($7)); $$ = c; // // start block here, so possible anonymous methods inside // constructor initializer can get correct parent block // start_block (lexer.Location); } opt_constructor_initializer { if ($9 != null) { var c = (Constructor) $8; c.Initializer = (ConstructorInitializer) $9; if (c.IsStatic) { report.Error (514, c.Location, "`{0}': static constructor cannot have an explicit `this' or `base' constructor call", c.GetSignatureForError ()); } } $$ = $8; } ; constructor_body : block_prepared | SEMICOLON { current_block = null; $$ = null; } ; opt_constructor_initializer : /* Empty */ | constructor_initializer ; constructor_initializer : COLON BASE OPEN_PARENS { ++lexer.parsing_block; } opt_argument_list CLOSE_PARENS { --lexer.parsing_block; $$ = new ConstructorBaseInitializer ((Arguments) $5, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); } | COLON THIS OPEN_PARENS { ++lexer.parsing_block; } opt_argument_list CLOSE_PARENS { --lexer.parsing_block; $$ = new ConstructorThisInitializer ((Arguments) $5, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); } | COLON error { Error_SyntaxError (yyToken); $$ = new ConstructorThisInitializer (null, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($1)); } | error { Error_SyntaxError (yyToken); $$ = null; } ; destructor_declaration : opt_attributes opt_modifiers TILDE { if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; } current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; } IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body { var lt = (LocatedToken) $5; if (lt.Value != current_container.MemberName.Name){ report.Error (574, lt.Location, "Name of destructor must match name of class"); } else if (current_container.Kind != MemberKind.Class){ report.Error (575, lt.Location, "Only class types can contain destructor"); } Destructor d = new Destructor (current_type, (Modifiers) $2, ParametersCompiled.EmptyReadOnlyParameters, (Attributes) $1, lt.Location); if (doc_support) d.DocComment = ConsumeStoredComment (); d.Block = (ToplevelBlock) $8; current_type.AddMember (d); lbag.AddMember (d, mod_locations, GetLocation ($3), GetLocation ($6), GetLocation ($7)); current_local_parameters = null; } ; event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name { current_event_field = new EventField (current_type, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); current_type.AddMember (current_event_field); if (current_event_field.MemberName.ExplicitInterface != null) { report.Error (71, current_event_field.Location, "`{0}': An explicit interface implementation of an event must use property syntax", current_event_field.GetSignatureForError ()); } $$ = current_event_field; } opt_event_initializer opt_event_declarators SEMICOLON { if (doc_support) { current_event_field.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } lbag.AddMember (current_event_field, mod_locations, GetLocation ($3), GetLocation ($9)); current_event_field = null; } | opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE { current_event = new EventProperty (current_type, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); current_type.AddMember (current_event); lbag.AddMember (current_event, mod_locations, GetLocation ($3), GetLocation ($6)); lexer.EventParsing = true; } event_accessor_declarations { if (current_container.Kind == MemberKind.Interface) report.Error (69, GetLocation ($6), "Event in interface cannot have add or remove accessors"); lexer.EventParsing = false; } CLOSE_BRACE { if (doc_support) { current_event.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } lbag.AppendToMember (current_event, GetLocation ($9)); current_event = null; current_local_parameters = null; } | opt_attributes opt_modifiers EVENT type error { Error_SyntaxError (yyToken); current_type.AddMember (new EventField (current_type, (FullNamedExpression) $4, (Modifiers) $2, MemberName.Null, (Attributes) $1)); } ; opt_event_initializer : /* empty */ | ASSIGN { ++lexer.parsing_block; } event_variable_initializer { --lexer.parsing_block; current_event_field.Initializer = (Expression) $3; } ; opt_event_declarators : /* empty */ | event_declarators ; event_declarators : event_declarator { current_event_field.AddDeclarator ((FieldDeclarator) $1); } | event_declarators event_declarator { current_event_field.AddDeclarator ((FieldDeclarator) $2); } ; event_declarator : COMMA IDENTIFIER { var lt = (LocatedToken) $2; $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); lbag.AddLocation ($$, GetLocation ($1)); } | COMMA IDENTIFIER ASSIGN { ++lexer.parsing_block; } event_variable_initializer { --lexer.parsing_block; var lt = (LocatedToken) $2; $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } ; event_variable_initializer : { if (current_container.Kind == MemberKind.Interface) { report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", current_event_field.GetSignatureForError ()); } if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) { report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer", current_event_field.GetSignatureForError ()); } } variable_initializer { $$ = $2; } ; event_accessor_declarations : add_accessor_declaration remove_accessor_declaration | remove_accessor_declaration add_accessor_declaration | add_accessor_declaration { report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", current_event.GetSignatureForError ()); } | remove_accessor_declaration { report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", current_event.GetSignatureForError ()); } | error { report.Error (1055, GetLocation ($1), "An add or remove accessor expected"); $$ = null; } ; add_accessor_declaration : opt_attributes opt_modifiers ADD { if ($2 != ModifierNone) { report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); } current_event.Add = new EventProperty.AddDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); current_local_parameters = current_event.Add.ParameterInfo; lbag.AddMember (current_event.Add, mod_locations); lexer.EventParsing = false; } event_accessor_block { lexer.EventParsing = true; current_event.Add.Block = (ToplevelBlock) $5; if (current_container.Kind == MemberKind.Interface) { report.Error (531, current_event.Add.Block.StartLocation, "`{0}': interface members cannot have a definition", current_event.Add.GetSignatureForError ()); } current_local_parameters = null; } ; remove_accessor_declaration : opt_attributes opt_modifiers REMOVE { if ($2 != ModifierNone) { report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); } current_event.Remove = new EventProperty.RemoveDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); current_local_parameters = current_event.Remove.ParameterInfo; lbag.AddMember (current_event.Remove, mod_locations); lexer.EventParsing = false; } event_accessor_block { lexer.EventParsing = true; current_event.Remove.Block = (ToplevelBlock) $5; if (current_container.Kind == MemberKind.Interface) { report.Error (531, current_event.Remove.Block.StartLocation, "`{0}': interface members cannot have a definition", current_event.Remove.GetSignatureForError ()); } current_local_parameters = null; } ; event_accessor_block : opt_semicolon { report.Error (73, lexer.Location, "An add or remove accessor must have a body"); $$ = null; } | block; ; attributes_without_members : attribute_sections CLOSE_BRACE { current_type.UnattachedAttributes = (Attributes) $1; report.Error (1519, GetLocation ($1), "An attribute is missing member declaration"); lexer.putback ('}'); } ; // For full ast try to recover incomplete ambiguous member // declaration in form on class X { public int } incomplete_member : opt_attributes opt_modifiers member_type CLOSE_BRACE { report.Error (1519, lexer.Location, "Unexpected symbol `}' in class, struct, or interface member declaration"); lexer.putback ('}'); lexer.parsing_generic_declaration = false; FullNamedExpression type = (FullNamedExpression) $3; current_field = new Field (current_type, type, (Modifiers) $2, MemberName.Null, (Attributes) $1); current_type.AddField (current_field); $$ = current_field; } ; enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base { if (doc_support) enumTypeComment = Lexer.consume_doc_comment (); } OPEN_BRACE { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; MemberName name = (MemberName) $4; if (name.IsGeneric) { report.Error (1675, name.Location, "Enums cannot have type parameters"); } push_current_container (new Enum (current_container, (FullNamedExpression) $5, (Modifiers) $2, name, (Attributes) $1), null); } opt_enum_member_declarations { lexer.parsing_modifiers = true; // here will be evaluated after CLOSE_BLACE is consumed. if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } CLOSE_BRACE opt_semicolon { if (doc_support) current_container.DocComment = enumTypeComment; --lexer.parsing_declaration; // if (doc_support) // em.DocComment = ev.DocComment; lbag.AddMember (current_container, mod_locations, GetLocation ($3), GetLocation ($7), GetLocation ($11)); $$ = pop_current_class (); } ; opt_enum_base : /* empty */ | COLON type { $$ = $2; } | COLON error { Error_TypeExpected (GetLocation ($1)); $$ = null; } ; opt_enum_member_declarations : /* empty */ | enum_member_declarations | enum_member_declarations COMMA { lbag.AddLocation ($1, GetLocation ($2)); } ; enum_member_declarations : enum_member_declaration | enum_member_declarations COMMA enum_member_declaration { lbag.AddLocation ($1, GetLocation ($2)); $$ = $3; } ; enum_member_declaration : opt_attributes IDENTIFIER { var lt = (LocatedToken) $2; var em = new EnumMember ((Enum) current_type, new MemberName (lt.Value, lt.Location), (Attributes) $1); ((Enum) current_type).AddEnumMember (em); if (doc_support) { em.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } $$ = em; } | opt_attributes IDENTIFIER { ++lexer.parsing_block; if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; } } ASSIGN constant_expression { --lexer.parsing_block; var lt = (LocatedToken) $2; var em = new EnumMember ((Enum) current_type, new MemberName (lt.Value, lt.Location), (Attributes) $1); em.Initializer = new ConstInitializer (em, (Expression) $5, GetLocation ($4)); ((Enum) current_type).AddEnumMember (em); if (doc_support) em.DocComment = ConsumeStoredComment (); $$ = em; } | opt_attributes IDENTIFIER error { Error_SyntaxError (yyToken); var lt = (LocatedToken) $2; var em = new EnumMember ((Enum) current_type, new MemberName (lt.Value, lt.Location), (Attributes) $1); ((Enum) current_type).AddEnumMember (em); if (doc_support) { em.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } $$ = em; } | attributes_without_members ; delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; } opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; ParametersCompiled p = (ParametersCompiled) $8; Delegate del = new Delegate (current_container, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, p, (Attributes) $1); p.CheckParameters (del); current_container.AddTypeContainer (del); current_delegate = del; lexer.ConstraintsParsing = true; } opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; } SEMICOLON { if (doc_support) { current_delegate.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } if ($11 != null) current_delegate.SetConstraints ((List) $11); lbag.AddMember (current_delegate, mod_locations, GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($13)); $$ = current_delegate; current_delegate = null; } ; opt_nullable : /* empty */ | INTERR_NULLABLE { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "nullable types"); $$ = ComposedTypeSpecifier.CreateNullable (GetLocation ($1)); } ; namespace_or_type_expr : member_name | qualified_alias_member IDENTIFIER opt_type_argument_list { var lt1 = (LocatedToken) $1; var lt2 = (LocatedToken) $2; $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); lbag.AddLocation ($$, GetLocation ($2)); } | qualified_alias_member IDENTIFIER generic_dimension { var lt1 = (LocatedToken) $1; var lt2 = (LocatedToken) $2; $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) $3, lt1.Location); lbag.AddLocation ($$, GetLocation ($2)); } ; member_name : simple_name_expr | namespace_or_type_expr DOT IDENTIFIER opt_type_argument_list { var lt = (LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | namespace_or_type_expr DOT IDENTIFIER generic_dimension { var lt = (LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } ; simple_name_expr : IDENTIFIER opt_type_argument_list { var lt = (LocatedToken) $1; $$ = new SimpleName (lt.Value, (TypeArguments)$2, lt.Location); } | IDENTIFIER generic_dimension { var lt = (LocatedToken) $1; $$ = new SimpleName (lt.Value, (int) $2, lt.Location); } ; // // Generics arguments (any type, without attributes) // opt_type_argument_list : /* empty */ | OP_GENERICS_LT type_arguments OP_GENERICS_GT { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "generics"); $$ = $2; } | OP_GENERICS_LT error { Error_TypeExpected (lexer.Location); $$ = new TypeArguments (); } ; type_arguments : type { TypeArguments type_args = new TypeArguments (); type_args.Add ((FullNamedExpression) $1); $$ = type_args; } | type_arguments COMMA type { TypeArguments type_args = (TypeArguments) $1; type_args.Add ((FullNamedExpression) $3); $$ = type_args; } ; // // Generics parameters (identifiers only, with attributes), used in type or method declarations // type_declaration_name : IDENTIFIER { lexer.parsing_generic_declaration = true; } opt_type_parameter_list { lexer.parsing_generic_declaration = false; var lt = (LocatedToken) $1; $$ = new MemberName (lt.Value, (TypeParameters)$3, lt.Location); } ; member_declaration_name : method_declaration_name { MemberName mn = (MemberName)$1; if (mn.TypeParameters != null) syntax_error (mn.Location, string.Format ("Member `{0}' cannot declare type arguments", mn.GetSignatureForError ())); } ; method_declaration_name : type_declaration_name | explicit_interface IDENTIFIER opt_type_parameter_list { lexer.parsing_generic_declaration = false; var lt = (LocatedToken) $2; $$ = new MemberName (lt.Value, (TypeParameters) $3, (ATypeNameExpression) $1, lt.Location); } ; indexer_declaration_name : THIS { lexer.parsing_generic_declaration = false; $$ = new MemberName (TypeDefinition.DefaultIndexerName, GetLocation ($1)); } | explicit_interface THIS { lexer.parsing_generic_declaration = false; $$ = new MemberName (TypeDefinition.DefaultIndexerName, null, (ATypeNameExpression) $1, GetLocation ($2)); } ; explicit_interface : IDENTIFIER opt_type_argument_list DOT { var lt = (LocatedToken) $1; $$ = new SimpleName (lt.Value, (TypeArguments) $2, lt.Location); lbag.AddLocation ($$, GetLocation ($3)); } | qualified_alias_member IDENTIFIER opt_type_argument_list DOT { var lt1 = (LocatedToken) $1; var lt2 = (LocatedToken) $2; $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); lbag.AddLocation ($$, GetLocation ($4)); } | explicit_interface IDENTIFIER opt_type_argument_list DOT { var lt = (LocatedToken) $2; $$ = new MemberAccess ((ATypeNameExpression) $1, lt.Value, (TypeArguments) $3, lt.Location); lbag.AddLocation ($$, GetLocation ($4)); } ; opt_type_parameter_list : /* empty */ | OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "generics"); $$ = $2; lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } ; type_parameters : type_parameter { var tparams = new TypeParameters (); tparams.Add ((TypeParameter)$1); $$ = tparams; } | type_parameters COMMA type_parameter { var tparams = (TypeParameters) $1; tparams.Add ((TypeParameter)$3); $$ = tparams; lbag.AddLocation ($3, GetLocation ($3)); } ; type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER { var lt = (LocatedToken)$3; $$ = new TypeParameter (new MemberName (lt.Value, lt.Location), (Attributes)$1, (VarianceDecl) $2); } | error { if (GetTokenName (yyToken) == "type") report.Error (81, GetLocation ($1), "Type parameter declaration must be an identifier not a type"); else Error_SyntaxError (yyToken); $$ = new TypeParameter (MemberName.Null, null, null); } ; // // All types where void is allowed // type_and_void : type_expression_or_array | VOID { $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); } ; member_type : type_and_void { lexer.parsing_generic_declaration = true; } ; // // A type which does not allow `void' to be used // type : type_expression_or_array | void_invalid ; simple_type : type_expression | void_invalid ; parameter_type : type_expression_or_array | VOID { report.Error (1536, GetLocation ($1), "Invalid parameter type `void'"); $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); } ; type_expression_or_array : type_expression | type_expression rank_specifiers { $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); } ; type_expression : namespace_or_type_expr opt_nullable { if ($2 != null) { $$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2); } else { var sn = $1 as SimpleName; if (sn != null && sn.Name == "var") $$ = new VarExpr (sn.Location); else $$ = $1; } } | namespace_or_type_expr pointer_stars { $$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2); } | builtin_type_expression ; void_invalid : VOID { Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); } ; builtin_type_expression : builtin_types opt_nullable { if ($2 != null) $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); } | builtin_types pointer_stars { $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); } | VOID pointer_stars { $$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); } ; type_list : base_type_name { var types = new List (2); types.Add ((FullNamedExpression) $1); $$ = types; } | type_list COMMA base_type_name { var types = (List) $1; types.Add ((FullNamedExpression) $3); $$ = types; } ; base_type_name : type { if ($1 is ComposedCast) { report.Error (1521, GetLocation ($1), "Invalid base type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); } $$ = $1; } ; /* * replaces all the productions for isolating the various * simple types, but we need this to reuse it easily in variable_type */ builtin_types : OBJECT { $$ = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation ($1)); } | STRING { $$ = new TypeExpression (compiler.BuiltinTypes.String, GetLocation ($1)); } | BOOL { $$ = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation ($1)); } | DECIMAL { $$ = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation ($1)); } | FLOAT { $$ = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation ($1)); } | DOUBLE { $$ = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation ($1)); } | integral_type ; integral_type : SBYTE { $$ = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation ($1)); } | BYTE { $$ = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation ($1)); } | SHORT { $$ = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation ($1)); } | USHORT { $$ = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation ($1)); } | INT { $$ = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation ($1)); } | UINT { $$ = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation ($1)); } | LONG { $$ = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation ($1)); } | ULONG { $$ = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation ($1)); } | CHAR { $$ = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation ($1)); } ; // // Expressions, section 7.5 // primary_expression : type_name_expression | literal | array_creation_expression | parenthesized_expression | default_value_expression | invocation_expression | element_access | this_access | base_access | post_increment_expression | post_decrement_expression | object_or_delegate_creation_expression | anonymous_type_expression | typeof_expression | sizeof_expression | checked_expression | unchecked_expression | pointer_member_access | anonymous_method_expression | undocumented_expressions | interpolated_string ; type_name_expression : simple_name_expr | IDENTIFIER GENERATE_COMPLETION { var lt = (LocatedToken) $1; $$ = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); } | member_access ; literal : boolean_literal | LITERAL | NULL { $$ = new NullLiteral (GetLocation ($1)); } ; boolean_literal : TRUE { $$ = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation ($1)); } | FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); } ; interpolated_string : INTERPOLATED_STRING interpolations INTERPOLATED_STRING_END { if (lang_version < LanguageVersion.V_6) FeatureIsNotAvailable (GetLocation ($1), "interpolated strings"); $$ = new InterpolatedString ((StringLiteral) $1, (List) $2, (StringLiteral) $3); } | INTERPOLATED_STRING_END { if (lang_version < LanguageVersion.V_6) FeatureIsNotAvailable (GetLocation ($1), "interpolated strings"); $$ = new InterpolatedString ((StringLiteral) $1, null, null); } ; interpolations : interpolation { var list = new List (); list.Add ((InterpolatedStringInsert) $1); $$ = list; } | interpolations INTERPOLATED_STRING interpolation { var list = (List) $1; list.Add ((StringLiteral) $2); list.Add ((InterpolatedStringInsert) $3); $$ = list; } ; interpolation : expression { $$ = new InterpolatedStringInsert ((Expression) $1); } | expression COMMA expression { $$ = new InterpolatedStringInsert ((Expression) $1) { Alignment = (Expression)$3 }; } | expression COLON { lexer.parsing_interpolation_format = true; } LITERAL { lexer.parsing_interpolation_format = false; $$ = new InterpolatedStringInsert ((Expression) $1) { Format = (string)$4 }; } | expression COMMA expression COLON { lexer.parsing_interpolation_format = true; } LITERAL { lexer.parsing_interpolation_format = false; $$ = new InterpolatedStringInsert ((Expression) $1) { Alignment = (Expression)$3, Format = (string) $6 }; } ; // // Here is the trick, tokenizer may think that parens is a special but // parser is interested in open parens only, so we merge them. // Consider: if (a)foo (); // open_parens_any : OPEN_PARENS | OPEN_PARENS_CAST ; // // Use this production to accept closing parenthesis or // performing completion // close_parens : CLOSE_PARENS | COMPLETE_COMPLETION ; parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS { $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } | OPEN_PARENS expression COMPLETE_COMPLETION { $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); } ; member_access : primary_expression DOT identifier_inside_body opt_type_argument_list { var lt = (LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | primary_expression DOT identifier_inside_body generic_dimension { var lt = (LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | primary_expression INTERR_OPERATOR DOT identifier_inside_body opt_type_argument_list { if (lang_version < LanguageVersion.V_6) FeatureIsNotAvailable (GetLocation ($2), "null propagating operator"); var lt = (LocatedToken) $4; $$ = new ConditionalMemberAccess ((Expression) $1, lt.Value, (TypeArguments) $5, lt.Location); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); } | builtin_types DOT identifier_inside_body opt_type_argument_list { var lt = (LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | BASE DOT identifier_inside_body opt_type_argument_list { var lt = (LocatedToken) $3; $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | AWAIT DOT identifier_inside_body opt_type_argument_list { var lt = (LocatedToken) $3; $$ = new MemberAccess (new SimpleName ("await", ((LocatedToken) $1).Location), lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | qualified_alias_member identifier_inside_body opt_type_argument_list { var lt1 = (LocatedToken) $1; var lt2 = (LocatedToken) $2; $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); lbag.AddLocation ($$, GetLocation ($2)); } | qualified_alias_member identifier_inside_body generic_dimension { var lt1 = (LocatedToken) $1; var lt2 = (LocatedToken) $2; $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) $3, lt1.Location); lbag.AddLocation ($$, GetLocation ($2)); } | primary_expression DOT GENERATE_COMPLETION { $$ = new CompletionMemberAccess ((Expression) $1, null,GetLocation ($3)); } | primary_expression DOT IDENTIFIER GENERATE_COMPLETION { var lt = (LocatedToken) $3; $$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); } | builtin_types DOT GENERATE_COMPLETION { $$ = new CompletionMemberAccess ((Expression) $1, null, lexer.Location); } | builtin_types DOT IDENTIFIER GENERATE_COMPLETION { var lt = (LocatedToken) $3; $$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); } ; invocation_expression : primary_expression open_parens_any opt_argument_list close_parens { $$ = new Invocation ((Expression) $1, (Arguments) $3); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | primary_expression open_parens_any argument_list error { Error_SyntaxError (yyToken); $$ = new Invocation ((Expression) $1, (Arguments) $3); lbag.AddLocation ($$, GetLocation ($2)); } | primary_expression open_parens_any error { Error_SyntaxError (yyToken); $$ = new Invocation ((Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; opt_object_or_collection_initializer : /* empty */ { $$ = null; } | object_or_collection_initializer ; object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion { if ($2 == null) { $$ = new CollectionOrObjectInitializers (GetLocation ($1)); } else { $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); } lbag.AddLocation ($$, GetLocation ($3)); } | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE { $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3), GetLocation ($4)); } ; opt_member_initializer_list : /* empty */ { $$ = null; } | member_initializer_list { $$ = $1; } ; member_initializer_list : member_initializer { var a = new List (); a.Add ((Expression) $1); $$ = a; } | member_initializer_list COMMA member_initializer { var a = (List)$1; a.Add ((Expression) $3); $$ = a; } | member_initializer_list error { Error_SyntaxError (yyToken); $$ = $1; } ; member_initializer : IDENTIFIER ASSIGN initializer_value { var lt = (LocatedToken) $1; $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | AWAIT ASSIGN initializer_value { var lt = (LocatedToken) Error_AwaitAsIdentifier ($1); $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | GENERATE_COMPLETION { $$ = new CompletionElementInitializer (null, GetLocation ($1)); } | non_assignment_expression opt_COMPLETE_COMPLETION { CompletionSimpleName csn = $1 as CompletionSimpleName; if (csn == null) $$ = new CollectionElementInitializer ((Expression)$1); else $$ = new CompletionElementInitializer (csn.Prefix, csn.Location); } | OPEN_BRACE expression_list CLOSE_BRACE { if ($2 == null) $$ = new CollectionElementInitializer (GetLocation ($1)); else $$ = new CollectionElementInitializer ((List)$2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } | OPEN_BRACKET_EXPR argument_list CLOSE_BRACKET ASSIGN initializer_value { if (lang_version < LanguageVersion.V_6) FeatureIsNotAvailable (GetLocation ($1), "dictionary initializer"); $$ = new DictionaryElementInitializer ((Arguments)$2, (Expression) $5, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3), GetLocation ($4)); } | OPEN_BRACE CLOSE_BRACE { report.Error (1920, GetLocation ($1), "An element initializer cannot be empty"); $$ = new CollectionElementInitializer (GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2)); } ; initializer_value : expression | object_or_collection_initializer ; opt_argument_list : /* empty */ { $$ = null; } | argument_list ; argument_list : argument_or_named_argument { Arguments list = new Arguments (4); list.Add ((Argument) $1); $$ = list; } | argument_list COMMA argument { Arguments list = (Arguments) $1; if (list [list.Count - 1] is NamedArgument) Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); list.Add ((Argument) $3); $$ = list; } | argument_list COMMA named_argument { Arguments list = (Arguments) $1; NamedArgument a = (NamedArgument) $3; for (int i = 0; i < list.Count; ++i) { NamedArgument na = list [i] as NamedArgument; if (na != null && na.Name == a.Name) report.Error (1740, na.Location, "Named argument `{0}' specified multiple times", na.Name); } list.Add (a); $$ = list; } | argument_list COMMA error { if (lexer.putback_char == -1) lexer.putback (')'); // TODO: Wrong but what can I do Error_SyntaxError (yyToken); $$ = $1; } | COMMA error { report.Error (839, GetLocation ($1), "An argument is missing"); $$ = null; } ; argument : expression { $$ = new Argument ((Expression) $1); } | non_simple_argument ; argument_or_named_argument : argument | named_argument ; non_simple_argument : REF variable_reference { $$ = new Argument ((Expression) $2, Argument.AType.Ref); lbag.AddLocation ($$, GetLocation ($1)); } | REF declaration_expression { $$ = new Argument ((Expression) $2, Argument.AType.Ref); } | OUT variable_reference { $$ = new Argument ((Expression) $2, Argument.AType.Out); lbag.AddLocation ($$, GetLocation ($1)); } | OUT declaration_expression { $$ = new Argument ((Expression) $2, Argument.AType.Out); } | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS { $$ = new Argument (new Arglist ((Arguments) $3, GetLocation ($1))); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | ARGLIST OPEN_PARENS CLOSE_PARENS { $$ = new Argument (new Arglist (GetLocation ($1))); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); } ; declaration_expression : OPEN_PARENS declaration_expression CLOSE_PARENS { $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } /* | CHECKED open_parens_any declaration_expression CLOSE_PARENS { $$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | UNCHECKED open_parens_any declaration_expression CLOSE_PARENS { $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } */ | variable_type identifier_inside_body { if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($1), "declaration expression"); var lt = (LocatedToken) $2; var lv = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (lv); $$ = new DeclarationExpression ((FullNamedExpression) $1, lv); } | variable_type identifier_inside_body ASSIGN expression { if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($1), "declaration expression"); var lt = (LocatedToken) $2; var lv = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (lv); $$ = new DeclarationExpression ((FullNamedExpression) $1, lv) { Initializer = (Expression) $4 }; } ; variable_reference : expression ; element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET { $$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($4)); } | primary_expression INTERR_OPERATOR OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET { if (lang_version < LanguageVersion.V_6) FeatureIsNotAvailable (GetLocation ($2), "null propagating operator"); $$ = new ElementAccess ((Expression) $1, (Arguments) $4, GetLocation ($3)) { ConditionalAccess = true }; lbag.AddLocation ($$, GetLocation ($2), GetLocation ($5)); } | primary_expression OPEN_BRACKET_EXPR expression_list_arguments error { Error_SyntaxError (yyToken); $$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); } | primary_expression OPEN_BRACKET_EXPR error { Error_SyntaxError (yyToken); $$ = new ElementAccess ((Expression) $1, null, GetLocation ($2)); } ; expression_list : expression_or_error { var list = new List (4); list.Add ((Expression) $1); $$ = list; } | expression_list COMMA expression_or_error { var list = (List) $1; list.Add ((Expression) $3); $$ = list; } ; expression_list_arguments : expression_list_argument { Arguments args = new Arguments (4); args.Add ((Argument) $1); $$ = args; } | expression_list_arguments COMMA expression_list_argument { Arguments args = (Arguments) $1; if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); $$ = args; } ; expression_list_argument : expression { $$ = new Argument ((Expression) $1); } | named_argument ; this_access : THIS { $$ = new This (GetLocation ($1)); } ; base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET { $$ = new ElementAccess (new BaseThis (GetLocation ($1)), (Arguments) $3, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($4)); } | BASE OPEN_BRACKET error { Error_SyntaxError (yyToken); $$ = new ElementAccess (null, null, GetLocation ($2)); } ; post_increment_expression : primary_expression OP_INC { $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) $1, GetLocation ($2)); } ; post_decrement_expression : primary_expression OP_DEC { $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) $1, GetLocation ($2)); } ; object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer { if ($6 != null) { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "object initializers"); $$ = new NewInitialize ((FullNamedExpression) $2, (Arguments) $4, (CollectionOrObjectInitializers) $6, GetLocation ($1)); } else { $$ = new New ((FullNamedExpression) $2, (Arguments) $4, GetLocation ($1)); } lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); } | NEW new_expr_type object_or_collection_initializer { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "collection initializers"); $$ = new NewInitialize ((FullNamedExpression) $2, null, (CollectionOrObjectInitializers) $3, GetLocation ($1)); } ; array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer { $$ = new ArrayCreation ((FullNamedExpression) $2, (List) $4, new ComposedTypeSpecifier (((List) $4).Count, GetLocation ($3)) { Next = (ComposedTypeSpecifier) $6 }, (ArrayInitializer) $7, GetLocation ($1)) { NoEmptyInterpolation = true }; lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); } | NEW new_expr_type rank_specifiers opt_array_initializer { if ($4 == null) report.Error (1586, GetLocation ($1), "Array creation must have array size or array initializer"); $$ = new ArrayCreation ((FullNamedExpression) $2, (ComposedTypeSpecifier) $3, (ArrayInitializer) $4, GetLocation ($1)) { NoEmptyInterpolation = true }; } | NEW rank_specifier array_initializer { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "implicitly typed arrays"); $$ = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) $2, (ArrayInitializer) $3, GetLocation ($1)); } | NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET { report.Error (178, GetLocation ($6), "Invalid rank specifier, expecting `,' or `]'"); $$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); } | NEW new_expr_type error { Error_SyntaxError (yyToken); // It can be any of new expression, create the most common one $$ = new New ((FullNamedExpression) $2, null, GetLocation ($1)); } ; new_expr_type : { ++lexer.parsing_type; } simple_type { --lexer.parsing_type; $$ = $2; } ; anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "anonymous types"); $$ = new NewAnonymousType ((List) $3, current_container, GetLocation ($1)); // TODO: lbag comma location lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | NEW OPEN_BRACE GENERATE_COMPLETION { $$ = new EmptyCompletion (); } ; anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt | anonymous_type_parameters COMMA ; anonymous_type_parameters_opt : { $$ = null; } | anonymous_type_parameters ; anonymous_type_parameters : anonymous_type_parameter { var a = new List (4); a.Add ((AnonymousTypeParameter) $1); $$ = a; } | anonymous_type_parameters COMMA anonymous_type_parameter { var a = (List) $1; a.Add ((AnonymousTypeParameter) $3); $$ = a; } | COMPLETE_COMPLETION { $$ = new EmptyCompletion (); } | anonymous_type_parameter COMPLETE_COMPLETION { $$ = $1; } ; anonymous_type_parameter : identifier_inside_body ASSIGN variable_initializer { var lt = (LocatedToken)$1; $$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } | identifier_inside_body { var lt = (LocatedToken)$1; $$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), lt.Value, lt.Location); } | member_access { MemberAccess ma = (MemberAccess) $1; $$ = new AnonymousTypeParameter (ma, ma.Name, ma.Location); } | error { report.Error (746, lexer.Location, "Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); $$ = null; } ; opt_rank_specifier : /* empty */ | rank_specifiers ; rank_specifiers : rank_specifier | rank_specifier rank_specifiers { ((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; $$ = $1; } ; rank_specifier : OPEN_BRACKET CLOSE_BRACKET { $$ = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2)); } | OPEN_BRACKET dim_separators CLOSE_BRACKET { $$ = ComposedTypeSpecifier.CreateArrayDimension ((int)$2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } ; dim_separators : COMMA { $$ = 2; } | dim_separators COMMA { $$ = ((int) $1) + 1; } ; opt_array_initializer : /* empty */ { $$ = null; } | array_initializer { $$ = $1; } ; array_initializer : OPEN_BRACE CLOSE_BRACE { var ai = new ArrayInitializer (0, GetLocation ($1)); ai.VariableDeclaration = current_variable; lbag.AddLocation (ai, GetLocation ($2)); $$ = ai; } | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE { var ai = new ArrayInitializer ((List) $2, GetLocation ($1)); ai.VariableDeclaration = current_variable; if ($3 != null) { lbag.AddLocation (ai, GetLocation ($3), GetLocation ($4)); } else { lbag.AddLocation (ai, GetLocation ($4)); } $$ = ai; } ; variable_initializer_list : variable_initializer { var list = new List (4); list.Add ((Expression) $1); $$ = list; } | variable_initializer_list COMMA variable_initializer { var list = (List) $1; list.Add ((Expression) $3); $$ = list; } ; typeof_expression : TYPEOF open_parens_any typeof_type_expression CLOSE_PARENS { $$ = new TypeOf ((FullNamedExpression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } ; typeof_type_expression : type_and_void | error { Error_TypeExpected (lexer.Location); $$ = null; } ; generic_dimension : GENERIC_DIMENSION { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "generics"); $$ = $1; } ; qualified_alias_member : IDENTIFIER DOUBLE_COLON { var lt = (LocatedToken) $1; if (lang_version == LanguageVersion.ISO_1) FeatureIsNotAvailable (lt.Location, "namespace alias qualifier"); $$ = lt; } ; sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS { $$ = new SizeOf ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | SIZEOF open_parens_any type error { Error_SyntaxError (yyToken); $$ = new SizeOf ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2)); } ; checked_expression : CHECKED open_parens_any expression CLOSE_PARENS { $$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | CHECKED error { Error_SyntaxError (yyToken); $$ = new CheckedExpr (null, GetLocation ($1)); } ; unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS { $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | UNCHECKED error { Error_SyntaxError (yyToken); $$ = new UnCheckedExpr (null, GetLocation ($1)); } ; pointer_member_access : primary_expression OP_PTR IDENTIFIER opt_type_argument_list { var lt = (LocatedToken) $3; $$ = new MemberAccess (new Indirection ((Expression) $1, GetLocation ($2)), lt.Value, (TypeArguments) $4, lt.Location); } ; anonymous_method_expression : DELEGATE opt_anonymous_method_signature { start_anonymous (false, (ParametersCompiled) $2, false, GetLocation ($1)); } block { $$ = end_anonymous ((ParametersBlock) $4); } | ASYNC DELEGATE opt_anonymous_method_signature { start_anonymous (false, (ParametersCompiled) $3, true, GetLocation ($1)); } block { $$ = end_anonymous ((ParametersBlock) $5); } ; opt_anonymous_method_signature : { $$ = ParametersCompiled.Undefined; } | anonymous_method_signature ; anonymous_method_signature : OPEN_PARENS { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } opt_formal_parameter_list CLOSE_PARENS { valid_param_mod = 0; $$ = $3; } ; default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "default value expression"); $$ = new DefaultValueExpression ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } ; unary_expression : primary_expression | BANG prefixed_unary_expression { $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, GetLocation ($1)); } | TILDE prefixed_unary_expression { $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, GetLocation ($1)); } | OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression { $$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } | AWAIT prefixed_unary_expression { if (!async_block) { if (current_anonymous_method is LambdaExpression) { report.Error (4034, GetLocation ($1), "The `await' operator can only be used when its containing lambda expression is marked with the `async' modifier"); } else if (current_anonymous_method != null) { report.Error (4035, GetLocation ($1), "The `await' operator can only be used when its containing anonymous method is marked with the `async' modifier"); } else if (interactive_async != null) { current_block.Explicit.RegisterAsyncAwait (); interactive_async = true; } else { report.Error (4033, GetLocation ($1), "The `await' operator can only be used when its containing method is marked with the `async' modifier"); } } else { current_block.Explicit.RegisterAsyncAwait (); } $$ = new Await ((Expression) $2, GetLocation ($1)); } | BANG error { Error_SyntaxError (yyToken); $$ = new Unary (Unary.Operator.LogicalNot, null, GetLocation ($1)); } | TILDE error { Error_SyntaxError (yyToken); $$ = new Unary (Unary.Operator.OnesComplement, null, GetLocation ($1)); } | OPEN_PARENS_CAST type CLOSE_PARENS error { Error_SyntaxError (yyToken); $$ = new Cast ((FullNamedExpression) $2, null, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } | AWAIT error { Error_SyntaxError (yyToken); $$ = new Await (null, GetLocation ($1)); } ; // // The idea to split this out is from Rhys' grammar // to solve the problem with casts. // prefixed_unary_expression : unary_expression | PLUS prefixed_unary_expression { $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, GetLocation ($1)); } | MINUS prefixed_unary_expression { $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); } | OP_INC prefixed_unary_expression { $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) $2, GetLocation ($1)); } | OP_DEC prefixed_unary_expression { $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) $2, GetLocation ($1)); } | STAR prefixed_unary_expression { $$ = new Indirection ((Expression) $2, GetLocation ($1)); } | BITWISE_AND prefixed_unary_expression { $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, GetLocation ($1)); } | PLUS error { Error_SyntaxError (yyToken); $$ = new Unary (Unary.Operator.UnaryPlus, null, GetLocation ($1)); } | MINUS error { Error_SyntaxError (yyToken); $$ = new Unary (Unary.Operator.UnaryNegation, null, GetLocation ($1)); } | OP_INC error { Error_SyntaxError (yyToken); $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement, null, GetLocation ($1)); } | OP_DEC error { Error_SyntaxError (yyToken); $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement, null, GetLocation ($1)); } | STAR error { Error_SyntaxError (yyToken); $$ = new Indirection (null, GetLocation ($1)); } | BITWISE_AND error { Error_SyntaxError (yyToken); $$ = new Unary (Unary.Operator.AddressOf, null, GetLocation ($1)); } ; multiplicative_expression : prefixed_unary_expression | multiplicative_expression STAR prefixed_unary_expression { $$ = new Binary (Binary.Operator.Multiply, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | multiplicative_expression DIV prefixed_unary_expression { $$ = new Binary (Binary.Operator.Division, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | multiplicative_expression PERCENT prefixed_unary_expression { $$ = new Binary (Binary.Operator.Modulus, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | multiplicative_expression STAR error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Multiply, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | multiplicative_expression DIV error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Division, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | multiplicative_expression PERCENT error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Modulus, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; additive_expression : multiplicative_expression | additive_expression PLUS multiplicative_expression { $$ = new Binary (Binary.Operator.Addition, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | additive_expression MINUS multiplicative_expression { $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | additive_expression PLUS error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Addition, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | additive_expression MINUS error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | additive_expression AS type { $$ = new As ((Expression) $1, (Expression) $3, GetLocation ($2)); } | additive_expression IS pattern_type_expr opt_identifier { var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); if ($4 != null) { if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($4), "type pattern matching"); var lt = (LocatedToken) $4; is_expr.Variable = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (is_expr.Variable); } $$ = is_expr; } | additive_expression IS pattern_expr { var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($2), "pattern matching"); $$ = is_expr; } | additive_expression AS error { Error_SyntaxError (yyToken); $$ = new As ((Expression) $1, null, GetLocation ($2)); } | additive_expression IS error { Error_SyntaxError (yyToken); $$ = new Is ((Expression) $1, null, GetLocation ($2)); } | AWAIT IS type { var lt = (LocatedToken) $1; $$ = new Is (new SimpleName (lt.Value, lt.Location), (Expression) $3, GetLocation ($2)); } | AWAIT AS type { var lt = (LocatedToken) $1; $$ = new As (new SimpleName (lt.Value, lt.Location), (Expression) $3, GetLocation ($2)); } ; pattern_type_expr : variable_type ; pattern_expr : literal | PLUS prefixed_unary_expression { $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, GetLocation ($1)); } | MINUS prefixed_unary_expression { $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); } | sizeof_expression | default_value_expression | OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression { $$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } | STAR { $$ = new WildcardPattern (GetLocation ($1)); } | pattern_expr_invocation | pattern_property ; pattern_expr_invocation : type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS { $$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2)); } ; pattern_property : type_name_expression OPEN_BRACE pattern_property_list CLOSE_BRACE { $$ = new PropertyPattern ((ATypeNameExpression) $1, (List) $3, GetLocation ($2)); } ; pattern_property_list : pattern_property_entry { var list = new List (); list.Add ((PropertyPatternMember) $1); $$ = list; } | pattern_property_list COMMA pattern_property_entry { var list = (List) $1; list.Add ((PropertyPatternMember) $3); $$ = list; } ; pattern_property_entry : identifier_inside_body IS pattern { var lt = (LocatedToken) $1; $$ = new PropertyPatternMember (lt.Value, (Expression) $3, lt.Location); } ; pattern : pattern_expr | pattern_type_expr opt_identifier { if ($2 != null) { var lt = (LocatedToken) $2; var variable = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (variable); } } ; opt_pattern_list : /* empty */ { $$ = new Arguments (0); } | pattern_list ; pattern_list : pattern_argument { Arguments args = new Arguments (4); args.Add ((Argument) $1); $$ = args; } | pattern_list COMMA pattern_argument { Arguments args = (Arguments) $1; if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); $$ = args; } ; pattern_argument : pattern { $$ = new Argument ((Expression) $1); } | IDENTIFIER COLON pattern { var lt = (LocatedToken) $1; $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3); } ; shift_expression : additive_expression | shift_expression OP_SHIFT_LEFT additive_expression { $$ = new Binary (Binary.Operator.LeftShift, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | shift_expression OP_SHIFT_RIGHT additive_expression { $$ = new Binary (Binary.Operator.RightShift, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | shift_expression OP_SHIFT_LEFT error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.LeftShift, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | shift_expression OP_SHIFT_RIGHT error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.RightShift, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; relational_expression : shift_expression | relational_expression OP_LT shift_expression { $$ = new Binary (Binary.Operator.LessThan, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_GT shift_expression { $$ = new Binary (Binary.Operator.GreaterThan, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_LE shift_expression { $$ = new Binary (Binary.Operator.LessThanOrEqual, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_GE shift_expression { $$ = new Binary (Binary.Operator.GreaterThanOrEqual, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_LT error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.LessThan, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_GT error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.GreaterThan, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_LE error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.LessThanOrEqual, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | relational_expression OP_GE error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.GreaterThanOrEqual, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; equality_expression : relational_expression | equality_expression OP_EQ relational_expression { $$ = new Binary (Binary.Operator.Equality, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | equality_expression OP_NE relational_expression { $$ = new Binary (Binary.Operator.Inequality, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | equality_expression OP_EQ error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Equality, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } | equality_expression OP_NE error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.Inequality, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; and_expression : equality_expression | and_expression BITWISE_AND equality_expression { $$ = new Binary (Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | and_expression BITWISE_AND error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.BitwiseAnd, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; exclusive_or_expression : and_expression | exclusive_or_expression CARRET and_expression { $$ = new Binary (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | exclusive_or_expression CARRET error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.ExclusiveOr, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; inclusive_or_expression : exclusive_or_expression | inclusive_or_expression BITWISE_OR exclusive_or_expression { $$ = new Binary (Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | inclusive_or_expression BITWISE_OR error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.BitwiseOr, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; conditional_and_expression : inclusive_or_expression | conditional_and_expression OP_AND inclusive_or_expression { $$ = new Binary (Binary.Operator.LogicalAnd, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | conditional_and_expression OP_AND error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.LogicalAnd, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; conditional_or_expression : conditional_and_expression | conditional_or_expression OP_OR conditional_and_expression { $$ = new Binary (Binary.Operator.LogicalOr, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | conditional_or_expression OP_OR error { Error_SyntaxError (yyToken); $$ = new Binary (Binary.Operator.LogicalOr, (Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); } ; null_coalescing_expression : conditional_or_expression | conditional_or_expression OP_COALESCING null_coalescing_expression { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($2), "null coalescing operator"); $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } ; conditional_expression : null_coalescing_expression | null_coalescing_expression INTERR expression COLON expression { $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($4)); } | null_coalescing_expression INTERR expression error { Error_SyntaxError (yyToken); $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); } | null_coalescing_expression INTERR expression COLON error { Error_SyntaxError (yyToken); $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($4)); } | null_coalescing_expression INTERR expression COLON CLOSE_BRACE { Error_SyntaxError (Token.CLOSE_BRACE); $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($4)); lexer.putback ('}'); } ; assignment_expression : prefixed_unary_expression ASSIGN expression { $$ = new SimpleAssign ((Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_MULT_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.Multiply, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_DIV_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.Division, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_MOD_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.Modulus, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_ADD_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.Addition, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_SUB_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.LeftShift, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.RightShift, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_AND_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_OR_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } | prefixed_unary_expression OP_XOR_ASSIGN expression { $$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } ; lambda_parameter_list : lambda_parameter { var pars = new List (4); pars.Add ((Parameter) $1); $$ = pars; } | lambda_parameter_list COMMA lambda_parameter { var pars = (List) $1; Parameter p = (Parameter)$3; if (pars[0].GetType () != p.GetType ()) { report.Error (748, p.Location, "All lambda parameters must be typed either explicitly or implicitly"); } pars.Add (p); $$ = pars; } ; lambda_parameter : parameter_modifier parameter_type identifier_inside_body { var lt = (LocatedToken) $3; $$ = new Parameter ((FullNamedExpression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location); } | parameter_type identifier_inside_body { var lt = (LocatedToken) $2; $$ = new Parameter ((FullNamedExpression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location); } | IDENTIFIER { var lt = (LocatedToken) $1; $$ = new ImplicitLambdaParameter (lt.Value, lt.Location); } | AWAIT { var lt = (LocatedToken) Error_AwaitAsIdentifier ($1); $$ = new ImplicitLambdaParameter (lt.Value, lt.Location); } ; opt_lambda_parameter_list : /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } | lambda_parameter_list { var pars_list = (List) $1; $$ = new ParametersCompiled (pars_list.ToArray ()); } ; lambda_expression_body : { start_block (Location.Null); } expression // All expressions must handle error or current block won't be restored and breaking ast completely { Block b = end_block (Location.Null); b.IsCompilerGenerated = true; b.AddStatement (new ContextualReturn ((Expression) $2)); $$ = b; } | block | error { // Handles only cases like foo = x.FirstOrDefault (l => ); // where we must restore current_variable Block b = end_block (Location.Null); b.IsCompilerGenerated = true; Error_SyntaxError (yyToken); $$ = null; } ; expression_or_error : expression | error { Error_SyntaxError (yyToken); $$ = null; } ; lambda_expression : IDENTIFIER ARROW { var lt = (LocatedToken) $1; Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); start_anonymous (true, new ParametersCompiled (p), false, lt.Location); } lambda_expression_body { $$ = end_anonymous ((ParametersBlock) $4); lbag.AddLocation ($$, GetLocation ($2)); } | AWAIT ARROW { var lt = (LocatedToken) Error_AwaitAsIdentifier ($1); Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); start_anonymous (true, new ParametersCompiled (p), false, lt.Location); } lambda_expression_body { $$ = end_anonymous ((ParametersBlock) $4); lbag.AddLocation ($$, GetLocation ($2)); } | ASYNC identifier_inside_body ARROW { var lt = (LocatedToken) $2; Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); start_anonymous (true, new ParametersCompiled (p), true, lt.Location); } lambda_expression_body { $$ = end_anonymous ((ParametersBlock) $5); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } | OPEN_PARENS_LAMBDA { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } opt_lambda_parameter_list CLOSE_PARENS ARROW { valid_param_mod = 0; start_anonymous (true, (ParametersCompiled) $3, false, GetLocation ($1)); } lambda_expression_body { $$ = end_anonymous ((ParametersBlock) $7); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($4), GetLocation ($5)); } | ASYNC OPEN_PARENS_LAMBDA { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } opt_lambda_parameter_list CLOSE_PARENS ARROW { valid_param_mod = 0; start_anonymous (true, (ParametersCompiled) $4, true, GetLocation ($1)); } lambda_expression_body { $$ = end_anonymous ((ParametersBlock) $8); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($5), GetLocation ($6)); } ; expression : assignment_expression | non_assignment_expression ; non_assignment_expression : conditional_expression | lambda_expression | query_expression | ARGLIST { $$ = new ArglistAccess (GetLocation ($1)); } ; undocumented_expressions : REFVALUE OPEN_PARENS non_assignment_expression COMMA type CLOSE_PARENS { $$ = new RefValueExpr ((Expression) $3, (FullNamedExpression) $5, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); } | REFTYPE open_parens_any expression CLOSE_PARENS { $$ = new RefTypeExpr ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } | MAKEREF open_parens_any expression CLOSE_PARENS { $$ = new MakeRefExpr ((Expression) $3, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); } ; constant_expression : expression ; boolean_expression : expression { $$ = new BooleanExpression ((Expression) $1); } ; opt_primary_parameters : /* empty */ { $$ = null; } | primary_parameters ; primary_parameters : OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { $$ = $2; // Cannot use opt_formal_parameter_list because it can be shared instance for empty parameters lbag.AppendToMember (current_container, GetLocation ($1), GetLocation ($3)); if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($1), "primary constructor"); } ; opt_primary_parameters_with_class_base : /* empty */ { $$ = null; } | class_base { $$ = null; } | primary_parameters { $$ = $1; } | primary_parameters class_base { $$ = $1; } | primary_parameters class_base OPEN_PARENS { ++lexer.parsing_block; current_type.PrimaryConstructorBaseArgumentsStart = GetLocation ($3); } opt_argument_list CLOSE_PARENS { lbag.AppendToMember (current_container, GetLocation ($6)); current_type.PrimaryConstructorBaseArguments = (Arguments) $5; --lexer.parsing_block; $$ = $1; } ; // // 10 classes // class_declaration : opt_attributes opt_modifiers opt_partial CLASS { } type_declaration_name { lexer.ConstraintsParsing = true; Class c = new Class (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1); if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (c.Location, "static classes"); } push_current_container (c, $3); valid_param_mod = ParameterModifierType.PrimaryConstructor; } opt_primary_parameters_with_class_base opt_type_parameter_constraints_clauses { valid_param_mod = 0; lexer.ConstraintsParsing = false; if ($8 != null) current_type.PrimaryConstructorParameters = (ParametersCompiled) $8; if ($9 != null) current_container.SetConstraints ((List) $9); lbag.AddMember (current_container, mod_locations, GetLocation ($4)); if (doc_support) { current_container.PartialContainer.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } lexer.parsing_modifiers = true; } OPEN_BRACE opt_class_member_declarations CLOSE_BRACE { --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } opt_semicolon { if ($15 == null) { lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13)); } else { lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13), GetLocation ($15)); } $$ = pop_current_class (); } ; opt_partial : /* empty */ { $$ = null; } | PARTIAL { $$ = $1; } // location ; opt_modifiers : /* empty */ { mod_locations = null; $$ = ModifierNone; lexer.parsing_modifiers = false; } | modifiers { lexer.parsing_modifiers = false; } ; modifiers : modifier | modifiers modifier { var m1 = (Modifiers) $1; var m2 = (Modifiers) $2; if ((m1 & m2) != 0) { report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && ((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, "More than one protection modifier specified"); } $$ = m1 | m2; } ; modifier : NEW { $$ = Modifiers.NEW; StoreModifierLocation ($$, GetLocation ($1)); if (current_container.Kind == MemberKind.Namespace) report.Error (1530, GetLocation ($1), "Keyword `new' is not allowed on namespace elements"); } | PUBLIC { $$ = Modifiers.PUBLIC; StoreModifierLocation ($$, GetLocation ($1)); } | PROTECTED { $$ = Modifiers.PROTECTED; StoreModifierLocation ($$, GetLocation ($1)); } | INTERNAL { $$ = Modifiers.INTERNAL; StoreModifierLocation ($$, GetLocation ($1)); } | PRIVATE { $$ = Modifiers.PRIVATE; StoreModifierLocation ($$, GetLocation ($1)); } | ABSTRACT { $$ = Modifiers.ABSTRACT; StoreModifierLocation ($$, GetLocation ($1)); } | SEALED { $$ = Modifiers.SEALED; StoreModifierLocation ($$, GetLocation ($1)); } | STATIC { $$ = Modifiers.STATIC; StoreModifierLocation ($$, GetLocation ($1)); } | READONLY { $$ = Modifiers.READONLY; StoreModifierLocation ($$, GetLocation ($1)); } | VIRTUAL { $$ = Modifiers.VIRTUAL; StoreModifierLocation ($$, GetLocation ($1)); } | OVERRIDE { $$ = Modifiers.OVERRIDE; StoreModifierLocation ($$, GetLocation ($1)); } | EXTERN { $$ = Modifiers.EXTERN; StoreModifierLocation ($$, GetLocation ($1)); } | VOLATILE { $$ = Modifiers.VOLATILE; StoreModifierLocation ($$, GetLocation ($1)); } | UNSAFE { $$ = Modifiers.UNSAFE; StoreModifierLocation ($$, GetLocation ($1)); if (!settings.Unsafe) Error_UnsafeCodeNotAllowed (GetLocation ($1)); } | ASYNC { $$ = Modifiers.ASYNC; StoreModifierLocation ($$, GetLocation ($1)); } ; opt_class_base : /* empty */ | class_base ; class_base : COLON type_list { current_type.SetBaseTypes ((List) $2); } | COLON type_list error { Error_SyntaxError (yyToken); current_type.SetBaseTypes ((List) $2); } ; opt_type_parameter_constraints_clauses : /* empty */ | type_parameter_constraints_clauses { $$ = $1; } ; type_parameter_constraints_clauses : type_parameter_constraints_clause { var constraints = new List (1); constraints.Add ((Constraints) $1); $$ = constraints; } | type_parameter_constraints_clauses type_parameter_constraints_clause { var constraints = (List) $1; Constraints new_constraint = (Constraints)$2; foreach (Constraints c in constraints) { if (new_constraint.TypeParameter.Value == c.TypeParameter.Value) { report.Error (409, new_constraint.Location, "A constraint clause has already been specified for type parameter `{0}'", new_constraint.TypeParameter.Value); } } constraints.Add (new_constraint); $$ = constraints; } ; type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints { var lt = (LocatedToken) $2; $$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) $4, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } | WHERE IDENTIFIER error { Error_SyntaxError (yyToken); var lt = (LocatedToken) $2; $$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), null, GetLocation ($1)); } ; type_parameter_constraints : type_parameter_constraint { var constraints = new List (1); constraints.Add ((FullNamedExpression) $1); $$ = constraints; } | type_parameter_constraints COMMA type_parameter_constraint { var constraints = (List) $1; var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; if (prev != null && (prev.Constraint & SpecialConstraint.Constructor) != 0) { report.Error (401, GetLocation ($2), "The `new()' constraint must be the last constraint specified"); } prev = $3 as SpecialContraintExpr; if (prev != null) { if ((prev.Constraint & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) { report.Error (449, prev.Location, "The `class' or `struct' constraint must be the first constraint specified"); } else { prev = constraints [0] as SpecialContraintExpr; if (prev != null && (prev.Constraint & SpecialConstraint.Struct) != 0) { report.Error (451, GetLocation ($3), "The `new()' constraint cannot be used with the `struct' constraint"); } } } constraints.Add ((FullNamedExpression) $3); $$ = constraints; } ; type_parameter_constraint : type { if ($1 is ComposedCast) report.Error (706, GetLocation ($1), "Invalid constraint type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); $$ = $1; } | NEW OPEN_PARENS CLOSE_PARENS { $$ = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); } | CLASS { $$ = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation ($1)); } | STRUCT { $$ = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation ($1)); } ; opt_type_parameter_variance : /* empty */ { $$ = null; } | type_parameter_variance { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (lexer.Location, "generic type variance"); $$ = $1; } ; type_parameter_variance : OUT { $$ = new VarianceDecl (Variance.Covariant, GetLocation ($1)); } | IN { $$ = new VarianceDecl (Variance.Contravariant, GetLocation ($1)); } ; // // Statements (8.2) // // // A block is "contained" on the following places: // method_body // property_declaration as part of the accessor body (get/set) // operator_declaration // constructor_declaration // destructor_declaration // event_declaration as part of add_accessor_declaration or remove_accessor_declaration // block : OPEN_BRACE { ++lexer.parsing_block; start_block (GetLocation ($1)); } opt_statement_list block_end { $$ = $4; } ; block_end : CLOSE_BRACE { --lexer.parsing_block; $$ = end_block (GetLocation ($1)); } | COMPLETE_COMPLETION { --lexer.parsing_block; $$ = end_block (lexer.Location); } ; block_prepared : OPEN_BRACE { ++lexer.parsing_block; current_block.StartLocation = GetLocation ($1); } opt_statement_list CLOSE_BRACE { --lexer.parsing_block; $$ = end_block (GetLocation ($4)); } ; opt_statement_list : /* empty */ | statement_list ; statement_list : statement | statement_list statement ; statement : block_variable_declaration { current_block.AddStatement ((Statement) $1); } | valid_declaration_statement { current_block.AddStatement ((Statement) $1); } | labeled_statement | error { Error_SyntaxError (yyToken); $$ = null; } ; // // The interactive_statement and its derivatives are only // used to provide a special version of `expression_statement' // that has a side effect of assigning the expression to // $retval // interactive_statement_list : interactive_statement | interactive_statement_list interactive_statement ; interactive_statement : block_variable_declaration { current_block.AddStatement ((Statement) $1); } | interactive_valid_declaration_statement { current_block.AddStatement ((Statement) $1); } | labeled_statement ; valid_declaration_statement : block | empty_statement | expression_statement | selection_statement | iteration_statement | jump_statement | try_statement | checked_statement | unchecked_statement | lock_statement | using_statement | unsafe_statement | fixed_statement ; interactive_valid_declaration_statement : block | empty_statement | interactive_expression_statement | selection_statement | iteration_statement | jump_statement | try_statement | checked_statement | unchecked_statement | lock_statement | using_statement | unsafe_statement | fixed_statement ; embedded_statement : valid_declaration_statement | block_variable_declaration { report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); $$ = null; } | labeled_statement { report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); $$ = null; } | error { Error_SyntaxError (yyToken); $$ = new EmptyStatement (GetLocation ($1)); } ; empty_statement : SEMICOLON { // Uses lexer.Location because semicolon location is not kept in quick mode $$ = new EmptyStatement (lexer.Location); } ; labeled_statement : identifier_inside_body COLON { var lt = (LocatedToken) $1; LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); lbag.AddLocation (labeled, GetLocation ($2)); current_block.AddLabel (labeled); current_block.AddStatement (labeled); } statement ; variable_type : variable_type_simple | variable_type_simple rank_specifiers { if ($1 is VarExpr) $1 = new SimpleName ("var", ((VarExpr) $1).Location); $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); } ; /* * The following is from Rhys' grammar: * > Types in local variable declarations must be recognized as * > expressions to prevent reduce/reduce errors in the grammar. * > The expressions are converted into types during semantic analysis. */ variable_type_simple : type_name_expression opt_nullable { // Ok, the above "primary_expression" is there to get rid of // both reduce/reduce and shift/reduces in the grammar, it should // really just be "type_name". If you use type_name, a reduce/reduce // creeps up. If you use namespace_or_type_name (which is all we need // really) two shift/reduces appear. // // So the super-trick is that primary_expression // can only be either a SimpleName or a MemberAccess. // The MemberAccess case arises when you have a fully qualified type-name like : // Foo.Bar.Blah i; // SimpleName is when you have // Blah i; var expr = (ATypeNameExpression) $1; if ($2 == null) { if (expr.Name == "var" && expr is SimpleName) $$ = new VarExpr (expr.Location); else $$ = $1; } else { $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); } } | type_name_expression pointer_stars { var expr = (ATypeNameExpression) $1; $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); } | builtin_type_expression | void_invalid ; pointer_stars : pointer_star | pointer_star pointer_stars { ((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; $$ = $1; } ; pointer_star : STAR { $$ = ComposedTypeSpecifier.CreatePointer (GetLocation ($1)); } ; identifier_inside_body : IDENTIFIER | AWAIT { $$ = Error_AwaitAsIdentifier ($1); } ; block_variable_declaration : variable_type identifier_inside_body { var lt = (LocatedToken) $2; var li = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (li); current_variable = new BlockVariable ((FullNamedExpression) $1, li); } opt_local_variable_initializer opt_variable_declarators SEMICOLON { $$ = current_variable; current_variable = null; if ($4 != null) lbag.AddLocation ($$, PopLocation (), GetLocation ($6)); else lbag.AddLocation ($$, GetLocation ($6)); } | CONST variable_type identifier_inside_body { var lt = (LocatedToken) $3; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); current_block.AddLocalName (li); current_variable = new BlockConstant ((FullNamedExpression) $2, li); } const_variable_initializer opt_const_declarators SEMICOLON { $$ = current_variable; current_variable = null; lbag.AddLocation ($$, GetLocation ($1), GetLocation ($7)); } ; opt_local_variable_initializer : /* empty */ | ASSIGN block_variable_initializer { current_variable.Initializer = (Expression) $2; PushLocation (GetLocation ($1)); $$ = current_variable; } | error { if (yyToken == Token.OPEN_BRACKET_EXPR) { report.Error (650, lexer.Location, "Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type"); } else { Error_SyntaxError (yyToken); } } ; opt_variable_declarators : /* empty */ | variable_declarators ; opt_using_or_fixed_variable_declarators : /* empty */ | variable_declarators { foreach (var d in current_variable.Declarators) { if (d.Initializer == null) Error_MissingInitializer (d.Variable.Location); } } ; variable_declarators : variable_declarator | variable_declarators variable_declarator ; variable_declarator : COMMA identifier_inside_body { var lt = (LocatedToken) $2; var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); var d = new BlockVariableDeclarator (li, null); current_variable.AddDeclarator (d); current_block.AddLocalName (li); lbag.AddLocation (d, GetLocation ($1)); } | COMMA identifier_inside_body ASSIGN block_variable_initializer { var lt = (LocatedToken) $2; var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); var d = new BlockVariableDeclarator (li, (Expression) $4); current_variable.AddDeclarator (d); current_block.AddLocalName (li); lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); } ; const_variable_initializer : /* empty */ { report.Error (145, lexer.Location, "A const field requires a value to be provided"); } | ASSIGN constant_initializer_expr { current_variable.Initializer = (Expression) $2; } ; opt_const_declarators : /* empty */ | const_declarators ; const_declarators : const_declarator | const_declarators const_declarator ; const_declarator : COMMA identifier_inside_body ASSIGN constant_initializer_expr { var lt = (LocatedToken) $2; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); var d = new BlockVariableDeclarator (li, (Expression) $4); current_variable.AddDeclarator (d); current_block.AddLocalName (li); lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); } ; block_variable_initializer : variable_initializer | STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET { $$ = new StackAlloc ((Expression) $2, (Expression) $4, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); } | STACKALLOC simple_type { report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type"); $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); } ; expression_statement : statement_expression SEMICOLON { $$ = $1; lbag.AddStatement ($$, GetLocation ($2)); } | statement_expression COMPLETE_COMPLETION { $$ = $1; } | statement_expression CLOSE_BRACE { $$ = $1; report.Error (1002, GetLocation ($2), "; expected"); lexer.putback ('}'); } ; interactive_expression_statement : interactive_statement_expression SEMICOLON { $$ = $1; } | interactive_statement_expression COMPLETE_COMPLETION { $$ = $1; } ; // // We have to do the wrapping here and not in the case above, // because statement_expression is used for example in for_statement // statement_expression : expression { ExpressionStatement s = $1 as ExpressionStatement; if (s == null) { var expr = $1 as Expression; $$ = new StatementErrorExpression (expr); } else { $$ = new StatementExpression (s); } } ; interactive_statement_expression : expression { Expression expr = (Expression) $1; $$ = new StatementExpression (new OptionalAssign (expr, lexer.Location)); } | error { Error_SyntaxError (yyToken); $$ = new EmptyStatement (GetLocation ($1)); } ; selection_statement : if_statement | switch_statement ; if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement { if ($5 is EmptyStatement) Warning_EmptyStatement (GetLocation ($5)); $$ = new If ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement { $$ = new If ((BooleanExpression) $3, (Statement) $5, (Statement) $7, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); if ($5 is EmptyStatement) Warning_EmptyStatement (GetLocation ($5)); if ($7 is EmptyStatement) Warning_EmptyStatement (GetLocation ($7)); } | IF open_parens_any boolean_expression error { Error_SyntaxError (yyToken); $$ = new If ((BooleanExpression) $3, null, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; switch_statement : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE { start_block (GetLocation ($5)); } opt_switch_sections CLOSE_BRACE { $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, GetLocation ($1)); end_block (GetLocation ($8)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | SWITCH open_parens_any expression error { Error_SyntaxError (yyToken); $$ = new Switch ((Expression) $3, null, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; opt_switch_sections : /* empty */ { report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); } | switch_sections ; switch_sections : switch_section | switch_sections switch_section | error { Error_SyntaxError (yyToken); } ; switch_section : switch_labels statement_list ; switch_labels : switch_label { var label = (SwitchLabel) $1; label.SectionStart = true; current_block.AddStatement (label); } | switch_labels switch_label { current_block.AddStatement ((Statement) $2); } ; switch_label : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); } | CASE constant_expression error { Error_SyntaxError (yyToken); $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); } /* | CASE pattern_expr_invocation COLON { if (lang_version != LanguageVersion.Experimental) FeatureIsNotAvailable (GetLocation ($2), "pattern matching"); $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)) { PatternMatching = true }; lbag.AddLocation ($$, GetLocation ($3)); } */ | DEFAULT_COLON { $$ = new SwitchLabel (null, GetLocation ($1)); } ; iteration_statement : while_statement | do_statement | for_statement | foreach_statement ; while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement { if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($5)); $$ = new While ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | WHILE open_parens_any boolean_expression error { Error_SyntaxError (yyToken); $$ = new While ((BooleanExpression) $3, null, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON { $$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1), GetLocation ($3)); lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4), GetLocation ($6), GetLocation ($7)); } | DO embedded_statement error { Error_SyntaxError (yyToken); $$ = new Do ((Statement) $2, null, GetLocation ($1), Location.Null); } | DO embedded_statement WHILE open_parens_any boolean_expression error { Error_SyntaxError (yyToken); $$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1), GetLocation ($3)); lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4)); } ; for_statement : FOR open_parens_any { start_block (GetLocation ($2)); current_block.IsCompilerGenerated = true; For f = new For (GetLocation ($1)); current_block.AddStatement (f); $$ = f; } for_statement_cont { $$ = $4; } ; // Has to use be extra rule to recover started block for_statement_cont : opt_for_initializer SEMICOLON { ((For) $0).Initializer = (Statement) $1; // Pass the "For" object to the iterator_part4 oob_stack.Push ($0); } for_condition_and_iterator_part embedded_statement { var locations = (Tuple) $4; oob_stack.Pop (); if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($5)); For f = ((For) $0); f.Statement = (Statement) $5; lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2), GetLocation (locations.Item1), GetLocation (locations.Item2)); $$ = end_block (GetLocation ($2)); } | error { Error_SyntaxError (yyToken); $$ = end_block (current_block.StartLocation); } ; for_condition_and_iterator_part : opt_for_condition SEMICOLON { For f = (For) oob_stack.Peek (); f.Condition = (BooleanExpression) $1; } for_iterator_part { $$ = new Tuple (GetLocation ($2), (Location) $4); } // Handle errors in the case of opt_for_condition being followed by // a close parenthesis | opt_for_condition close_parens_close_brace { report.Error (1525, GetLocation ($2), "Unexpected symbol `}'"); For f = (For) oob_stack.Peek (); f.Condition = (BooleanExpression) $1; $$ = new Tuple (GetLocation ($2), GetLocation ($2)); } ; for_iterator_part : opt_for_iterator CLOSE_PARENS { For f = (For) oob_stack.Peek (); f.Iterator = (Statement) $1; $$ = GetLocation ($2); } | opt_for_iterator CLOSE_BRACE { report.Error (1525, GetLocation ($2), "Unexpected symbol expected ')'"); For f = (For) oob_stack.Peek (); f.Iterator = (Statement) $1; $$ = GetLocation ($2); } ; close_parens_close_brace : CLOSE_PARENS | CLOSE_BRACE { lexer.putback ('}'); } ; opt_for_initializer : /* empty */ { $$ = new EmptyStatement (lexer.Location); } | for_initializer ; for_initializer : variable_type identifier_inside_body { var lt = (LocatedToken) $2; var li = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (li); current_variable = new BlockVariable ((FullNamedExpression) $1, li); } opt_local_variable_initializer opt_variable_declarators { $$ = current_variable; if ($4 != null) lbag.AddLocation (current_variable, PopLocation ()); current_variable = null; } | statement_expression_list ; opt_for_condition : /* empty */ { $$ = null; } | boolean_expression ; opt_for_iterator : /* empty */ { $$ = new EmptyStatement (lexer.Location); } | for_iterator ; for_iterator : statement_expression_list ; statement_expression_list : statement_expression | statement_expression_list COMMA statement_expression { var sl = $1 as StatementList; if (sl == null) { sl = new StatementList ((Statement) $1, (Statement) $3); lbag.AddStatement (sl, GetLocation ($2)); } else { sl.Add ((Statement) $3); lbag.AppendTo (sl, GetLocation ($2)); } $$ = sl; } ; foreach_statement : FOREACH open_parens_any type error { report.Error (230, GetLocation ($1), "Type and identifier are both required in a foreach statement"); start_block (GetLocation ($2)); current_block.IsCompilerGenerated = true; Foreach f = new Foreach ((Expression) $3, null, null, null, null, GetLocation ($1)); current_block.AddStatement (f); lbag.AddStatement (f, GetLocation ($2)); $$ = end_block (GetLocation ($4)); } | FOREACH open_parens_any type identifier_inside_body error { Error_SyntaxError (yyToken); start_block (GetLocation ($2)); current_block.IsCompilerGenerated = true; var lt = (LocatedToken) $4; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); current_block.AddLocalName (li); Foreach f = new Foreach ((Expression) $3, li, null, null, null, GetLocation ($1)); current_block.AddStatement (f); lbag.AddStatement (f, GetLocation ($2)); $$ = end_block (GetLocation ($5)); } | FOREACH open_parens_any type identifier_inside_body IN expression CLOSE_PARENS { start_block (GetLocation ($2)); current_block.IsCompilerGenerated = true; var lt = (LocatedToken) $4; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); current_block.AddLocalName (li); $$ = li; } embedded_statement { if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($9)); Foreach f = new Foreach ((Expression) $3, (LocalVariable) $8, (Expression) $6, (Statement) $9, current_block, GetLocation ($1)); lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7)); end_block (GetLocation ($7)); $$ = f; } ; jump_statement : break_statement | continue_statement | goto_statement | return_statement | throw_statement | yield_statement ; break_statement : BREAK SEMICOLON { $$ = new Break (GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; continue_statement : CONTINUE SEMICOLON { $$ = new Continue (GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } | CONTINUE error { Error_SyntaxError (yyToken); $$ = new Continue (GetLocation ($1)); } ; goto_statement : GOTO identifier_inside_body SEMICOLON { var lt = (LocatedToken) $2; $$ = new Goto (lt.Value, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); } | GOTO CASE constant_expression SEMICOLON { $$ = new GotoCase ((Expression) $3, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | GOTO DEFAULT SEMICOLON { $$ = new GotoDefault (GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); } ; return_statement : RETURN opt_expression SEMICOLON { $$ = new Return ((Expression) $2, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($3)); } | RETURN expression error { Error_SyntaxError (yyToken); $$ = new Return ((Expression) $2, GetLocation ($1)); } | RETURN error { Error_SyntaxError (yyToken); $$ = new Return (null, GetLocation ($1)); } ; throw_statement : THROW opt_expression SEMICOLON { $$ = new Throw ((Expression) $2, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($3)); } | THROW expression error { Error_SyntaxError (yyToken); $$ = new Throw ((Expression) $2, GetLocation ($1)); } | THROW error { Error_SyntaxError (yyToken); $$ = new Throw (null, GetLocation ($1)); } ; yield_statement : identifier_inside_body RETURN opt_expression SEMICOLON { var lt = (LocatedToken) $1; string s = lt.Value; if (s != "yield"){ report.Error (1003, lt.Location, "; expected"); } else if ($3 == null) { report.Error (1627, GetLocation ($4), "Expression expected after yield return"); } else if (lang_version == LanguageVersion.ISO_1){ FeatureIsNotAvailable (lt.Location, "iterators"); } current_block.Explicit.RegisterIteratorYield (); $$ = new Yield ((Expression) $3, lt.Location); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | identifier_inside_body RETURN expression error { Error_SyntaxError (yyToken); var lt = (LocatedToken) $1; string s = lt.Value; if (s != "yield"){ report.Error (1003, lt.Location, "; expected"); } else if ($3 == null) { report.Error (1627, GetLocation ($4), "Expression expected after yield return"); } else if (lang_version == LanguageVersion.ISO_1){ FeatureIsNotAvailable (lt.Location, "iterators"); } current_block.Explicit.RegisterIteratorYield (); $$ = new Yield ((Expression) $3, lt.Location); lbag.AddStatement ($$, GetLocation ($2)); } | identifier_inside_body BREAK SEMICOLON { var lt = (LocatedToken) $1; string s = lt.Value; if (s != "yield"){ report.Error (1003, lt.Location, "; expected"); } else if (lang_version == LanguageVersion.ISO_1){ FeatureIsNotAvailable (lt.Location, "iterators"); } current_block.ParametersBlock.TopBlock.IsIterator = true; $$ = new YieldBreak (lt.Location); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); } ; opt_expression : /* empty */ | expression ; try_statement : TRY block catch_clauses { $$ = new TryCatch ((Block) $2, (List) $3, GetLocation ($1), false); } | TRY block FINALLY block { $$ = new TryFinally ((Statement) $2, (ExplicitBlock) $4, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($3)); } | TRY block catch_clauses FINALLY block { $$ = new TryFinally (new TryCatch ((Block) $2, (List) $3, Location.Null, true), (ExplicitBlock) $5, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($4)); } | TRY block error { Error_SyntaxError (1524, yyToken); $$ = new TryCatch ((Block) $2, null, GetLocation ($1), false); } ; catch_clauses : catch_clause { var l = new List (2); l.Add ((Catch) $1); $$ = l; } | catch_clauses catch_clause { var l = (List) $1; Catch c = (Catch) $2; var prev_catch = l [l.Count - 1]; if (prev_catch.IsGeneral && prev_catch.Filter == null) { report.Error (1017, c.loc, "Try statement already has an empty catch block"); } l.Add (c); $$ = l; } ; opt_identifier : /* empty */ | identifier_inside_body ; catch_clause : CATCH opt_catch_filter block { var c = new Catch ((ExplicitBlock) $3, GetLocation ($1)); c.Filter = (CatchFilterExpression) $2; $$ = c; } | CATCH open_parens_any type opt_identifier CLOSE_PARENS { start_block (GetLocation ($2)); var c = new Catch ((ExplicitBlock) current_block, GetLocation ($1)); c.TypeExpression = (FullNamedExpression) $3; if ($4 != null) { var lt = (LocatedToken) $4; c.Variable = new LocalVariable (current_block, lt.Value, lt.Location); current_block.AddLocalName (c.Variable); } lbag.AddLocation (c, GetLocation ($2), GetLocation ($5)); $$ = c; lexer.parsing_catch_when = true; } opt_catch_filter_or_error { ((Catch) $6).Filter = (CatchFilterExpression) $7; $$ = $6; } | CATCH open_parens_any error { if (yyToken == Token.CLOSE_PARENS) { report.Error (1015, lexer.Location, "A type that derives from `System.Exception', `object', or `string' expected"); } else { Error_SyntaxError (yyToken); } $$ = new Catch (null, GetLocation ($1)); } ; opt_catch_filter_or_error : opt_catch_filter block_prepared { $$ = $1; } | error { end_block (Location.Null); Error_SyntaxError (yyToken); $$ = null; } ; opt_catch_filter : { lexer.parsing_catch_when = false; } | WHEN { lexer.parsing_catch_when = false; } open_parens_any expression CLOSE_PARENS { if (lang_version <= LanguageVersion.V_5) FeatureIsNotAvailable (GetLocation ($1), "exception filter"); $$ = new CatchFilterExpression ((Expression) $4, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); } ; checked_statement : CHECKED block { $$ = new Checked ((Block) $2, GetLocation ($1)); } ; unchecked_statement : UNCHECKED block { $$ = new Unchecked ((Block) $2, GetLocation ($1)); } ; unsafe_statement : UNSAFE { if (!settings.Unsafe) Error_UnsafeCodeNotAllowed (GetLocation ($1)); } block { $$ = new Unsafe ((Block) $3, GetLocation ($1)); } ; lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement { if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($5)); $$ = new Lock ((Expression) $3, (Statement) $5, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | LOCK open_parens_any expression error { Error_SyntaxError (yyToken); $$ = new Lock ((Expression) $3, null, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; fixed_statement : FIXED open_parens_any variable_type identifier_inside_body { start_block (GetLocation ($2)); current_block.IsCompilerGenerated = true; var lt = (LocatedToken) $4; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.FixedVariable | LocalVariable.Flags.Used, lt.Location); current_block.AddLocalName (li); current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) $3, li); } using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS { $$ = current_variable; current_variable = null; } embedded_statement { if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($10)); Fixed f = new Fixed ((Fixed.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); current_block.AddStatement (f); lbag.AddStatement (f, GetLocation ($2), GetLocation ($8)); $$ = end_block (GetLocation ($8)); } ; using_statement : USING open_parens_any variable_type identifier_inside_body { start_block (GetLocation ($2)); current_block.IsCompilerGenerated = true; var lt = (LocatedToken) $4; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.UsingVariable | LocalVariable.Flags.Used, lt.Location); current_block.AddLocalName (li); current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li); } using_initialization CLOSE_PARENS { $$ = current_variable; current_variable = null; } embedded_statement { if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($9)); Using u = new Using ((Using.VariableDeclaration) $8, (Statement) $9, GetLocation ($1)); current_block.AddStatement (u); $$ = end_block (GetLocation ($7)); } | USING open_parens_any expression CLOSE_PARENS embedded_statement { if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation ($5)); $$ = new Using ((Expression) $3, (Statement) $5, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } | USING open_parens_any expression error { Error_SyntaxError (yyToken); $$ = new Using ((Expression) $3, null, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; using_initialization : using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators | error { // It has to be here for the parent to safely restore artificial block Error_SyntaxError (yyToken); } ; using_or_fixed_variable_initializer : /* empty */ { Error_MissingInitializer (lexer.Location); } | ASSIGN variable_initializer { current_variable.Initializer = (Expression) $2; $$ = current_variable; } ; // LINQ query_expression : first_from_clause query_body { lexer.query_parsing = false; Linq.AQueryClause from = $1 as Linq.AQueryClause; from.Tail.Next = (Linq.AQueryClause)$2; $$ = from; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } | nested_from_clause query_body { Linq.AQueryClause from = $1 as Linq.AQueryClause; from.Tail.Next = (Linq.AQueryClause)$2; $$ = from; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } // Bubble up COMPLETE_COMPLETION productions | first_from_clause COMPLETE_COMPLETION { lexer.query_parsing = false; $$ = $1; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } | nested_from_clause COMPLETE_COMPLETION { $$ = $1; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } ; first_from_clause : FROM_FIRST identifier_inside_body IN expression { current_block = new Linq.QueryBlock (current_block, lexer.Location); var lt = (LocatedToken) $2; var rv = new Linq.RangeVariable (lt.Value, lt.Location); var clause = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)); lbag.AddLocation (clause, GetLocation ($3)); $$ = new Linq.QueryExpression (clause); } | FROM_FIRST type identifier_inside_body IN expression { current_block = new Linq.QueryBlock (current_block, lexer.Location); var lt = (LocatedToken) $3; var rv = new Linq.RangeVariable (lt.Value, lt.Location); var clause = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { IdentifierType = (FullNamedExpression)$2 }; lbag.AddLocation (clause, GetLocation ($4)); $$ = new Linq.QueryExpression (clause); } ; nested_from_clause : FROM identifier_inside_body IN expression { current_block = new Linq.QueryBlock (current_block, lexer.Location); var lt = (LocatedToken) $2; var rv = new Linq.RangeVariable (lt.Value, lt.Location); var clause = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)); lbag.AddLocation (clause, GetLocation ($3)); $$ = new Linq.QueryExpression (clause); } | FROM type identifier_inside_body IN expression { current_block = new Linq.QueryBlock (current_block, lexer.Location); var lt = (LocatedToken) $3; var rv = new Linq.RangeVariable (lt.Value, lt.Location); var clause = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { IdentifierType = (FullNamedExpression)$2 }; lbag.AddLocation (clause, GetLocation ($4)); $$ = new Linq.QueryExpression (clause); } ; from_clause : FROM identifier_inside_body IN { current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error { var lt = (LocatedToken) $2; var sn = new Linq.RangeVariable (lt.Value, lt.Location); $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$5, GetLocation ($1)); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; ((Linq.QueryBlock)current_block).AddRangeVariable (sn); lbag.AddLocation ($$, GetLocation ($3)); } | FROM type identifier_inside_body IN { current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error { var lt = (LocatedToken) $3; var sn = new Linq.RangeVariable (lt.Value, lt.Location); $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$6, GetLocation ($1)) { IdentifierType = (FullNamedExpression)$2 }; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; ((Linq.QueryBlock)current_block).AddRangeVariable (sn); lbag.AddLocation ($$, GetLocation ($4)); } ; query_body : query_body_clauses select_or_group_clause opt_query_continuation { Linq.AQueryClause head = (Linq.AQueryClause)$2; if ($3 != null) head.Next = (Linq.AQueryClause)$3; if ($1 != null) { Linq.AQueryClause clause = (Linq.AQueryClause)$1; clause.Tail.Next = head; head = clause; } $$ = head; } | select_or_group_clause opt_query_continuation { Linq.AQueryClause head = (Linq.AQueryClause)$2; if ($1 != null) { Linq.AQueryClause clause = (Linq.AQueryClause)$1; clause.Tail.Next = head; head = clause; } $$ = head; } | query_body_clauses COMPLETE_COMPLETION | query_body_clauses error { report.Error (742, GetLocation ($2), "Unexpected symbol `{0}'. A query body must end with select or group clause", GetSymbolName (yyToken)); $$ = $1; } | error { Error_SyntaxError (yyToken); $$ = null; } ; select_or_group_clause : SELECT { current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error { $$ = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } | GROUP { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); current_block = new Linq.QueryBlock (current_block, lexer.Location); linq_clause_blocks.Push ((Linq.QueryBlock)current_block); } expression_or_error { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); } by_expression { var obj = (object[]) $5; $$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)obj[0], GetLocation ($1)); lbag.AddLocation ($$, (Location) obj[1]); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } ; by_expression : BY expression_or_error { $$ = new object[] { $2, GetLocation ($1) }; } | error { Error_SyntaxError (yyToken); $$ = new object[2] { null, Location.Null }; } ; query_body_clauses : query_body_clause | query_body_clauses query_body_clause { ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$2; $$ = $1; } ; query_body_clause : from_clause | let_clause | where_clause | join_clause | orderby_clause ; let_clause : LET identifier_inside_body ASSIGN { current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error { var lt = (LocatedToken) $2; var sn = new Linq.RangeVariable (lt.Value, lt.Location); $$ = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)$5, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3)); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; ((Linq.QueryBlock)current_block).AddRangeVariable (sn); } ; where_clause : WHERE { current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error { $$ = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } ; join_clause : JOIN identifier_inside_body IN { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); current_block = new Linq.QueryBlock (current_block, lexer.Location); linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } expression_or_error ON { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } expression_or_error EQUALS { current_block.AddStatement (new ContextualReturn ((Expression) $8)); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error opt_join_into { current_block.AddStatement (new ContextualReturn ((Expression) $11)); current_block.SetEndLocation (lexer.Location); var outer_selector = linq_clause_blocks.Pop (); var block = linq_clause_blocks.Pop (); var lt = (LocatedToken) $2; var sn = new Linq.RangeVariable (lt.Value, lt.Location); Linq.RangeVariable into; if ($12 == null) { into = sn; $$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9)); } else { // // Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions // var parent = block.Parent; while (parent is Linq.QueryBlock) { parent = parent.Parent; } current_block.Parent = parent; ((Linq.QueryBlock)current_block).AddRangeVariable (sn); lt = (LocatedToken) $12; into = new Linq.RangeVariable (lt.Value, lt.Location); $$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($12)); } current_block = block.Parent; ((Linq.QueryBlock)current_block).AddRangeVariable (into); } | JOIN type identifier_inside_body IN { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); current_block = new Linq.QueryBlock (current_block, lexer.Location); linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } expression_or_error ON { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } expression_or_error EQUALS { current_block.AddStatement (new ContextualReturn ((Expression) $9)); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); } expression_or_error opt_join_into { current_block.AddStatement (new ContextualReturn ((Expression) $12)); current_block.SetEndLocation (lexer.Location); var outer_selector = linq_clause_blocks.Pop (); var block = linq_clause_blocks.Pop (); var lt = (LocatedToken) $3; var sn = new Linq.RangeVariable (lt.Value, lt.Location); Linq.RangeVariable into; if ($13 == null) { into = sn; $$ = new Linq.Join (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)) { IdentifierType = (FullNamedExpression)$2 }; lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9)); } else { // // Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions // var parent = block.Parent; while (parent is Linq.QueryBlock) { parent = parent.Parent; } current_block.Parent = parent; ((Linq.QueryBlock)current_block).AddRangeVariable (sn); lt = (LocatedToken) $13; into = new Linq.RangeVariable (lt.Value, lt.Location); // TODO: $$ = new Linq.GroupJoin (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)) { IdentifierType = (FullNamedExpression)$2 }; } current_block = block.Parent; ((Linq.QueryBlock)current_block).AddRangeVariable (into); } ; opt_join_into : /* empty */ | INTO identifier_inside_body { $$ = $2; } ; orderby_clause : ORDERBY { current_block = new Linq.QueryBlock (current_block, lexer.Location); } orderings { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; $$ = $3; } ; orderings : order_by | order_by COMMA { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); } orderings_then_by { ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$4; $$ = $1; } ; orderings_then_by : then_by | orderings_then_by COMMA { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); } then_by { ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$4; $$ = $1; } ; order_by : expression { $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); } | expression ASCENDING { $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); lbag.AddLocation ($$, GetLocation ($2)); } | expression DESCENDING { $$ = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)$1); lbag.AddLocation ($$, GetLocation ($2)); } ; then_by : expression { $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); } | expression ASCENDING { $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); lbag.AddLocation ($$, GetLocation ($2)); } | expression DESCENDING { $$ = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)$1); lbag.AddLocation ($$, GetLocation ($2)); } ; opt_query_continuation : /* empty */ | INTO identifier_inside_body { // query continuation block is not linked with query block but with block // before. This means each query can use same range variable names for // different identifiers. current_block.SetEndLocation (GetLocation ($1)); current_block = current_block.Parent; current_block = new Linq.QueryBlock (current_block, lexer.Location); if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } query_body { var current_block = linq_clause_blocks.Pop (); var lt = (LocatedToken) $2; var rv = new Linq.RangeVariable (lt.Value, lt.Location); $$ = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, rv, GetLocation ($1)) { next = (Linq.AQueryClause)$4 }; } ; // // Support for using the compiler as an interactive parser // // The INTERACTIVE_PARSER token is first sent to parse our // productions; If the result is a Statement, the parsing // is repeated, this time with INTERACTIVE_PARSE_WITH_BLOCK // to setup the blocks in advance. // // This setup is here so that in the future we can add // support for other constructs (type parsing, namespaces, etc) // that do not require a block to be setup in advance // interactive_parsing : EVAL_STATEMENT_PARSER EOF | EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION | EVAL_STATEMENT_PARSER { current_container = current_type = new Class (current_container, new MemberName (""), Modifiers.PUBLIC, null); // (ref object retval) Parameter [] mpar = new Parameter [1]; mpar [0] = new Parameter (new TypeExpression (compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null); ParametersCompiled pars = new ParametersCompiled (mpar); var mods = Modifiers.PUBLIC | Modifiers.STATIC; if (settings.Unsafe) mods |= Modifiers.UNSAFE; current_local_parameters = pars; var method = new InteractiveMethod ( current_type, new TypeExpression (compiler.BuiltinTypes.Void, Location.Null), mods, pars); current_type.AddMember (method); oob_stack.Push (method); interactive_async = false; ++lexer.parsing_block; start_block (lexer.Location); } interactive_statement_list opt_COMPLETE_COMPLETION { --lexer.parsing_block; var method = (InteractiveMethod) oob_stack.Pop (); method.Block = (ToplevelBlock) end_block(lexer.Location); if (interactive_async == true) { method.ChangeToAsync (); } InteractiveResult = (Class) pop_current_class (); current_local_parameters = null; } | EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit ; interactive_compilation_unit : opt_extern_alias_directives opt_using_directives | opt_extern_alias_directives opt_using_directives namespace_or_type_declarations ; opt_COMPLETE_COMPLETION : /* nothing */ | COMPLETE_COMPLETION ; close_brace_or_complete_completion : CLOSE_BRACE | COMPLETE_COMPLETION ; // // XML documentation code references micro parser // documentation_parsing : DOC_SEE doc_cref { module.DocumentationBuilder.ParsedName = (MemberName) $2; } ; doc_cref : doc_type_declaration_name opt_doc_method_sig { module.DocumentationBuilder.ParsedParameters = (List)$2; } | builtin_types opt_doc_method_sig { module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; module.DocumentationBuilder.ParsedParameters = (List)$2; $$ = null; } | VOID opt_doc_method_sig { module.DocumentationBuilder.ParsedBuiltinType = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); module.DocumentationBuilder.ParsedParameters = (List)$2; $$ = null; } | builtin_types DOT IDENTIFIER opt_doc_method_sig { module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; module.DocumentationBuilder.ParsedParameters = (List)$4; var lt = (LocatedToken) $3; $$ = new MemberName (lt.Value); } | doc_type_declaration_name DOT THIS { $$ = new MemberName ((MemberName) $1, MemberCache.IndexerNameAlias, Location.Null); } | doc_type_declaration_name DOT THIS OPEN_BRACKET { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } opt_doc_parameters CLOSE_BRACKET { module.DocumentationBuilder.ParsedParameters = (List)$6; $$ = new MemberName ((MemberName) $1, MemberCache.IndexerNameAlias, Location.Null); } | EXPLICIT OPERATOR type opt_doc_method_sig { var p = (List)$4 ?? new List (1); p.Add (new DocumentationParameter ((FullNamedExpression) $3)); module.DocumentationBuilder.ParsedParameters = p; module.DocumentationBuilder.ParsedOperator = Operator.OpType.Explicit; $$ = null; } | IMPLICIT OPERATOR type opt_doc_method_sig { var p = (List)$4 ?? new List (1); p.Add (new DocumentationParameter ((FullNamedExpression) $3)); module.DocumentationBuilder.ParsedParameters = p; module.DocumentationBuilder.ParsedOperator = Operator.OpType.Implicit; $$ = null; } | OPERATOR overloadable_operator opt_doc_method_sig { var p = (List)$3; module.DocumentationBuilder.ParsedParameters = p; module.DocumentationBuilder.ParsedOperator = (Operator.OpType) $2; $$ = null; } ; doc_type_declaration_name : type_declaration_name | doc_type_declaration_name DOT type_declaration_name { $$ = new MemberName (((MemberName) $1), (MemberName) $3); } ; opt_doc_method_sig : /* empty */ | OPEN_PARENS { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } opt_doc_parameters CLOSE_PARENS { $$ = $3; } ; opt_doc_parameters : /* empty */ { $$ = new List (0); } | doc_parameters ; doc_parameters : doc_parameter { var parameters = new List (); parameters.Add ((DocumentationParameter) $1); $$ = parameters; } | doc_parameters COMMA doc_parameter { var parameters = $1 as List; parameters.Add ((DocumentationParameter) $3); $$ = parameters; } ; doc_parameter : opt_parameter_modifier parameter_type { if ($1 != null) $$ = new DocumentationParameter ((Parameter.Modifier) $1, (FullNamedExpression) $2); else $$ = new DocumentationParameter ((FullNamedExpression) $2); } ; %% // // A class used to hold info about an operator declarator // class OperatorDeclaration { public readonly Operator.OpType optype; public readonly FullNamedExpression ret_type; public readonly Location location; public OperatorDeclaration (Operator.OpType op, FullNamedExpression ret_type, Location location) { optype = op; this.ret_type = ret_type; this.location = location; } } void Error_ExpectingTypeName (Expression expr) { if (expr is Invocation){ report.Error (1002, expr.Location, "Expecting `;'"); } else { expr.Error_InvalidExpressionStatement (report); } } void Error_ParameterModifierNotValid (string modifier, Location loc) { report.Error (631, loc, "The parameter modifier `{0}' is not valid in this context", modifier); } void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) { report.Error (1107, loc, "Duplicate parameter modifier `{0}'", Parameter.GetModifierSignature (mod)); } void Error_TypeExpected (Location loc) { report.Error (1031, loc, "Type expected"); } void Error_UnsafeCodeNotAllowed (Location loc) { report.Error (227, loc, "Unsafe code requires the `unsafe' command line option to be specified"); } void Warning_EmptyStatement (Location loc) { report.Warning (642, 3, loc, "Possible mistaken empty statement"); } void Error_NamedArgumentExpected (NamedArgument a) { report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); } void Error_MissingInitializer (Location loc) { report.Error (210, loc, "You must provide an initializer in a fixed or using statement declaration"); } object Error_AwaitAsIdentifier (object token) { if (async_block) { report.Error (4003, GetLocation (token), "`await' cannot be used as an identifier within an async method or lambda expression"); return new LocatedToken ("await", GetLocation (token)); } return token; } void push_current_container (TypeDefinition tc, object partial_token) { if (module.Evaluator != null){ tc.Definition.Modifiers = tc.ModFlags = (tc.ModFlags & ~Modifiers.AccessibilityMask) | Modifiers.PUBLIC; if (undo == null) undo = new Undo (); undo.AddTypeContainer (current_container, tc); } if (partial_token != null) current_container.AddPartial (tc); else current_container.AddTypeContainer (tc); ++lexer.parsing_declaration; current_container = tc; current_type = tc; } TypeContainer pop_current_class () { var retval = current_container; current_container = current_container.Parent; current_type = current_type.Parent as TypeDefinition; return retval; } [System.Diagnostics.Conditional ("FULL_AST")] void StoreModifierLocation (object token, Location loc) { if (lbag == null) return; if (mod_locations == null) mod_locations = new List> (); mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); } [System.Diagnostics.Conditional ("FULL_AST")] void PushLocation (Location loc) { if (location_stack == null) location_stack = new Stack (); location_stack.Push (loc); } Location PopLocation () { if (location_stack == null) return Location.Null; return location_stack.Pop (); } string CheckAttributeTarget (int token, string a, Location l) { switch (a) { case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : return a; } if (!Tokenizer.IsValidIdentifier (a)) { Error_SyntaxError (token); } else { report.Warning (658, 1, l, "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", a); } return string.Empty; } static bool IsUnaryOperator (Operator.OpType op) { switch (op) { case Operator.OpType.LogicalNot: case Operator.OpType.OnesComplement: case Operator.OpType.Increment: case Operator.OpType.Decrement: case Operator.OpType.True: case Operator.OpType.False: case Operator.OpType.UnaryPlus: case Operator.OpType.UnaryNegation: return true; } return false; } void syntax_error (Location l, string msg) { report.Error (1003, l, "Syntax error, " + msg); } Tokenizer lexer; public Tokenizer Lexer { get { return lexer; } } public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, ParserSession session) : this (reader, file, file.Compiler.Report, session) { } public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Report report, ParserSession session) { this.file = file; current_container = current_namespace = file; this.module = file.Module; this.compiler = file.Compiler; this.settings = compiler.Settings; this.report = report; lang_version = settings.Version; yacc_verbose_flag = settings.VerboseParserFlag; doc_support = settings.DocumentationFile != null; lexer = new Tokenizer (reader, file, session, report); oob_stack = new Stack (); lbag = session.LocationsBag; use_global_stacks = session.UseJayGlobalArrays; parameters_bucket = session.ParametersStack; } public void parse () { eof_token = Token.EOF; try { if (yacc_verbose_flag > 1) yyparse (lexer, new yydebug.yyDebugSimple ()); else yyparse (lexer); Tokenizer tokenizer = lexer as Tokenizer; tokenizer.cleanup (); } catch (Exception e){ if (e is yyParser.yyUnexpectedEof) { Error_SyntaxError (yyToken); UnexpectedEOF = true; return; } if (e is yyParser.yyException) { if (report.Errors == 0) report.Error (-25, lexer.Location, "Parsing error"); } else { // Used by compiler-tester to test internal errors if (yacc_verbose_flag > 0 || e is FatalException) throw; report.Error (589, lexer.Location, "Internal compiler error during parsing" + e); } } } void CheckToken (int error, int yyToken, string msg, Location loc) { if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) report.Error (error, loc, "{0}: `{1}' is a keyword", msg, GetTokenName (yyToken)); else report.Error (error, loc, msg); } string ConsumeStoredComment () { string s = tmpComment; tmpComment = null; Lexer.doc_state = XmlCommentState.Allowed; return s; } void FeatureIsNotAvailable (Location loc, string feature) { report.FeatureIsNotAvailable (compiler, loc, feature); } Location GetLocation (object obj) { var lt = obj as LocatedToken; if (lt != null) return lt.Location; var mn = obj as MemberName; if (mn != null) return mn.Location; var expr = obj as Expression; if (expr != null) return expr.Location; return lexer.Location; } void start_block (Location loc) { if (current_block == null) { current_block = new ToplevelBlock (compiler, current_local_parameters, loc); parsing_anonymous_method = false; } else if (parsing_anonymous_method) { current_block = new ParametersBlock (current_block, current_local_parameters, loc); parsing_anonymous_method = false; } else { current_block = new ExplicitBlock (current_block, loc, Location.Null); } } Block end_block (Location loc) { Block retval = current_block.Explicit; retval.SetEndLocation (loc); current_block = retval.Parent; return retval; } void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync, Location loc) { oob_stack.Push (current_anonymous_method); oob_stack.Push (current_local_parameters); oob_stack.Push (current_variable); oob_stack.Push (async_block); current_local_parameters = parameters; if (isLambda) { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (loc, "lambda expressions"); current_anonymous_method = new LambdaExpression (loc); } else { if (lang_version == LanguageVersion.ISO_1) FeatureIsNotAvailable (loc, "anonymous methods"); current_anonymous_method = new AnonymousMethodExpression (loc); } async_block = isAsync; // Force the next block to be created as a ToplevelBlock parsing_anonymous_method = true; } /* * Completes the anonymous method processing, if lambda_expr is null, this * means that we have a Statement instead of an Expression embedded */ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) { AnonymousMethodExpression retval; if (async_block) anon_block.IsAsync = true; current_anonymous_method.Block = anon_block; retval = current_anonymous_method; async_block = (bool) oob_stack.Pop (); current_variable = (BlockVariable) oob_stack.Pop (); current_local_parameters = (ParametersCompiled) oob_stack.Pop (); current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); return retval; } void Error_SyntaxError (int token) { Error_SyntaxError (0, token); } void Error_SyntaxError (int error_code, int token) { Error_SyntaxError (error_code, token, "Unexpected symbol"); } void Error_SyntaxError (int error_code, int token, string msg) { Lexer.CompleteOnEOF = false; // An error message has been reported by tokenizer if (token == Token.ERROR) return; // Avoid duplicit error message after unterminated string literals if (token == Token.LITERAL && lexer.Location.Column == 0) return; string symbol = GetSymbolName (token); string expecting = GetExpecting (); var loc = lexer.Location - symbol.Length; if (error_code == 0) { if (expecting == "`identifier'") { if (token > Token.FIRST_KEYWORD && token < Token.LAST_KEYWORD) { report.Error (1041, loc, "Identifier expected, `{0}' is a keyword", symbol); return; } error_code = 1001; expecting = "identifier"; } else if (expecting == "`)'") { error_code = 1026; } else { error_code = 1525; } } if (string.IsNullOrEmpty (expecting)) report.Error (error_code, loc, "{1} `{0}'", symbol, msg); else report.Error (error_code, loc, "{2} `{0}', expecting {1}", symbol, expecting, msg); } string GetExpecting () { int [] tokens = yyExpectingTokens (yyExpectingState); var names = new List (tokens.Length); bool has_type = false; bool has_identifier = false; for (int i = 0; i < tokens.Length; i++){ int token = tokens [i]; has_identifier |= token == Token.IDENTIFIER; string name = GetTokenName (token); if (name == "") continue; has_type |= name == "type"; if (names.Contains (name)) continue; names.Add (name); } // // Too many tokens to enumerate // if (names.Count > 8) return null; if (has_type && has_identifier) names.Remove ("identifier"); if (names.Count == 1) return "`" + GetTokenName (tokens [0]) + "'"; StringBuilder sb = new StringBuilder (); names.Sort (); int count = names.Count; for (int i = 0; i < count; i++){ bool last = i + 1 == count; if (last) sb.Append ("or "); sb.Append ('`'); sb.Append (names [i]); sb.Append (last ? "'" : count < 3 ? "' " : "', "); } return sb.ToString (); } string GetSymbolName (int token) { switch (token){ case Token.LITERAL: return ((Constant)lexer.Value).GetValue ().ToString (); case Token.IDENTIFIER: return ((LocatedToken)lexer.Value).Value; case Token.BOOL: return "bool"; case Token.BYTE: return "byte"; case Token.CHAR: return "char"; case Token.VOID: return "void"; case Token.DECIMAL: return "decimal"; case Token.DOUBLE: return "double"; case Token.FLOAT: return "float"; case Token.INT: return "int"; case Token.LONG: return "long"; case Token.SBYTE: return "sbyte"; case Token.SHORT: return "short"; case Token.STRING: return "string"; case Token.UINT: return "uint"; case Token.ULONG: return "ulong"; case Token.USHORT: return "ushort"; case Token.OBJECT: return "object"; case Token.PLUS: return "+"; case Token.UMINUS: case Token.MINUS: return "-"; case Token.BANG: return "!"; case Token.BITWISE_AND: return "&"; case Token.BITWISE_OR: return "|"; case Token.STAR: return "*"; case Token.PERCENT: return "%"; case Token.DIV: return "/"; case Token.CARRET: return "^"; case Token.OP_INC: return "++"; case Token.OP_DEC: return "--"; case Token.OP_SHIFT_LEFT: return "<<"; case Token.OP_SHIFT_RIGHT: return ">>"; case Token.OP_LT: return "<"; case Token.OP_GT: return ">"; case Token.OP_LE: return "<="; case Token.OP_GE: return ">="; case Token.OP_EQ: return "=="; case Token.OP_NE: return "!="; case Token.OP_AND: return "&&"; case Token.OP_OR: return "||"; case Token.OP_PTR: return "->"; case Token.OP_COALESCING: return "??"; case Token.OP_MULT_ASSIGN: return "*="; case Token.OP_DIV_ASSIGN: return "/="; case Token.OP_MOD_ASSIGN: return "%="; case Token.OP_ADD_ASSIGN: return "+="; case Token.OP_SUB_ASSIGN: return "-="; case Token.OP_SHIFT_LEFT_ASSIGN: return "<<="; case Token.OP_SHIFT_RIGHT_ASSIGN: return ">>="; case Token.OP_AND_ASSIGN: return "&="; case Token.OP_XOR_ASSIGN: return "^="; case Token.OP_OR_ASSIGN: return "|="; } return GetTokenName (token); } static string GetTokenName (int token) { switch (token){ case Token.ABSTRACT: return "abstract"; case Token.AS: return "as"; case Token.ADD: return "add"; case Token.ASYNC: return "async"; case Token.BASE: return "base"; case Token.BREAK: return "break"; case Token.CASE: return "case"; case Token.CATCH: return "catch"; case Token.CHECKED: return "checked"; case Token.CLASS: return "class"; case Token.CONST: return "const"; case Token.CONTINUE: return "continue"; case Token.DEFAULT: return "default"; case Token.DELEGATE: return "delegate"; case Token.DO: return "do"; case Token.ELSE: return "else"; case Token.ENUM: return "enum"; case Token.EVENT: return "event"; case Token.EXPLICIT: return "explicit"; case Token.EXTERN: case Token.EXTERN_ALIAS: return "extern"; case Token.FALSE: return "false"; case Token.FINALLY: return "finally"; case Token.FIXED: return "fixed"; case Token.FOR: return "for"; case Token.FOREACH: return "foreach"; case Token.GOTO: return "goto"; case Token.IF: return "if"; case Token.IMPLICIT: return "implicit"; case Token.IN: return "in"; case Token.INTERFACE: return "interface"; case Token.INTERNAL: return "internal"; case Token.IS: return "is"; case Token.LOCK: return "lock"; case Token.NAMESPACE: return "namespace"; case Token.NEW: return "new"; case Token.NULL: return "null"; case Token.OPERATOR: return "operator"; case Token.OUT: return "out"; case Token.OVERRIDE: return "override"; case Token.PARAMS: return "params"; case Token.PRIVATE: return "private"; case Token.PROTECTED: return "protected"; case Token.PUBLIC: return "public"; case Token.READONLY: return "readonly"; case Token.REF: return "ref"; case Token.RETURN: return "return"; case Token.REMOVE: return "remove"; case Token.SEALED: return "sealed"; case Token.SIZEOF: return "sizeof"; case Token.STACKALLOC: return "stackalloc"; case Token.STATIC: return "static"; case Token.STRUCT: return "struct"; case Token.SWITCH: return "switch"; case Token.THIS: return "this"; case Token.THROW: return "throw"; case Token.TRUE: return "true"; case Token.TRY: return "try"; case Token.TYPEOF: return "typeof"; case Token.UNCHECKED: return "unchecked"; case Token.UNSAFE: return "unsafe"; case Token.USING: return "using"; case Token.VIRTUAL: return "virtual"; case Token.VOLATILE: return "volatile"; case Token.WHERE: return "where"; case Token.WHILE: return "while"; case Token.ARGLIST: return "__arglist"; case Token.REFVALUE: return "__refvalue"; case Token.REFTYPE: return "__reftype"; case Token.MAKEREF: return "__makeref"; case Token.PARTIAL: return "partial"; case Token.ARROW: return "=>"; case Token.FROM: case Token.FROM_FIRST: return "from"; case Token.JOIN: return "join"; case Token.ON: return "on"; case Token.EQUALS: return "equals"; case Token.SELECT: return "select"; case Token.GROUP: return "group"; case Token.BY: return "by"; case Token.LET: return "let"; case Token.ORDERBY: return "orderby"; case Token.ASCENDING: return "ascending"; case Token.DESCENDING: return "descending"; case Token.INTO: return "into"; case Token.GET: return "get"; case Token.SET: return "set"; case Token.OPEN_BRACE: return "{"; case Token.CLOSE_BRACE: return "}"; case Token.OPEN_BRACKET: case Token.OPEN_BRACKET_EXPR: return "["; case Token.CLOSE_BRACKET: return "]"; case Token.OPEN_PARENS_CAST: case Token.OPEN_PARENS_LAMBDA: case Token.OPEN_PARENS: return "("; case Token.CLOSE_PARENS: return ")"; case Token.DOT: return "."; case Token.COMMA: return ","; case Token.DEFAULT_COLON: return "default:"; case Token.COLON: return ":"; case Token.SEMICOLON: return ";"; case Token.TILDE: return "~"; case Token.WHEN: return "when"; case Token.INTERPOLATED_STRING_END: return "}"; case Token.INTERPOLATED_STRING: return "${"; case Token.PLUS: case Token.UMINUS: case Token.MINUS: case Token.BANG: case Token.OP_LT: case Token.OP_GT: case Token.BITWISE_AND: case Token.BITWISE_OR: case Token.STAR: case Token.PERCENT: case Token.DIV: case Token.CARRET: case Token.OP_INC: case Token.OP_DEC: case Token.OP_SHIFT_LEFT: case Token.OP_SHIFT_RIGHT: case Token.OP_LE: case Token.OP_GE: case Token.OP_EQ: case Token.OP_NE: case Token.OP_AND: case Token.OP_OR: case Token.OP_PTR: case Token.OP_COALESCING: case Token.OP_MULT_ASSIGN: case Token.OP_DIV_ASSIGN: case Token.OP_MOD_ASSIGN: case Token.OP_ADD_ASSIGN: case Token.OP_SUB_ASSIGN: case Token.OP_SHIFT_LEFT_ASSIGN: case Token.OP_SHIFT_RIGHT_ASSIGN: case Token.OP_AND_ASSIGN: case Token.OP_XOR_ASSIGN: case Token.OP_OR_ASSIGN: case Token.INTERR_OPERATOR: return ""; case Token.BOOL: case Token.BYTE: case Token.CHAR: case Token.VOID: case Token.DECIMAL: case Token.DOUBLE: case Token.FLOAT: case Token.INT: case Token.LONG: case Token.SBYTE: case Token.SHORT: case Token.STRING: case Token.UINT: case Token.ULONG: case Token.USHORT: case Token.OBJECT: return "type"; case Token.ASSIGN: return "="; case Token.OP_GENERICS_LT: case Token.GENERIC_DIMENSION: return "<"; case Token.OP_GENERICS_GT: return ">"; case Token.INTERR: case Token.INTERR_NULLABLE: return "?"; case Token.DOUBLE_COLON: return "::"; case Token.LITERAL: return "value"; case Token.IDENTIFIER: case Token.AWAIT: return "identifier"; case Token.EOF: return "end-of-file"; // All of these are internal. case Token.NONE: case Token.ERROR: case Token.FIRST_KEYWORD: case Token.EVAL_COMPILATION_UNIT_PARSER: case Token.EVAL_USING_DECLARATIONS_UNIT_PARSER: case Token.EVAL_STATEMENT_PARSER: case Token.LAST_KEYWORD: case Token.GENERATE_COMPLETION: case Token.COMPLETE_COMPLETION: return ""; // A bit more robust. default: return yyNames [token]; } } /* end end end */ }