Merge pull request #607 from maksimenko/master
[mono.git] / mcs / mcs / cs-parser.jay
index d0ac204bd7f6d10681d8c1d9118e40ddefa5de0e..902690017e992da6e112221bbd8078cc1d7751c8 100644 (file)
@@ -139,6 +139,7 @@ namespace Mono.CSharp
                //
                LocationsBag lbag;
                List<Tuple<Modifiers, Location>> mod_locations;
+               Stack<Location> location_stack;
 %}
 
 %token EOF
@@ -521,7 +522,7 @@ namespace_declaration
                if (doc_support)
                        Lexer.doc_state = XmlCommentState.Allowed;
          }
-         opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon
+         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));
@@ -541,6 +542,16 @@ namespace_declaration
          }
        ;
 
+opt_semicolon_error
+       : /* empty */
+       | SEMICOLON
+       | error
+         {
+               Error_SyntaxError (yyToken);
+               $$ = null;
+         }
+       ;
+
 namespace_name
        : IDENTIFIER
          {
@@ -665,6 +676,7 @@ attribute_sections
 attribute_section
        : OPEN_BRACKET
          {
+               PushLocation (GetLocation ($1));
                lexer.parsing_attribute_section = true;
          }
          attribute_section_cont
@@ -689,13 +701,43 @@ attribute_section_cont
                        $$ = new List<Attribute> (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 = (Tokenizer.LocatedToken) $1;
+               var tne = new SimpleName (lt.Value, null, lt.Location);
+
+               $$ = new List<Attribute> () {
+                       new Attribute (null, tne, null, GetLocation ($1), false)
+               };
+         }
+       | error
+         {
+               $$ = CheckAttributeTarget (GetTokenName (yyToken), GetLocation ($1)); 
+               $$ = null;
          }
        ;       
 
@@ -707,16 +749,6 @@ attribute_target
          }
        | EVENT  { $$ = "event"; }
        | RETURN { $$ = "return"; }
-       | error
-         {
-               if (yyToken == Token.IDENTIFIER) {
-                       Error_SyntaxError (yyToken);
-                       $$ = null;
-               } else {
-                       string name = GetTokenName (yyToken);
-                       $$ = CheckAttributeTarget (name, GetLocation ($1));
-               }
-         }
        ;
 
 attribute_list
@@ -727,7 +759,10 @@ attribute_list
        | attribute_list COMMA attribute
          {
                var attrs = (List<Attribute>) $1;
-               attrs.Add ((Attribute) $3);
+               if (attrs != null) {
+                       attrs.Add ((Attribute) $3);
+                       lbag.AppendTo (attrs, GetLocation ($2));
+               }
 
                $$ = attrs;
          }
@@ -809,6 +844,11 @@ positional_or_named_argument
                $$ = new Argument ((Expression) $1);
          }
        | named_argument
+       | error
+         {
+               Error_SyntaxError (yyToken);
+               $$ = null;
+         }
        ;
 
 named_attribute_argument
@@ -880,13 +920,14 @@ class_member_declaration
        | 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;
-         }
+         }     
        ;
 
 struct_declaration
@@ -895,10 +936,10 @@ struct_declaration
          opt_partial
          STRUCT
          {
-               lexer.ConstraintsParsing = true;
          }
          type_declaration_name
          { 
+               lexer.ConstraintsParsing = true;
                push_current_container (new Struct (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3);
          }
          opt_class_base
@@ -1463,7 +1504,7 @@ fixed_parameter
        : opt_attributes
          opt_parameter_modifier
          parameter_type
-         IDENTIFIER
+         identifier_inside_body
          {
                var lt = (Tokenizer.LocatedToken) $4;
                $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location);
@@ -1471,7 +1512,7 @@ fixed_parameter
        | opt_attributes
          opt_parameter_modifier
          parameter_type
-         IDENTIFIER OPEN_BRACKET CLOSE_BRACKET
+         identifier_inside_body OPEN_BRACKET CLOSE_BRACKET
          {
                var lt = (Tokenizer.LocatedToken) $4;
                report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name");
@@ -1495,7 +1536,7 @@ fixed_parameter
        | opt_attributes
          opt_parameter_modifier
          parameter_type
-         IDENTIFIER
+         identifier_inside_body
          ASSIGN
          {
                ++lexer.parsing_block;
@@ -1865,10 +1906,10 @@ interface_declaration
          opt_partial
          INTERFACE
          {
-               lexer.ConstraintsParsing = true;
          }
          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));            
          }
