[mono-api-html] Print string fields with no (or null) value without an NRE.
[mono.git] / mcs / mcs / cs-parser.jay
index 45b95d40aae601c8682f0b4b38fedb5dd082352e..97cfaaca0e8b225f0171d73bc31ad0d183b6a7f6 100644 (file)
@@ -35,7 +35,8 @@ namespace Mono.CSharp
                        Arglist = 1 << 5,
                        DefaultValue = 1 << 6,
                        
-                       All = Ref | Out | This | Params | Arglist | DefaultValue
+                       All = Ref | Out | This | Params | Arglist | DefaultValue,
+                       PrimaryConstructor = Ref | Out | Params | DefaultValue
                }
                
                static readonly object ModifierNone = 0;
@@ -116,6 +117,8 @@ namespace Mono.CSharp
                // Keeps track of global data changes to undo on parser error
                //
                public Undo undo;
+
+               bool? interactive_async;
                
                Stack<Linq.QueryBlock> linq_clause_blocks;
 
@@ -562,6 +565,7 @@ namespace_name
          {
                var lt = (LocatedToken) $3;
                $$ = new MemberName ((MemberName) $1, lt.Value, lt.Location);           
+               lbag.AddLocation ($$, GetLocation ($2));
          }
        | error
          {
@@ -736,7 +740,7 @@ attribute_section_cont
          }
        | error
          {
-               CheckAttributeTarget (GetTokenName (yyToken), GetLocation ($1)); 
+               CheckAttributeTarget (yyToken, GetTokenName (yyToken), GetLocation ($1)); 
                $$ = null;
          }
        ;       
@@ -745,7 +749,7 @@ attribute_target
        : IDENTIFIER
          {
                var lt = (LocatedToken) $1;
-               $$ = CheckAttributeTarget (lt.Value, lt.Location);
+               $$ = CheckAttributeTarget (yyToken, lt.Value, lt.Location);
          }
        | EVENT  { $$ = "event"; }
        | RETURN { $$ = "return"; }
@@ -901,10 +905,12 @@ 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;
          }
        ;
        
@@ -940,15 +946,21 @@ struct_declaration
          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 ($9 != null)
-                       current_container.SetConstraints ((List<Constraints>) $9);
+               if ($8 != null)
+                       current_type.PrimaryConstructorParameters = (ParametersCompiled) $8;
+
+               if ($10 != null)
+                       current_container.SetConstraints ((List<Constraints>) $10);
 
                if (doc_support)
                        current_container.PartialContainer.DocComment = Lexer.consume_doc_comment ();
@@ -970,7 +982,11 @@ struct_declaration
          }
          opt_semicolon
          {
-               lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($14), GetLocation ($16));
+               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
@@ -1138,6 +1154,7 @@ opt_field_initializer
          {
                --lexer.parsing_block;
                current_field.Initializer = (Expression) $3;
+               lbag.AppendToMember (current_field, GetLocation ($1));
                end_block (lexer.Location);
                current_local_parameters = null;
          }
@@ -1938,7 +1955,11 @@ interface_declaration
          }
          opt_semicolon 
          {
-           lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13));
+               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
@@ -1956,10 +1977,12 @@ 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;
          }
        ;
 
@@ -2589,6 +2612,8 @@ enum_declaration
          }
          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;
@@ -2921,7 +2946,7 @@ type_parameter
        : opt_attributes opt_type_parameter_variance IDENTIFIER
          {
                var lt = (LocatedToken)$3;
-               $$ = new TypeParameter (new MemberName (lt.Value, lt.Location), (Attributes)$1, (Variance) $2);
+               $$ = new TypeParameter (new MemberName (lt.Value, lt.Location), (Attributes)$1, (VarianceDecl) $2);
          }
        | error
          {
@@ -2930,7 +2955,7 @@ type_parameter
                else
                        Error_SyntaxError (yyToken);
                        
-               $$ = new TypeParameter (MemberName.Null, null, Variance.None);
+               $$ = new TypeParameter (MemberName.Null, null, null);
          }
        ;
 
@@ -3177,6 +3202,12 @@ member_access
                $$ = 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;
