Merge pull request #607 from maksimenko/master
[mono.git] / mcs / mcs / cs-parser.jay
index ca578594f32faa4add71dd01fbc983794a782ce4..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;
@@ -3147,7 +3213,13 @@ invocation_expression
                $$ = 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
@@ -3159,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
          {
@@ -3207,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));
@@ -3229,7 +3306,7 @@ member_initializer
          {
                report.Error (1920, GetLocation ($1), "An element initializer cannot be empty");
                $$ = null;
-         }       
+         }
        ;
 
 initializer_value
@@ -3345,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
@@ -3534,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),
@@ -3732,6 +3805,13 @@ sizeof_expression
                $$ = 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
@@ -3740,6 +3820,12 @@ checked_expression
                $$ = new CheckedExpr ((Expression) $3, GetLocation ($1));
                lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4));
          }
+       | CHECKED error
+         {
+               Error_SyntaxError (yyToken);
+
+               $$ = new CheckedExpr (null, GetLocation ($1));
+         }
        ;
 
 unchecked_expression
@@ -3748,6 +3834,12 @@ unchecked_expression
                $$ = 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
@@ -3842,6 +3934,31 @@ unary_expression
                
                $$ = 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));
+         }
        ;
 
        //
@@ -3874,6 +3991,42 @@ 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
@@ -3893,6 +4046,27 @@ multiplicative_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
@@ -3915,6 +4089,32 @@ additive_expression
          {
                $$ = new Is ((Expression) $1, (Expression) $3, 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 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));
+         }
        ;
 
 shift_expression
@@ -3929,6 +4129,20 @@ shift_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
@@ -3953,6 +4167,34 @@ relational_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
@@ -3967,6 +4209,20 @@ equality_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
@@ -3976,6 +4232,13 @@ and_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
@@ -3985,6 +4248,13 @@ exclusive_or_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
@@ -3994,6 +4264,13 @@ inclusive_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
@@ -4003,6 +4280,13 @@ conditional_and_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
@@ -4012,6 +4296,13 @@ conditional_or_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
@@ -4028,7 +4319,7 @@ null_coalescing_expression
 
 conditional_expression
        : null_coalescing_expression
-       | null_coalescing_expression INTERR expression COLON expression_or_error
+       | null_coalescing_expression INTERR expression COLON expression
          {
                $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2));
                lbag.AddLocation ($$, GetLocation ($4));
@@ -4036,8 +4327,24 @@ conditional_expression
        | 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
@@ -4137,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
@@ -4148,32 +4460,38 @@ opt_lambda_parameter_list
        ;
 
 lambda_expression_body
-       : lambda_expression_body_simple
-       | block
-       ;
-       
-lambda_expression_body_simple
        : {
                start_block (Location.Null);
          }
-         expression_or_error   // Have to close block when error occurs
+         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);    
-               $$ = EmptyExpression.Null;
+               Error_SyntaxError (yyToken);
+               $$ = null;
          }
        ;
-
+       
 lambda_expression
        : IDENTIFIER ARROW 
          {
@@ -4186,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;
@@ -4280,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");
@@ -4860,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);
          }
        ;
 
@@ -4879,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
          {
@@ -4901,7 +5231,8 @@ opt_local_variable_initializer
        | ASSIGN block_variable_initializer
          {
                current_variable.Initializer = (Expression) $2;
-               // TODO: lbag
+               PushLocation (GetLocation ($1));
+               $$ = current_variable;
          }
        | error
          {
@@ -5032,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);
                }
@@ -5098,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));
          }
@@ -5106,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));
          }
        ;
@@ -5115,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);
          }
        ;
 
@@ -5332,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
@@ -5547,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));
          }
@@ -5646,9 +5956,16 @@ catch_clause
          {
                Error_SyntaxError (yyToken);
 
+               // Required otherwise missing block could not be detected because
+               // start_block is run early
                var c = new Catch (null, GetLocation ($1));
                c.TypeExpression = (FullNamedExpression) $3;
 
+               if ($4 != null) {
+                       var lt = (Tokenizer.LocatedToken) $4;
+                       c.Variable = new LocalVariable (current_block, lt.Value, lt.Location);
+               }
+
                lbag.AddLocation (c, GetLocation ($2), GetLocation ($5));
 
                $$ = c;
@@ -5979,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
@@ -6500,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);
        }
 }
 
@@ -6541,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){
@@ -6583,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) {
@@ -6670,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)