@@ -2079,7 +2120,11 @@ conversion_operator_declarator
 
                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;
@@ -2098,7 +2143,11 @@ conversion_operator_declarator
                
                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;
@@ -2497,6 +2546,23 @@ attributes_without_members
                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
@@ -3081,35 +3147,35 @@ close_parens
 parenthesized_expression
        : OPEN_PARENS expression CLOSE_PARENS
          {
-               $$ = new ParenthesizedExpression ((Expression) $2);
+               $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1));
                lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3));
          }
        | OPEN_PARENS expression COMPLETE_COMPLETION
          {
-               $$ = new ParenthesizedExpression ((Expression) $2);
+               $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1));
          }
        ;
        
 member_access
-       : primary_expression DOT IDENTIFIER opt_type_argument_list
+       : primary_expression DOT identifier_inside_body opt_type_argument_list
          {
                var lt = (Tokenizer.LocatedToken) $3;
                $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
                lbag.AddLocation ($$, GetLocation ($2));
          }
-       | builtin_types DOT IDENTIFIER opt_type_argument_list
+       | builtin_types DOT identifier_inside_body opt_type_argument_list
          {
                var lt = (Tokenizer.LocatedToken) $3;
                $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
                lbag.AddLocation ($$, GetLocation ($2));
          }
-       | BASE DOT IDENTIFIER opt_type_argument_list
+       | BASE DOT identifier_inside_body opt_type_argument_list
          {
                var lt = (Tokenizer.LocatedToken) $3;
                $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location);
                lbag.AddLocation ($$, GetLocation ($2));
          }
-       | qualified_alias_member IDENTIFIER opt_type_argument_list
+       | qualified_alias_member identifier_inside_body opt_type_argument_list
          {
                var lt1 = (Tokenizer.LocatedToken) $1;
                var lt2 = (Tokenizer.LocatedToken) $2;
@@ -3153,7 +3219,7 @@ invocation_expression
 
                $$ = new Invocation ((Expression) $1, null);
                lbag.AddLocation ($$, GetLocation ($2));
-         }     
+         }
        ;
 
 opt_object_or_collection_initializer
@@ -3165,12 +3231,11 @@ object_or_collection_initializer
        : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion
          {
                if ($2 == null) {
-                       $$ = CollectionOrObjectInitializers.Empty;
-                       // TODO: lbag
+                       $$ = new CollectionOrObjectInitializers (GetLocation ($1));
                } else {
                        $$ = new CollectionOrObjectInitializers ((List<Expression>) $2, GetLocation ($1));
-                       lbag.AddLocation ($$, GetLocation ($3));
                }
+               lbag.AddLocation ($$, GetLocation ($3));
          }
        | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE
          {
@@ -3213,6 +3278,12 @@ member_initializer
                $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location);
                lbag.AddLocation ($$, GetLocation ($2));
          }
+       | AWAIT ASSIGN initializer_value
+         {
+               var lt = (Tokenizer.LocatedToken) Error_AwaitAsIdentifier ($1);
+               $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location);
+               lbag.AddLocation ($$, GetLocation ($2));
+         }
        | GENERATE_COMPLETION 
          {
                $$ = new CompletionElementInitializer (null, GetLocation ($1));
@@ -3235,7 +3306,7 @@ member_initializer
          {
                report.Error (1920, GetLocation ($1), "An element initializer cannot be empty");
                $$ = null;
-         }       
+         }
        ;
 
 initializer_value
@@ -3351,22 +3422,18 @@ element_access
        ;
 
 expression_list
-       : expression
+       : expression_or_error
          {
                var list = new List<Expression> (4);
                list.Add ((Expression) $1);
                $$ = list;
          }