@@ -3300,14 +3331,17 @@ member_initializer
        | OPEN_BRACE expression_list CLOSE_BRACE
          {
                if ($2 == null)
-                       $$ = null;
+                       $$ = new CollectionElementInitializer (GetLocation ($1));
                else
                        $$ = new CollectionElementInitializer ((List<Expression>)$2, GetLocation ($1));
+
+               lbag.AddLocation ($$, GetLocation ($2));
          }
        | OPEN_BRACE CLOSE_BRACE
          {
                report.Error (1920, GetLocation ($1), "An element initializer cannot be empty");
-               $$ = null;
+               $$ = new CollectionElementInitializer (GetLocation ($1));
+               lbag.AddLocation ($$, GetLocation ($2));
          }
        ;
 
@@ -3923,9 +3957,12 @@ unary_expression
                         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 is AnonymousMethodExpression) {
+                       } 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");
@@ -4602,6 +4639,51 @@ boolean_expression
          }
        ;
 
+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));
+         }
+       ;
+
+opt_primary_parameters_with_class_base
+       : /* empty */
+         {
+               $$ = null;
+         }
+       | class_base
+         {
+               $$ = null;
+         }
+       | primary_parameters
+         {
+               $$ = $1;
+         }
+       | primary_parameters class_base OPEN_PARENS
+         {
+               ++lexer.parsing_block;
+         }
+         opt_argument_list CLOSE_PARENS
+         {
+               lbag.AppendToMember (current_container, GetLocation ($3), GetLocation ($6));
+               ((Class)current_type).PrimaryConstructorBaseArguments = (Arguments) $5;
+               --lexer.parsing_block;
+
+               $$ = $1;
+         }
+       ;
+
 //
 // 10 classes
 //
@@ -4622,12 +4704,17 @@ class_declaration
                }
                        
                push_current_container (c, $3);
+               valid_param_mod = ParameterModifierType.PrimaryConstructor;
          }
-         opt_class_base
+         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<Constraints>) $9);
                lbag.AddMember (current_container, mod_locations, GetLocation ($4));
@@ -4647,7 +4734,11 @@ class_declaration
          }
          opt_semicolon 
          {
-               lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13), GetLocation ($15));
+               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 ();
          }
        ;       
@@ -4777,7 +4868,11 @@ modifier
        
 opt_class_base
        : /* empty */
-       | COLON type_list
+       | class_base
+       ;
+
+class_base
+       : COLON type_list
         {
                current_type.SetBaseTypes ((List<FullNamedExpression>) $2);
         }
@@ -4896,7 +4991,7 @@ type_parameter_constraint
 opt_type_parameter_variance
        : /* empty */
          {
-               $$ = Variance.None;
+               $$ = null;
          }
        | type_parameter_variance
          {
@@ -4910,11 +5005,11 @@ opt_type_parameter_variance
 type_parameter_variance
        : OUT
          {
-               $$ = Variance.Covariant;
+               $$ = new VarianceDecl (Variance.Covariant, GetLocation ($1));
          }
        | IN
          {
-               $$ = Variance.Contravariant;
+               $$ = new VarianceDecl (Variance.Contravariant, GetLocation ($1));
          }
        ;
 
@@ -5377,10 +5472,7 @@ interactive_statement_expression
        : expression
          {
                Expression expr = (Expression) $1;
-               ExpressionStatement s;
-
-               s = new OptionalAssign (new SimpleName ("$retval", lexer.Location), expr, lexer.Location);
-               $$ = new StatementExpression (s);
+               $$ = new StatementExpression (new OptionalAssign (expr, lexer.Location));
          }
        | error
          {
@@ -5881,12 +5973,12 @@ try_statement
          }
        | TRY block FINALLY block
          {
-               $$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1));
+               $$ = 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<Catch>) $3, Location.Null, true), (Block) $5, GetLocation ($1));
+               $$ = new TryFinally (new TryCatch ((Block) $2, (List<Catch>) $3, Location.Null, true), (ExplicitBlock) $5, GetLocation ($1));
                lbag.AddStatement ($$, GetLocation ($4));
          }
        | TRY block error
@@ -5909,7 +6001,8 @@ catch_clauses
                var l = (List<Catch>) $1;
                
                Catch c = (Catch) $2;
-               if (l [l.Count - 1].IsGeneral) {
+               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");
                }
                
@@ -5924,14 +6017,16 @@ opt_identifier
        ;
 
 catch_clause 