-       | expression_list COMMA expression
+       | expression_list COMMA expression_or_error
          {
                var list = (List<Expression>) $1;
                list.Add ((Expression) $3);
                $$ = list;
          }
-       | expression_list error {
-               Error_SyntaxError (yyToken);
-               $$ = $1;
-         }
        ;
        
 expression_list_arguments
@@ -3540,13 +3607,13 @@ anonymous_type_parameters
        ;
 
 anonymous_type_parameter
-       : IDENTIFIER ASSIGN variable_initializer
+       : identifier_inside_body ASSIGN variable_initializer
          {
                var lt = (Tokenizer.LocatedToken)$1;
                $$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location);
                lbag.AddLocation ($$, GetLocation ($2));
          }
-       | IDENTIFIER
+       | identifier_inside_body
          {
                var lt = (Tokenizer.LocatedToken)$1;
                $$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location),
@@ -4270,6 +4337,14 @@ conditional_expression
                $$ = 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
@@ -4369,6 +4444,11 @@ lambda_parameter
                var lt = (Tokenizer.LocatedToken) $1;
                $$ = new ImplicitLambdaParameter (lt.Value, lt.Location);
          }
+       | AWAIT
+         {
+               var lt = (Tokenizer.LocatedToken) Error_AwaitAsIdentifier ($1);
+               $$ = new ImplicitLambdaParameter (lt.Value, lt.Location);
+         }
        ;
 
 opt_lambda_parameter_list
@@ -4395,6 +4475,8 @@ lambda_expression_body
          {
                // 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;
@@ -4422,6 +4504,17 @@ lambda_expression
                $$ = end_anonymous ((ParametersBlock) $4);
                lbag.AddLocation ($$, GetLocation ($2));
          }
+       | AWAIT ARROW
+         {
+               var lt = (Tokenizer.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 = (Tokenizer.LocatedToken) $2;
@@ -4516,10 +4609,11 @@ class_declaration
          opt_partial
          CLASS
          {
-               lexer.ConstraintsParsing = true;
          }
          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");
@@ -5096,10 +5190,7 @@ identifier_inside_body
        : IDENTIFIER
        | AWAIT
          {
-               if (async_block) {
-                       report.Error (4003, GetLocation ($1), "`await' cannot be used as an identifier within an async method or lambda expression");
-                       $$ = new Tokenizer.LocatedToken ("await", GetLocation ($1));
-               }
+               $$ = Error_AwaitAsIdentifier ($1);
          }
        ;
 
@@ -5115,7 +5206,10 @@ block_variable_declaration
          {
                $$ = current_variable;
                current_variable = null;
-               lbag.AddLocation ($$, GetLocation ($6));
+               if ($4 != null)
+                       lbag.AddLocation ($$, PopLocation (), GetLocation ($6));
+               else
+                       lbag.AddLocation ($$, GetLocation ($6));
          }
        | CONST variable_type identifier_inside_body
          {
@@ -5137,7 +5231,8 @@ opt_local_variable_initializer
        | ASSIGN block_variable_initializer
          {
                current_variable.Initializer = (Expression) $2;
-               // TODO: lbag
+               PushLocation (GetLocation ($1));
+               $$ = current_variable;
          }
        | error
          {
@@ -5268,8 +5363,9 @@ statement_expression
          {
                ExpressionStatement s = $1 as ExpressionStatement;
                if (s == null) {
-                       Expression.Error_InvalidExpressionStatement (report, GetLocation ($1));
-                       $$ = new StatementErrorExpression ($1 as Expression);
+                       var expr = $1 as Expression;
+                       expr.Error_InvalidExpressionStatement (report);
+                       $$ = new StatementErrorExpression (expr);
                } else {
                        $$ = new StatementExpression (s);
                }
@@ -5334,7 +5430,7 @@ switch_statement
          }
          opt_switch_sections CLOSE_BRACE
          {
-               $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, (List<SwitchSection>) $7, GetLocation ($1));  
+               $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, GetLocation ($1));    
                end_block (GetLocation ($8));
                lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4));
          }
@@ -5342,7 +5438,7 @@ switch_statement
          {
                Error_SyntaxError (yyToken);
          
-               $$ = new Switch ((Expression) $3, null, null, GetLocation ($1));        
+               $$ = new Switch ((Expression) $3, null, GetLocation ($1));      
                lbag.AddStatement ($$, GetLocation ($2));
          }
        ;
@@ -5351,58 +5447,33 @@ opt_switch_sections
        : /* empty */           
       {
                report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); 
-               $$ = new List<SwitchSection> ();
          }
        | switch_sections
        ;
 
 switch_sections
        : switch_section 
-         {
-               var sections = new List<SwitchSection> (4);
-
-               sections.Add ((SwitchSection) $1);
-               $$ = sections;
-         }
        | switch_sections switch_section
-         {
-               var sections = (List<SwitchSection>) $1;
-
-               sections.Add ((SwitchSection) $2);
-               $$ = sections;
-         }
        | error
          {
                Error_SyntaxError (yyToken);
-               $$ = new List<SwitchSection> ();
          } 
        ;
 
 switch_section
-       : switch_labels
-         {
-               current_block = current_block.CreateSwitchBlock (lexer.Location);
-         }
-         statement_list 
-         {
-               $$ = new SwitchSection ((List<SwitchLabel>) $1, current_block);
-         }
+       : switch_labels statement_list 
        ;
 
 switch_labels
        : switch_label 
          {
-               var labels = new List<SwitchLabel> (2);
-
-               labels.Add ((SwitchLabel) $1);
-               $$ = labels;
+               var label = (SwitchLabel) $1;
+               label.SectionStart = true;
+               current_block.AddStatement (label);
          }
        | switch_labels switch_label 
          {
-               var labels = (List<SwitchLabel>) ($1);
-               labels.Add ((SwitchLabel) $2);
-
-               $$ = labels;
+               current_block.AddStatement ((Statement) $2);
          }
        ;
 
@@ -5568,6 +5639,9 @@ for_initializer
          opt_local_variable_initializer opt_variable_declarators
          {
                $$ = current_variable;
+               if ($4 != null)
+                       lbag.AddLocation (current_variable, PopLocation ());
+
                current_variable = null;
          }
        | statement_expression_list
@@ -5783,7 +5857,7 @@ yield_statement
                        FeatureIsNotAvailable (lt.Location, "iterators");
                }
                
-               current_block.Explicit.RegisterIteratorYield ();
+               current_block.ParametersBlock.TopBlock.IsIterator = true;
                $$ = new YieldBreak (lt.Location);
                lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3));
          }
@@ -6222,15 +6296,29 @@ select_or_group_clause
          
                current_block = new Linq.QueryBlock (current_block, lexer.Location);
          }
-         BY expression_or_error
+         by_expression
          {
-               $$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1));
-               lbag.AddLocation ($$, GetLocation ($5));
+               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
@@ -6743,7 +6831,7 @@ void Error_ExpectingTypeName (Expression expr)
        if (expr is Invocation){
                report.Error (1002, expr.Location, "Expecting `;'");
        } else {
-               Expression.Error_InvalidExpressionStatement (report, expr.Location);
+               expr.Error_InvalidExpressionStatement (report);
        }
 }
 
@@ -6784,6 +6872,16 @@ 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 Tokenizer.LocatedToken ("await", GetLocation (token));
+       }
+
+       return token;
+}
+
 void push_current_container (TypeDefinition tc, object partial_token)
 {
        if (module.Evaluator != null){
@@ -6826,6 +6924,23 @@ void StoreModifierLocation (object token, Location loc)
        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> ();
+
+       location_stack.Push (loc);
+}
+
+Location PopLocation ()
+{
+       if (location_stack == null)
+               return Location.Null;
+
+       return location_stack.Pop ();
+}
+
 string CheckAttributeTarget (string a, Location l)
 {
        switch (a) {
@@ -6913,7 +7028,8 @@ public void parse ()
                }
                        
                if (e is yyParser.yyException) {
-                       report.Error (-25, lexer.Location, "Parsing error");
+                       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)