-       : CATCH block
+       : CATCH opt_catch_filter block
          {
-               $$ = new Catch ((Block) $2, GetLocation ($1));
+               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 (current_block, GetLocation ($1));
+               var c = new Catch ((ExplicitBlock) current_block, GetLocation ($1));
                c.TypeExpression = (FullNamedExpression) $3;
 
                if ($4 != null) {
@@ -5943,8 +6038,9 @@ catch_clause
                lbag.AddLocation (c, GetLocation ($2), GetLocation ($5));
                $$ = c;
          }
-         block_prepared
+         opt_catch_filter block_prepared
          {
+               ((Catch) $6).Filter = (CatchFilterExpression) $7;
                $$ = $6;
          }
        | CATCH open_parens_any error
@@ -5978,6 +6074,18 @@ catch_clause
          }
        ;
 
+opt_catch_filter
+       : /* empty */
+       | IF open_parens_any expression CLOSE_PARENS
+         {
+               if (lang_version <= LanguageVersion.V_5)
+                       FeatureIsNotAvailable (GetLocation ($1), "exception filter");
+
+               $$ = new CatchFilterExpression ((Expression) $3, GetLocation ($1));
+               lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4));
+         }
+       ;
+
 checked_statement
        : CHECKED block
          {
@@ -6043,6 +6151,7 @@ fixed_statement
          
                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));
          }
        ;
@@ -6159,7 +6268,9 @@ first_from_clause
          
                var lt = (LocatedToken) $2;
                var rv = new Linq.RangeVariable (lt.Value, lt.Location);
-               $$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)));
+               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
          {
@@ -6167,11 +6278,11 @@ first_from_clause
          
                var lt = (LocatedToken) $3;
                var rv = new Linq.RangeVariable (lt.Value, lt.Location);
-               $$ = new Linq.QueryExpression (
-                       new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) {
+               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);
          }
        ;
 
@@ -6182,7 +6293,9 @@ nested_from_clause
          
                var lt = (LocatedToken) $2;
                var rv = new Linq.RangeVariable (lt.Value, lt.Location);
-               $$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)));
+               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
          {
@@ -6190,11 +6303,11 @@ nested_from_clause
          
                var lt = (LocatedToken) $3;
                var rv = new Linq.RangeVariable (lt.Value, lt.Location);
-               $$ = new Linq.QueryExpression (
-                       new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) {
+               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);
          }
        ;
        
@@ -6213,6 +6326,7 @@ from_clause
                current_block = current_block.Parent;
                
                ((Linq.QueryBlock)current_block).AddRangeVariable (sn);
+               lbag.AddLocation ($$, GetLocation ($3));
          }       
        | FROM type identifier_inside_body IN
          {
@@ -6231,6 +6345,8 @@ from_clause
                current_block = current_block.Parent;
                
                ((Linq.QueryBlock)current_block).AddRangeVariable (sn);
+               
+               lbag.AddLocation ($$, GetLocation ($4));
          }
        ;       
 
@@ -6480,6 +6596,7 @@ join_clause
                        $$ = 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
@@ -6653,27 +6770,30 @@ interactive_parsing
                        mods |= Modifiers.UNSAFE;
 
                current_local_parameters = pars;
-               Method method = new Method (
+               var method = new InteractiveMethod (
                        current_type,
                        new TypeExpression (compiler.BuiltinTypes.Void, Location.Null),
                        mods,
-                       new MemberName ("Host"),
-                       pars,
-                       null /* attributes */);
+                       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;
-               Method method = (Method) oob_stack.Pop ();
-
+               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;
          } 
@@ -6947,15 +7067,20 @@ Location PopLocation ()
        return location_stack.Pop ();
 }
 
-string CheckAttributeTarget (string a, Location l)
+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;
        }
 
-       report.Warning (658, 1, l,
-                "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", 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;
 }
 
@@ -7007,7 +7132,7 @@ public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Re
        lang_version = settings.Version;
        yacc_verbose_flag = settings.VerboseParserFlag;
        doc_support = settings.DocumentationFile != null;
-       lexer = new Tokenizer (reader, file, session);
+       lexer = new Tokenizer (reader, file, session, report);
        oob_stack = new Stack<object> ();
        lbag = session.LocationsBag;
        use_global_stacks = session.UseJayGlobalArrays;