* TypeDescriptor.cs: fixed properties order in returning collections in PropertyDescr...
[mono.git] / mcs / mcs / cs-parser.jay
index 112a809290a5794337025a432bb124e4ec79cfbd..a08eee0b7f2bade27d56445ad58aeb143c7c5abe 100644 (file)
@@ -45,7 +45,8 @@ namespace Mono.CSharp
                Block      current_block;
 
                Delegate   current_delegate;
-
+               
+               GenericMethod current_generic_method;
                AnonymousMethodExpression current_anonymous_method;
 
                /// <summary>
@@ -203,10 +204,25 @@ namespace Mono.CSharp
 %token VIRTUAL 
 %token VOID    
 %token VOLATILE
+%token WHERE
 %token WHILE   
 %token ARGLIST
 %token PARTIAL
 %token ARROW
+%token QUERY_FIRST_TOKEN
+%token FROM
+%token JOIN
+%token ON
+%token EQUALS
+%token SELECT
+%token GROUP
+%token BY
+%token LET
+%token ORDERBY
+%token ASCENDING
+%token DESCENDING
+%token INTO
+%token QUERY_LAST_TOKEN
 
 /* C# keywords which are not really keywords */
 %token GET           "get"
@@ -266,6 +282,7 @@ namespace Mono.CSharp
 %token OP_XOR_ASSIGN          "^="
 %token OP_OR_ASSIGN           "|="
 %token OP_PTR                 "->"
+%token OP_COALESCING          "??"
 
 /* Numbers */
 %token LITERAL_INTEGER           "int literal"
@@ -281,6 +298,9 @@ namespace Mono.CSharp
 %token CLOSE_PARENS_NO_CAST
 %token CLOSE_PARENS_OPEN_PARENS
 %token CLOSE_PARENS_MINUS
+%token DEFAULT_OPEN_PARENS
+%token GENERIC_DIMENSION
+%token DEFAULT_COLON
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc LOWPREC
@@ -404,6 +424,9 @@ namespace_declaration
                        Report.Error(1671, name.Location, "A namespace declaration cannot have modifiers or attributes");
                }
 
+               if (name.TypeArguments != null)
+                       syntax_error (lexer.Location, "namespace name expected");
+
                current_namespace = new NamespaceEntry (
                        current_namespace, file, name.GetName ());
                current_class = current_namespace.SlaveDeclSpace;
@@ -428,7 +451,14 @@ opt_comma
        ;
 
 namespace_name
-       : namespace_or_type_name
+       : namespace_or_type_name {
+               MemberName name = (MemberName) $1;
+
+               if (name.TypeArguments != null)
+                       syntax_error (lexer.Location, "namespace name expected");
+
+               $$ = name;
+         }
        ;
 
 namespace_body
@@ -674,7 +704,12 @@ attribute
        : attribute_name opt_attribute_arguments
          {
                MemberName mname = (MemberName) $1;
-               object[] arguments = (object[]) $2;
+               if (mname.IsGeneric) {
+                       Report.Error (404, lexer.Location,
+                                     "'<' unexpected: attributes cannot be generic");
+               }
+
+               object [] arguments = (object []) $2;
                MemberName left = mname.Left;
                string identifier = mname.Name;
 
@@ -813,6 +848,7 @@ struct_declaration
          opt_partial
          STRUCT
          {
+               lexer.ConstraintsParsing = true;
          }
          type_name
          { 
@@ -820,7 +856,12 @@ struct_declaration
                push_current_class (new Struct (current_namespace, current_class, name, (int) $2, (Attributes) $1), $3);
          }
          opt_class_base
+         opt_type_parameter_constraints_clauses
          {
+               lexer.ConstraintsParsing = false;
+
+               current_class.SetParameterInfo ((ArrayList) $9);
+
                if (RootContext.Documentation != null)
                        current_container.DocComment = Lexer.consume_doc_comment ();
          }
@@ -1100,6 +1141,7 @@ method_declaration
                current_container.AddMethod (method);
 
                anonymous_host = null;
+               current_generic_method = null;
                current_local_parameters = null;
 
                if (RootContext.Documentation != null)
@@ -1140,21 +1182,41 @@ open_parens
 method_header
        : opt_attributes
          opt_modifiers
-         type namespace_or_type_name
+         type member_name
          open_parens
          {
                arglist_allowed = true;
          }
-         opt_formal_parameter_list CLOSE_PARENS
+         opt_formal_parameter_list CLOSE_PARENS 
+         {
+               lexer.ConstraintsParsing = true;
+         }
+         opt_type_parameter_constraints_clauses
          {
+               lexer.ConstraintsParsing = false;
                arglist_allowed = false;
                MemberName name = (MemberName) $4;
                current_local_parameters = (Parameters) $7;
 
-               Method method = new Method (current_class, null, (Expression) $3, (int) $2,
-                                           false, name, current_local_parameters, (Attributes) $1);
+               if ($10 != null && name.TypeArguments == null)
+                       Report.Error (80, lexer.Location,
+                                     "Constraints are not allowed on non-generic declarations");
+
+               Method method;
+
+               GenericMethod generic = null;
+               if (name.TypeArguments != null) {
+                       generic = new GenericMethod (current_namespace, current_class, name,
+                                                    (Expression) $3, current_local_parameters);
+
+                       generic.SetParameterInfo ((ArrayList) $10);
+               }
+
+               method = new Method (current_class, generic, (Expression) $3, (int) $2, false,
+                                    name, current_local_parameters, (Attributes) $1);
 
                anonymous_host = method;
+               current_generic_method = generic;
 
                if (RootContext.Documentation != null)
                        method.DocComment = Lexer.consume_doc_comment ();
@@ -1163,23 +1225,99 @@ method_header
          }
        | opt_attributes
          opt_modifiers
-         VOID namespace_or_type_name
+         VOID member_name
          open_parens
          {
                arglist_allowed = true;
          }       
-         opt_formal_parameter_list CLOSE_PARENS 
+         opt_formal_parameter_list CLOSE_PARENS
+         {
+               lexer.ConstraintsParsing = true;
+         }
+         opt_type_parameter_constraints_clauses
          {
+               lexer.ConstraintsParsing = false;
                arglist_allowed = false;
-         
+
                MemberName name = (MemberName) $4;
                current_local_parameters = (Parameters) $7;
 
-               Method method = new Method (current_class, null, TypeManager.system_void_expr,
-                                           (int) $2, false, name, current_local_parameters,
-                                           (Attributes) $1);
+               if ($10 != null && name.TypeArguments == null)
+                       Report.Error (80, lexer.Location,
+                                     "Constraints are not allowed on non-generic declarations");
+
+               Method method;
+               GenericMethod generic = null;
+               if (name.TypeArguments != null) {
+                       generic = new GenericMethod (current_namespace, current_class, name,
+                                                    TypeManager.system_void_expr, current_local_parameters);
+
+                       generic.SetParameterInfo ((ArrayList) $10);
+               }
+
+               method = new Method (current_class, generic, TypeManager.system_void_expr,
+                                    (int) $2, false, name, current_local_parameters, (Attributes) $1);
+
+               anonymous_host = method;
+               current_generic_method = generic;
+
+               if (RootContext.Documentation != null)
+                       method.DocComment = Lexer.consume_doc_comment ();
+
+               $$ = method;
+       }
+       | opt_attributes
+         opt_modifiers
+         PARTIAL
+         VOID member_name
+         open_parens opt_formal_parameter_list CLOSE_PARENS 
+         {
+               lexer.ConstraintsParsing = true;
+         }
+         opt_type_parameter_constraints_clauses
+         {
+               lexer.ConstraintsParsing = false;
+
+               MemberName name = (MemberName) $5;
+               current_local_parameters = (Parameters) $7;
+
+               if ($9 != null && name.TypeArguments == null)
+                       Report.Error (80, lexer.Location,
+                                     "Constraints are not allowed on non-generic declarations");
+
+               Method method;
+               GenericMethod generic = null;
+               if (name.TypeArguments != null) {
+                       generic = new GenericMethod (current_namespace, current_class, name,
+                                                    TypeManager.system_void_expr, current_local_parameters);
+
+                       generic.SetParameterInfo ((ArrayList) $10);
+               }
+
+               int modifiers = (int) $2;
+
+
+               const int invalid_partial_mod = Modifiers.Accessibility | Modifiers.ABSTRACT | Modifiers.EXTERN |
+                       Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
+
+               if ((modifiers & invalid_partial_mod) != 0) {
+                       Report.Error (750, name.Location, "A partial method cannot define access modifier or " +
+                               "any of abstract, extern, new, override, sealed, or virtual modifiers");
+                       modifiers &= ~invalid_partial_mod;
+               }
+
+               if ((current_class.ModFlags & Modifiers.PARTIAL) == 0) {
+                       Report.Error (751, name.Location, "A partial method must be declared within a " +
+                               "partial class or partial struct");
+               }
+
+               modifiers |= Modifiers.PARTIAL | Modifiers.PRIVATE;
+               
+               method = new Method (current_class, generic, TypeManager.system_void_expr,
+                                    modifiers, false, name, current_local_parameters, (Attributes) $1);
 
                anonymous_host = method;
+               current_generic_method = generic;
 
                if (RootContext.Documentation != null)
                        method.DocComment = Lexer.consume_doc_comment ();
@@ -1189,7 +1327,7 @@ method_header
        | opt_attributes
          opt_modifiers
          type 
-         modifiers namespace_or_type_name open_parens opt_formal_parameter_list CLOSE_PARENS
+         modifiers member_name open_parens opt_formal_parameter_list CLOSE_PARENS
          {
                MemberName name = (MemberName) $5;
                Report.Error (1585, name.Location, 
@@ -1303,8 +1441,12 @@ fixed_parameters
        | fixed_parameters COMMA fixed_parameter
          {
                ArrayList pars = (ArrayList) $1;
-
-               pars.Add ($3);
+               Parameter p = (Parameter)$3;
+               if (p != null) {
+                       if ((p.modFlags & Parameter.Modifier.This) != 0)
+                               Report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter");
+                       pars.Add (p);
+               }
                $$ = $1;
          }
        ;
@@ -1371,7 +1513,17 @@ parameter_modifiers
                if (((Parameter.Modifier)$1 & p2) == p2) {
                        Error_DuplicateParameterModifier (lexer.Location, p2);
                } else {
-                       Report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier");
+                       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;
          }
@@ -1396,6 +1548,9 @@ parameter_modifier
          {
                if (parameter_modifiers_not_allowed)
                        Error_ParameterModifierNotValid ("this", (Location)$1);
+
+               if (RootContext.Version <= LanguageVersion.ISO_2)
+                       Report.FeatureIsNotAvailable (GetLocation ($1), "extension methods");
                                
                $$ = Parameter.Modifier.This;
          }
@@ -1474,9 +1629,12 @@ property_declaration
 
                MemberName name = (MemberName) $4;
 
-               prop = new Property (current_class, (Expression) $3, (int) $2,
-                       false, name, (Attributes) $1, get_block, set_block, accessors.declared_in_reverse);
-               
+               if (name.TypeArguments != null)
+                       syntax_error (lexer.Location, "a property can't have type arguments");
+
+               prop = new Property (current_class, (Expression) $3, (int) $2, false,
+                                    name, (Attributes) $1, get_block, set_block, accessors.declared_in_reverse, current_block);
+
                current_container.AddProperty (prop);
                implicit_value_parameter_type = null;
 
@@ -1614,6 +1772,7 @@ interface_declaration
          opt_partial
          INTERFACE
          {
+               lexer.ConstraintsParsing = true;
          }
          type_name
          {
@@ -1621,7 +1780,12 @@ interface_declaration
                push_current_class (new Interface (current_namespace, current_class, name, (int) $2, (Attributes) $1), $3);
          }
          opt_class_base
+         opt_type_parameter_constraints_clauses
          {
+               lexer.ConstraintsParsing = false;
+
+               current_class.SetParameterInfo ((ArrayList) $9);
+
                if (RootContext.Documentation != null) {
                        current_container.DocComment = Lexer.consume_doc_comment ();
                        Lexer.doc_state = XmlCommentState.Allowed;
@@ -1771,25 +1935,89 @@ opt_new
          }
        ;
 
+interface_method_declaration_body
+       : OPEN_BRACE 
+         {
+               Report.Error (531, (Location)$1,
+                             "`{0}.{1}{2}': interface members cannot have a definition",
+                             current_class.GetSignatureForError (),
+                             ((MemberName) $-0).ToString (),
+                             ((Parameters)$-4).GetSignatureForError ());
+         
+               lexer.ConstraintsParsing = false;
+         }
+         opt_statement_list CLOSE_BRACE
+         {
+               $$ = null;
+         }
+       | SEMICOLON
+       ;
+
 interface_method_declaration
        : opt_attributes opt_new type namespace_or_type_name
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
-         SEMICOLON
+         open_parens opt_formal_parameter_list CLOSE_PARENS
+         {
+               lexer.ConstraintsParsing = true;
+         }
+         opt_type_parameter_constraints_clauses
+         {
+               // Refer to the name as $-1 in interface_method_declaration_body          
+               $$ = $4;
+         }
+         interface_method_declaration_body
          {
-               $$ = new Method (current_class, null, (Expression) $3, (int) $2, true,
-                                (MemberName) $4, (Parameters) $6, (Attributes) $1);
+               lexer.ConstraintsParsing = false;
+
+               MemberName name = (MemberName) $4;
+
+               if ($9 != null && name.TypeArguments == null)
+                       Report.Error (80, lexer.Location,
+                                     "Constraints are not allowed on non-generic declarations");
+
+               GenericMethod generic = null;
+               if (name.TypeArguments != null) {
+                       generic = new GenericMethod (current_namespace, current_class, name,
+                                                    (Expression) $3, (Parameters) $6);
+
+                       generic.SetParameterInfo ((ArrayList) $9);
+               }
+
+               $$ = new Method (current_class, generic, (Expression) $3, (int) $2, true, name,
+                                (Parameters) $6, (Attributes) $1);
                if (RootContext.Documentation != null)
                        ((Method) $$).DocComment = Lexer.consume_doc_comment ();
          }
-       | opt_attributes opt_new type namespace_or_type_name
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
-         OPEN_BRACE opt_statement_list CLOSE_BRACE
+       | opt_attributes opt_new VOID namespace_or_type_name
+         open_parens opt_formal_parameter_list CLOSE_PARENS
+         {
+               lexer.ConstraintsParsing = true;
+         }
+         opt_type_parameter_constraints_clauses
+         {
+               $$ = $4;
+         }
+         interface_method_declaration_body
          {
-               $$ = new Method (current_class, null, (Expression) $3, (int) $2, true,
-                                (MemberName) $4, (Parameters) $6, (Attributes) $1);
+               lexer.ConstraintsParsing = false;
+
+               MemberName name = (MemberName) $4;
+
+               if ($9 != null && name.TypeArguments == null)
+                       Report.Error (80, lexer.Location,
+                                     "Constraints are not allowed on non-generic declarations");
+
+               GenericMethod generic = null;
+               if (name.TypeArguments != null) {
+                       generic = new GenericMethod (current_namespace, current_class, name,
+                                                    TypeManager.system_void_expr, (Parameters) $6);
+
+                       generic.SetParameterInfo ((ArrayList) $9);
+               }
 
-               Report.Error (531, lexer.Location, "`{0}': interface members cannot have a definition",
-                       ((Method)$$).GetSignatureForError ());
+               $$ = new Method (current_class, generic, TypeManager.system_void_expr, (int) $2,
+                                true, name, (Parameters) $6, (Attributes) $1);
+               if (RootContext.Documentation != null)
+                       ((Method) $$).DocComment = Lexer.consume_doc_comment ();
          }
        ;
 
@@ -2221,7 +2449,7 @@ destructor_declaration
          IDENTIFIER OPEN_PARENS CLOSE_PARENS block
          {
                LocatedToken lt = (LocatedToken) $5;
-               if (lt.Value != current_container.Basename){
+               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 != Kind.Class){
                        Report.Error (575, lt.Location, "Only class types can contain destructor");
@@ -2293,6 +2521,10 @@ event_declaration
                        $$ = null;
                } else {
                        Accessors accessors = (Accessors) $8;
+                       
+                       if (name.TypeArguments != null)
+                               syntax_error (lexer.Location, "an event can't have type arguments");
+
                        if (accessors.get_or_add == null || accessors.set_or_remove == null)
                                // CS0073 is already reported, so no CS0065 here.
                                $$ = null;
@@ -2616,15 +2848,13 @@ delegate_declaration
        : opt_attributes
          opt_modifiers
          DELEGATE
-         {
-         }
          type type_name
          open_parens opt_formal_parameter_list CLOSE_PARENS
          {
-               MemberName name = MakeName ((MemberName) $6);
-               Parameters p = (Parameters) $8;
+               MemberName name = MakeName ((MemberName) $5);
+               Parameters p = (Parameters) $7;
 
-               Delegate del = new Delegate (current_namespace, current_class, (Expression) $5,
+               Delegate del = new Delegate (current_namespace, current_class, (Expression) $4,
                                             (int) $2, name, p, (Attributes) $1);
 
                if (RootContext.Documentation != null) {
@@ -2634,39 +2864,137 @@ delegate_declaration
 
                current_container.AddDelegate (del);
                current_delegate = del;
+               lexer.ConstraintsParsing = true;
+         }
+         opt_type_parameter_constraints_clauses
+         {
+               lexer.ConstraintsParsing = false;
          }
          SEMICOLON
          {
+               current_delegate.SetParameterInfo ((ArrayList) $10);
                $$ = current_delegate;
 
                current_delegate = null;
          }
        ;
 
+opt_nullable
+       : /* empty */
+         {
+               lexer.CheckNullable (false);
+               $$ = false;
+         }
+       | INTERR
+         {
+               // FIXME: A hack with parsing conditional operator as nullable type
+               //if (RootContext.Version < LanguageVersion.ISO_2)
+               //      Report.FeatureIsNotAvailable (lexer.Location, "nullable types");
+                       
+               lexer.CheckNullable (true);
+               $$ = true;
+         }
+       ;
+
 namespace_or_type_name
-       : member_name
-       | IDENTIFIER DOUBLE_COLON IDENTIFIER {
+       : IDENTIFIER opt_type_argument_list
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               $$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location);
+         }
+       | IDENTIFIER DOUBLE_COLON IDENTIFIER opt_type_argument_list {
                LocatedToken lt1 = (LocatedToken) $1;
                LocatedToken lt2 = (LocatedToken) $3;
-               $$ = new MemberName (lt1.Value, lt2.Value, null, lt2.Location);
+               $$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $4, lt2.Location);
          }
-       | namespace_or_type_name DOT IDENTIFIER {
+       | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list {
                LocatedToken lt = (LocatedToken) $3;
-               $$ = new MemberName ((MemberName) $1, lt.Value);
+               $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location);
          }
        ;
 
 member_name
-       : IDENTIFIER {
+       : IDENTIFIER opt_type_parameter_list
+         {
                LocatedToken lt = (LocatedToken) $1;
-               $$ = new MemberName (lt.Value, lt.Location);
+               $$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location);
+         }
+       | namespace_or_type_name DOT IDENTIFIER opt_type_parameter_list 
+         {
+               LocatedToken lt = (LocatedToken) $3;
+               $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location);
          }
        ;
 
 type_name
-       : member_name
+       : IDENTIFIER opt_type_parameter_list
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               $$ = new MemberName (lt.Value, (TypeArguments)$2, lt.Location);   
+         }
        ;
 
+//
+// Generics arguments  (any type, without attributes)
+//
+
+opt_type_argument_list
+       : /* empty */                { $$ = null; } 
+       | OP_GENERICS_LT type_arguments OP_GENERICS_GT
+         {
+               if (RootContext.Version < LanguageVersion.ISO_2)
+                       Report.FeatureIsNotAvailable (GetLocation ($1), "generics");      
+         
+               $$ = $2;
+         }
+       ;
+
+//
+// Generics parameters (identifiers only, with attributes), used in type, method declarations
+//
+
+opt_type_parameter_list
+       : /* empty */                { $$ = null; } 
+       | OP_GENERICS_LT type_arguments OP_GENERICS_GT
+         {
+               if (RootContext.Version < LanguageVersion.ISO_2)
+                       Report.FeatureIsNotAvailable (GetLocation ($1), "generics");
+         
+               $$ = $2;
+         }
+       ;
+
+type_arguments
+       : type_argument
+         {
+               TypeArguments type_args = new TypeArguments (lexer.Location);
+               type_args.Add ((Expression) $1);
+               $$ = type_args;
+         }
+       | type_arguments COMMA type_argument
+         {
+               TypeArguments type_args = (TypeArguments) $1;
+               type_args.Add ((Expression) $3);
+               $$ = type_args;
+         }       
+       ;
+
+type_argument
+       : type
+         {
+               $$ = $1;
+         }
+       | attribute_sections type
+         {
+               SimpleName sn = $2 as SimpleName;
+               if (sn == null)
+                       Error_TypeExpected (GetLocation ($2));
+               else
+                       $2 = new TypeParameterName (sn.Name, (Attributes) $1, lexer.Location);
+               $$ = $2;          
+         }
+       ;
+       
 /* 
  * Before you think of adding a return_type, notice that we have been
  * using two rules in the places where it matters (one rule using type
@@ -2674,17 +3002,28 @@ type_name
  * gets rid of a shift/reduce couple
  */
 type
-       : namespace_or_type_name
+       : namespace_or_type_name opt_nullable
          {
                MemberName name = (MemberName) $1;
-               $$ = name.GetTypeExpression ();
+
+               if ((bool) $2) {
+                       $$ = new ComposedCast (name.GetTypeExpression (), "?", lexer.Location);
+               } else {
+                       if (RootContext.Version > LanguageVersion.ISO_2 && name.Name == "var")
+                               $$ = new VarExpr (name.Location);
+                       else
+                               $$ = name.GetTypeExpression ();
+               }
+         }
+       | builtin_types opt_nullable
+         {
+               if ((bool) $2)
+                       $$ = new ComposedCast ((Expression) $1, "?", lexer.Location);
          }
-       | builtin_types
        | array_type
-       | pointer_type    
+       | pointer_type
        ;
 
-
 pointer_type
        : type STAR
          {
@@ -2702,7 +3041,11 @@ pointer_type
        ;
 
 non_expression_type
-       : builtin_types 
+       : builtin_types opt_nullable
+         {
+               if ((bool) $2)
+                       $$ = new ComposedCast ((Expression) $1, "?", lexer.Location);
+         }
        | non_expression_type rank_specifier
          {
                Location loc = GetLocation ($1);
@@ -2781,9 +3124,13 @@ integral_type
        ;
 
 array_type
-       : type rank_specifiers
+       : type rank_specifiers opt_nullable
          {
-               $$ = current_array_type = new ComposedCast ((Expression) $1, (string) $2);
+               string rank_specifiers = (string) $2;
+               if ((bool) $3)
+                       rank_specifiers += "?";
+
+               $$ = current_array_type = new ComposedCast ((Expression) $1, rank_specifiers);
          }
        ;
 
@@ -2795,7 +3142,7 @@ primary_expression
          {
                // 7.5.1: Literals
          }
-       | member_name
+       | type_name
          {
                MemberName mn = (MemberName) $1;
                $$ = mn.GetTypeExpression ();
@@ -2807,6 +3154,7 @@ primary_expression
                $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, lt2.Location);
          }
        | parenthesized_expression
+       | default_value_expression
        | member_access
        | invocation_expression
        | element_access
@@ -2891,16 +3239,16 @@ parenthesized_expression
        ;
 
 member_access
-       : primary_expression DOT IDENTIFIER
+       : primary_expression DOT IDENTIFIER opt_type_argument_list
          {
                LocatedToken lt = (LocatedToken) $3;
-               $$ = new MemberAccess ((Expression) $1, lt.Value);
+               $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
          }
-       | predefined_type DOT IDENTIFIER
+       | predefined_type DOT IDENTIFIER opt_type_argument_list
          {
                LocatedToken lt = (LocatedToken) $3;
                // TODO: Location is wrong as some predefined types doesn't hold a location
-               $$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location);
+               $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
          }
        ;
 
@@ -2938,6 +3286,73 @@ invocation_expression
          }
        ;
 
+opt_object_or_collection_initializer
+       : /* empty */           { $$ = null; }
+       | object_or_collection_initializer
+       ;
+
+object_or_collection_initializer
+       : OPEN_BRACE opt_member_initializer_list CLOSE_BRACE
+         {
+               if ($2 == null)
+                 $$ = CollectionOrObjectInitializers.Empty;
+               else
+                 $$ = new CollectionOrObjectInitializers ((ArrayList) $2, GetLocation ($1));
+         }
+       | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE
+         {
+               $$ = new CollectionOrObjectInitializers ((ArrayList) $2, GetLocation ($1));
+         }
+       ;
+
+opt_member_initializer_list
+       : /* empty */           { $$ = null; }
+       | member_initializer_list
+       {
+               $$ = $1;
+       }
+       ;
+
+member_initializer_list
+       : member_initializer
+         {
+               ArrayList a = new ArrayList ();
+               a.Add ($1);
+               $$ = a;
+         }
+       | member_initializer_list COMMA member_initializer
+         {
+               ArrayList a = (ArrayList)$1;
+               a.Add ($3);
+               $$ = a;
+         }
+       ;
+
+member_initializer
+       : IDENTIFIER ASSIGN initializer_value
+         {
+               LocatedToken lt = $1 as LocatedToken;
+               $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location);
+         }
+       | non_assignment_expression
+         {
+               $$ = new CollectionElementInitializer ((Expression)$1);
+         }
+       | OPEN_BRACE expression_list CLOSE_BRACE
+         {
+               $$ = new CollectionElementInitializer ((ArrayList)$2, GetLocation ($1));
+         }
+       | OPEN_BRACE CLOSE_BRACE
+         {
+               Report.Error (1920, GetLocation ($1), "An element initializer cannot be empty");
+         }       
+       ;
+
+initializer_value
+       : expression
+       | object_or_collection_initializer
+       ;
+
 opt_argument_list
        : /* empty */           { $$ = null; }
        | argument_list
@@ -3022,7 +3437,7 @@ element_access
                Expression expr = (Expression) $1;  
                if (expr is ComposedCast){
                        $$ = new ComposedCast (expr, (string) $2);
-               } else if (!(expr is SimpleName || expr is MemberAccess || expr is QualifiedAliasMember)){
+               } else if (!(expr is SimpleName || expr is MemberAccess || expr is ConstructedType || expr is QualifiedAliasMember)){
                        Error_ExpectingTypeName (expr);
                        $$ = TypeManager.system_object_expr;
                } else {
@@ -3059,10 +3474,10 @@ this_access
        ;
 
 base_access
-       : BASE DOT IDENTIFIER
+       : BASE DOT IDENTIFIER opt_type_argument_list
          {
                LocatedToken lt = (LocatedToken) $3;
-               $$ = new BaseAccess (lt.Value, lt.Location);
+               $$ = new BaseAccess (lt.Value, (TypeArguments) $4, lt.Location);
          }
        | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
          {
@@ -3093,12 +3508,27 @@ post_decrement_expression
 new_expression
        : object_or_delegate_creation_expression
        | array_creation_expression
+       | anonymous_type_expression
        ;
 
 object_or_delegate_creation_expression
-       : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+       : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer
+         {
+               if ($6 != null) {
+                       if (RootContext.Version <= LanguageVersion.ISO_2)
+                               Report.FeatureIsNotAvailable (GetLocation ($1), "object initializers");
+                               
+                       $$ = new NewInitialize ((Expression) $2, (ArrayList) $4, (CollectionOrObjectInitializers) $6, (Location) $1);
+               }
+               else
+                       $$ = new New ((Expression) $2, (ArrayList) $4, (Location) $1);
+         }
+       | NEW type object_or_collection_initializer
          {
-               $$ = new New ((Expression) $2, (ArrayList) $4, (Location) $1);
+               if (RootContext.Version <= LanguageVersion.ISO_2)
+                       Report.FeatureIsNotAvailable (GetLocation ($1), "collection initializers");
+         
+               $$ = new NewInitialize ((Expression) $2, null, (CollectionOrObjectInitializers) $3, (Location) $1);
          }
        ;
 
@@ -3113,6 +3543,10 @@ array_creation_expression
          {
                $$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, (Location) $1);
          }
+       | NEW rank_specifiers array_initializer
+         {
+               $$ = new ImplicitlyTypedArrayCreation ((string) $2, (ArrayList) $3, (Location) $1);
+         }
        | NEW error
          {
                Report.Error (1031, (Location) $1, "Type expected");
@@ -3125,6 +3559,56 @@ array_creation_expression
          }
        ;
 
+anonymous_type_expression
+       : NEW OPEN_BRACE anonymous_type_parameters CLOSE_BRACE
+         {
+               if (RootContext.Version <= LanguageVersion.ISO_2)
+                       Report.FeatureIsNotAvailable (GetLocation ($1), "anonymous types");
+
+               $$ = new AnonymousTypeDeclaration ((ArrayList) $3, current_container, GetLocation ($1));
+         }
+       ;
+
+anonymous_type_parameters
+       : { $$ = null; }
+       | anonymous_type_parameter
+         {
+               ArrayList a = new ArrayList (4);
+               a.Add ($1);
+               $$ = a;
+         }
+       | anonymous_type_parameters COMMA anonymous_type_parameter
+         {
+               ArrayList a = (ArrayList) $1;
+               a.Add ($3);
+               $$ = a;
+         }
+       ;
+
+anonymous_type_parameter
+       : IDENTIFIER ASSIGN variable_initializer
+         {
+               LocatedToken lt = (LocatedToken)$1;
+               $$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location);
+         }
+       | IDENTIFIER
+         {
+               LocatedToken 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.Identifier, 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");
+         }
+       ;
+
 opt_rank_specifier
        : /* empty */
          {
@@ -3136,6 +3620,31 @@ opt_rank_specifier
          }
        ;
 
+opt_rank_specifier_or_nullable
+       : /* empty */
+         {
+               $$ = "";
+         }
+       | INTERR
+         {
+               $$ = "?";
+         }
+       | opt_nullable rank_specifiers
+         {
+               if ((bool) $1)
+                       $$ = "?" + $2;
+               else
+                       $$ = $2;
+         }
+       | opt_nullable rank_specifiers INTERR
+         {
+               if ((bool) $1)
+                       $$ = "?" + $2 + "?";
+               else
+                       $$ = $2 + "?";
+         }
+       ;
+
 rank_specifiers
        : rank_specifier opt_rank_specifier
          {
@@ -3214,9 +3723,11 @@ typeof_expression
        : TYPEOF
       {
                pushed_current_array_type = current_array_type;
+               lexer.TypeOfParsing = true;
          }
-         OPEN_PARENS type CLOSE_PARENS
+         OPEN_PARENS typeof_type_expression CLOSE_PARENS
          {
+               lexer.TypeOfParsing = false;
                Expression type = (Expression)$4;
                if (type == TypeManager.system_void_expr)
                        $$ = new TypeOfVoid ((Location) $1);
@@ -3225,13 +3736,61 @@ typeof_expression
                current_array_type = pushed_current_array_type;
          }
        ;
+       
+typeof_type_expression
+       : type
+         {
+               $$ = $1;
+         }
+       | unbound_type_name
+         {
+               $$ = new UnboundTypeExpression ((MemberName)$1, lexer.Location);
+         }
+       ;
+       
+unbound_type_name
+       : IDENTIFIER GENERIC_DIMENSION
+         {
+               if (RootContext.Version < LanguageVersion.ISO_1)
+                       Report.FeatureIsNotAvailable (lexer.Location, "generics");
+         
+               LocatedToken lt = (LocatedToken) $1;
+               TypeArguments ta = new TypeArguments ((int)$2, lt.Location);
+
+               $$ = new MemberName (lt.Value, ta, lt.Location);
+         }
+       | IDENTIFIER DOUBLE_COLON IDENTIFIER GENERIC_DIMENSION
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               MemberName left = new MemberName (lt.Value, lt.Location);
+               lt = (LocatedToken) $3;
+               TypeArguments ta = new TypeArguments ((int)$4, lt.Location);
+               
+               $$ = new MemberName (left, lt.Value, ta, lt.Location);
+         }
+       | unbound_type_name DOT IDENTIFIER GENERIC_DIMENSION
+         {
+               LocatedToken lt = (LocatedToken) $3;
+               TypeArguments ta = new TypeArguments ((int)$4, lt.Location);
+               
+               $$ = new MemberName ((MemberName)$1, lt.Value, ta, lt.Location);
+         }
+       | namespace_or_type_name DOT IDENTIFIER GENERIC_DIMENSION
+         {
+               LocatedToken lt = (LocatedToken) $3;
+               TypeArguments ta = new TypeArguments ((int)$4, lt.Location);
+               
+               $$ = new MemberName ((MemberName)$1, lt.Value, ta, lt.Location);
+         }
+       ;
+
+
+sizeof_expression
+       : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
+               $$ = new SizeOf ((Expression) $3, (Location) $1);
+         }
+       ;
 
-sizeof_expression
-       : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
-               $$ = new SizeOf ((Expression) $3, (Location) $1);
-         }
-       ;
-
 checked_expression
        : CHECKED OPEN_PARENS expression CLOSE_PARENS
          {
@@ -3265,7 +3824,7 @@ anonymous_method_expression
          block
          {
                $$ = end_anonymous ((ToplevelBlock) $4, (Location) $1);
-         }
+       }
        ;
 
 opt_anonymous_method_signature
@@ -3285,6 +3844,16 @@ anonymous_method_signature
          }
        ;
 
+default_value_expression
+       : DEFAULT_OPEN_PARENS type CLOSE_PARENS
+         {
+               if (RootContext.Version < LanguageVersion.ISO_2)
+                       Report.FeatureIsNotAvailable (lexer.Location, "default value expression");
+
+               $$ = new DefaultValueExpression ((Expression) $2, lexer.Location);
+         }
+       ;
+
 unary_expression
        : primary_expression
        | BANG prefixed_unary_expression
@@ -3303,6 +3872,10 @@ cast_list
          {
                $$ = new Cast ((Expression) $1, (Expression) $3);
          }
+       | parenthesized_expression_0 CLOSE_PARENS_NO_CAST default_value_expression
+         {
+               $$ = new Cast ((Expression) $1, (Expression) $3);
+         }
        | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
          {
                $$ = new Cast ((Expression) $1, (Expression) $3);
@@ -3352,22 +3925,6 @@ prefixed_unary_expression
          }
        ;
 
-pre_increment_expression
-       : OP_INC prefixed_unary_expression 
-         {
-               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
-                                      (Expression) $2, (Location) $1);
-         }
-       ;
-
-pre_decrement_expression
-       : OP_DEC prefixed_unary_expression 
-         {
-               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
-                                      (Expression) $2, (Location) $1);
-         }
-       ;
-
 multiplicative_expression
        : prefixed_unary_expression
        | multiplicative_expression STAR prefixed_unary_expression
@@ -3415,6 +3972,28 @@ shift_expression
          }
        ; 
 
+opt_error
+       : /* empty */
+         {
+               $$ = false;
+         }
+       | error
+         {
+               lexer.PutbackNullable ();
+               $$ = true;
+         }
+       ;
+
+nullable_type_or_conditional
+       : type opt_error
+         {
+               if (((bool) $2) && ($1 is ComposedCast))
+                       $$ = ((ComposedCast) $1).RemoveNullable ();
+               else
+                       $$ = $1;
+         }
+       ;
+
 relational_expression
        : shift_expression
        | relational_expression OP_LT shift_expression
@@ -3437,13 +4016,19 @@ relational_expression
                $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
                                 (Expression) $1, (Expression) $3);
          }
-       | relational_expression IS type
+       | relational_expression IS
          {
-               $$ = new Is ((Expression) $1, (Expression) $3, (Location) $2);
+               yyErrorFlag = 3;
+         } nullable_type_or_conditional
+         {
+               $$ = new Is ((Expression) $1, (Expression) $4, (Location) $2);
          }
-       | relational_expression AS type
+       | relational_expression AS
+         {
+               yyErrorFlag = 3;
+         } nullable_type_or_conditional
          {
-               $$ = new As ((Expression) $1, (Expression) $3, (Location) $2);
+               $$ = new As ((Expression) $1, (Expression) $4, (Location) $2);
          }
        ;
 
@@ -3512,6 +4097,16 @@ conditional_expression
          {
                $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
          }
+       | conditional_or_expression OP_COALESCING expression
+         {
+               $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3, lexer.Location);
+         }
+       // We'll be resolved into a `parenthesized_expression_0' later on.
+       | conditional_or_expression INTERR CLOSE_PARENS
+         {
+               $$ = new ComposedCast ((Expression) $1, "?", lexer.Location);
+               lexer.PutbackCloseParens ();
+         }
        ;
 
 assignment_expression
@@ -3571,40 +4166,28 @@ assignment_expression
          }
        ;
 
-implicitly_typed_lambda_parameter_list
-       : IDENTIFIER { 
-               LocatedToken lt = (LocatedToken) $1;
-               ArrayList a = new ArrayList (4); 
-
-               a.Add (new Parameter ((Expression)null, lt.Value, Parameter.Modifier.NONE, null, lt.Location));
-               $$ = a;
-         } 
-       | implicitly_typed_lambda_parameter_list COMMA IDENTIFIER {
-               LocatedToken lt = (LocatedToken) $3;
-               ArrayList a = (ArrayList) $1;
-               a.Add (new Parameter ((Expression)null, lt.Value, Parameter.Modifier.NONE, null, lt.Location));
-               $$ = a;
-         }
-       ;
-
-explicitly_typed_lambda_parameter_list
-       : explicitly_typed_lambda_parameter
+lambda_parameter_list
+       : lambda_parameter
          {
                ArrayList pars = new ArrayList (4);
                pars.Add ($1);
 
                $$ = pars;
          }
-       | explicitly_typed_lambda_parameter_list COMMA explicitly_typed_lambda_parameter
+       | lambda_parameter_list COMMA lambda_parameter
          {
                ArrayList pars = (ArrayList) $1;
-               pars.Add ($3);
-
+               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;
          }
        ;
 
-explicitly_typed_lambda_parameter
+lambda_parameter
        : parameter_modifier type IDENTIFIER
          {
                LocatedToken lt = (LocatedToken) $3;
@@ -3617,21 +4200,18 @@ explicitly_typed_lambda_parameter
 
                $$ = new Parameter ((Expression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
          }
-       ;
-
-lambda_parameter_list
-       : implicitly_typed_lambda_parameter_list { $$ = $1; }
-       | explicitly_typed_lambda_parameter_list { $$ = $1; }
+       | IDENTIFIER
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               $$ = new ImplicitLambdaParameter (lt.Value, lt.Location);
+         }
        ;
 
 opt_lambda_parameter_list
-       : /* empty */                   { $$ = null; }
+       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
        | lambda_parameter_list         { 
                ArrayList pars_list = (ArrayList) $1;
-
-               Parameter [] pars = new Parameter [pars_list.Count];
-               pars_list.CopyTo (pars);
-               $$ = new Parameters (pars);
+               $$ = new Parameters ((Parameter[])pars_list.ToArray (typeof (Parameter)));
          }
        ;
 
@@ -3653,13 +4233,9 @@ lambda_expression_body
 lambda_expression
        : IDENTIFIER ARROW 
          {
-               Parameter [] pars = new Parameter [1];
                LocatedToken lt = (LocatedToken) $1;
-               pars [0] = new Parameter ((Expression)null, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
-
-               Parameters parameters = new Parameters (pars);
-
-               start_anonymous (true, parameters, (Location) $2);
+               Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location);
+               start_anonymous (true, new Parameters (p), (Location) $2);
          }
          lambda_expression_body
          {
@@ -3676,9 +4252,14 @@ lambda_expression
        ;
 
 expression
+       : assignment_expression
+       | non_assignment_expression
+       ;
+       
+non_assignment_expression
        : conditional_expression
-       | assignment_expression
        | lambda_expression
+       | query_expression
        ;
 
 constant_expression
@@ -3698,6 +4279,7 @@ class_declaration
          opt_partial
          CLASS
          {
+               lexer.ConstraintsParsing = true;
          }
          type_name
          {
@@ -3705,7 +4287,12 @@ class_declaration
                push_current_class (new Class (current_namespace, current_class, name, (int) $2, (Attributes) $1), $3);
          }
          opt_class_base
+         opt_type_parameter_constraints_clauses
          {
+               lexer.ConstraintsParsing = false;
+
+               current_class.SetParameterInfo ((ArrayList) $9);
+
                if (RootContext.Documentation != null) {
                        current_container.DocComment = Lexer.consume_doc_comment ();
                        Lexer.doc_state = XmlCommentState.Allowed;
@@ -3775,6 +4362,68 @@ class_base
        : COLON type_list       { current_container.AddBasesForPart (current_class, (ArrayList) $2); }
        ;
 
+opt_type_parameter_constraints_clauses
+       : /* empty */           { $$ = null; }
+       | type_parameter_constraints_clauses 
+         { $$ = $1; }
+       ;
+
+type_parameter_constraints_clauses
+       : type_parameter_constraints_clause {
+               ArrayList constraints = new ArrayList (1);
+               constraints.Add ($1);
+               $$ = constraints;
+         }
+       | type_parameter_constraints_clauses type_parameter_constraints_clause {
+               ArrayList constraints = (ArrayList) $1;
+               Constraints new_constraint = (Constraints)$2;
+
+               foreach (Constraints c in constraints) {
+                       if (new_constraint.TypeParameter == c.TypeParameter) {
+                               Report.Error (409, new_constraint.Location, "A constraint clause has already been specified for type parameter `{0}'",
+                                       new_constraint.TypeParameter);
+                       }
+               }
+
+               constraints.Add (new_constraint);
+               $$ = constraints;
+         }
+       ; 
+
+type_parameter_constraints_clause
+       : WHERE IDENTIFIER COLON type_parameter_constraints {
+               LocatedToken lt = (LocatedToken) $2;
+               $$ = new Constraints (lt.Value, (ArrayList) $4, lt.Location);
+         }
+       ; 
+
+type_parameter_constraints
+       : type_parameter_constraint {
+               ArrayList constraints = new ArrayList (1);
+               constraints.Add ($1);
+               $$ = constraints;
+         }
+       | type_parameter_constraints COMMA type_parameter_constraint {
+               ArrayList constraints = (ArrayList) $1;
+
+               constraints.Add ($3);
+               $$ = constraints;
+         }
+       ;
+
+type_parameter_constraint
+       : type
+       | NEW OPEN_PARENS CLOSE_PARENS {
+               $$ = SpecialConstraint.Constructor;
+         }
+       | CLASS {
+               $$ = SpecialConstraint.ReferenceType;
+         }
+       | STRUCT {
+               $$ = SpecialConstraint.ValueType;
+         }
+       ;
+
 //
 // Statements (8.2)
 //
@@ -3917,7 +4566,7 @@ declaration_statement
  * > The expressions are converted into types during semantic analysis.
  */
 local_variable_type
-       : primary_expression opt_rank_specifier
+       : primary_expression opt_rank_specifier_or_nullable
          { 
                // FIXME: Do something smart here regarding the composition of the type.
 
@@ -3935,8 +4584,9 @@ local_variable_type
                // SimpleName is when you have
                // Blah i;
                  
-               Expression expr = (Expression) $1;  
-               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is QualifiedAliasMember)) {
+               Expression expr = (Expression) $1;
+               SimpleName sn = expr as SimpleName;
+               if (!(sn != null || expr is MemberAccess || expr is ComposedCast || expr is ConstructedType || expr is QualifiedAliasMember)) {
                        Error_ExpectingTypeName (expr);
                        $$ = null;
                } else {
@@ -3945,13 +4595,16 @@ local_variable_type
                        // or MemberAccess
                        // 
 
-                       if ((string) $2 == "")
-                               $$ = $1;
-                       else
+                       if ((string) $2 == "") {
+                               if (sn != null && RootContext.Version > LanguageVersion.ISO_2 && sn.Name == "var")
+                                       $$ = new VarExpr (sn.Location);
+                               else
+                                       $$ = $1;
+                       } else
                                $$ = new ComposedCast ((Expression) $1, (string) $2);
                }
          }
-       | builtin_types opt_rank_specifier
+       | builtin_types opt_rank_specifier_or_nullable
          {
                if ((string) $2 == "")
                        $$ = $1;
@@ -3965,7 +4618,7 @@ local_variable_pointer_type
          {
                Expression expr = (Expression) $1;  
 
-               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is QualifiedAliasMember)) {
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is ConstructedType || expr is QualifiedAliasMember)) {
                        Error_ExpectingTypeName (expr);
 
                        $$ = null;
@@ -3989,12 +4642,16 @@ local_variable_pointer_type
 local_variable_declaration
        : local_variable_type variable_declarators
          {
-               if ($1 != null)
+               if ($1 != null) {
+                       VarExpr ve = $1 as VarExpr;
+                       if (ve != null)
+                               ve.VariableInitializer = (ArrayList)$2;
+                               
                        $$ = new DictionaryEntry ($1, $2);
-               else
+               else
                        $$ = null;
          }
-        | local_variable_pointer_type opt_rank_specifier variable_declarators
+       | local_variable_pointer_type opt_rank_specifier_or_nullable variable_declarators
          {
                if ($1 != null){
                        Expression t;
@@ -4158,7 +4815,7 @@ switch_labels
 
 switch_label
        : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, (Location) $1); }
-       | DEFAULT COLON                         { $$ = new SwitchLabel (null, (Location) $1); }
+       | DEFAULT_COLON                         { $$ = new SwitchLabel (null, (Location) $1); }
        | error {
                Report.Error (
                        1523, GetLocation ($1), 
@@ -4724,6 +5381,262 @@ resource_acquisition
        | expression
        ;
 
+
+// LINQ
+
+query_expression
+       : first_from_clause
+         {
+               ++lexer.query_parsing;
+         }
+         query_body
+         {
+               if (--lexer.query_parsing == 1)
+                       lexer.query_parsing = 0;
+                       
+               Linq.AQueryClause from = $1 as Linq.AQueryClause;
+                       
+               from.Tail.Next = (Linq.AQueryClause)$3;
+               $$ = from;
+               
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         }     
+       ;
+       
+first_from_clause
+       : FROM IDENTIFIER IN expression
+         {
+               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
+               LocatedToken lt = (LocatedToken) $2;
+               
+               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance, lt.Value, lt.Location);
+               $$ = new Linq.QueryExpression (lt, new Linq.QueryStartClause ((Expression)$4));
+         }
+       | FROM type IDENTIFIER IN expression
+         {
+               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
+               LocatedToken lt = (LocatedToken) $3;
+
+               Expression type = (Expression)$2;
+               current_block.AddVariable (type, lt.Value, lt.Location);
+               $$ = new Linq.QueryExpression (lt, new Linq.Cast (type, (Expression)$5));
+         }
+       ;
+       
+from_clause
+       : FROM IDENTIFIER IN expression
+         {
+               LocatedToken lt = (LocatedToken) $2;
+               
+               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
+                       lt.Value, lt.Location);
+                       
+               $$ = new Linq.SelectMany (lt, (Expression)$4);                  
+         }
+       | FROM type IDENTIFIER IN expression
+         {
+               LocatedToken lt = (LocatedToken) $3;
+
+               Expression type = (Expression)$2;
+               current_block.AddVariable (type, lt.Value, lt.Location);
+               $$ = new Linq.SelectMany (lt, new Linq.Cast (type, (Expression)$5));
+         }
+       ;       
+
+query_body
+       : opt_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
+       : SELECT expression
+         {
+               $$ = new Linq.Select ((Expression)$2, GetLocation ($1));
+         }
+       | GROUP expression BY expression
+         {
+           $$ = new Linq.GroupBy ((Expression)$2, (Expression)$4, GetLocation ($1));
+         }
+       ;
+       
+opt_query_body_clauses
+       : /* empty */
+       | query_body_clauses
+       ;
+       
+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 ASSIGN expression
+         {
+               LocatedToken lt = (LocatedToken) $2;
+               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
+                       lt.Value, lt.Location);   
+               $$ = new Linq.Let (lt, (Expression)$4, GetLocation ($1));
+         }
+       ;
+
+where_clause
+       : WHERE boolean_expression
+         {
+               $$ = new Linq.Where ((Expression)$2, GetLocation ($1));
+         }
+       ;
+       
+join_clause
+       : JOIN IDENTIFIER IN expression ON expression EQUALS expression opt_join_into
+         {
+               Location loc = GetLocation ($1);
+               LocatedToken lt = (LocatedToken) $2;
+               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
+                       lt.Value, lt.Location);
+               
+               if ($9 == null) {
+                       $$ = new Linq.Join (lt, (Expression)$4, (Expression)$6,
+                               (Expression)$8, loc);
+               } else {
+                       LocatedToken lt_into = (LocatedToken) $9;
+                       $$ = new Linq.GroupJoin (lt, (Expression)$4, (Expression)$6,
+                               (Expression)$8, lt_into, loc);
+               }
+         }
+       | JOIN type IDENTIFIER IN expression ON expression EQUALS expression opt_join_into
+         {
+               Location loc = GetLocation ($1);
+               LocatedToken lt = (LocatedToken) $3;
+               current_block.AddVariable ((Expression)$2, lt.Value, lt.Location);
+               
+               Linq.Cast cast = new Linq.Cast ((Expression)$2, (Expression)$5);
+               if ($10 == null) {
+                       $$ = new Linq.Join (lt, cast, (Expression)$7,
+                               (Expression)$9, loc);
+               } else {
+                       LocatedToken lt_into = (LocatedToken) $10;
+                       $$ = new Linq.GroupJoin (lt, cast, (Expression)$7,
+                               (Expression)$9, lt_into, loc);
+               }
+         }
+       ;
+       
+opt_join_into
+       : /* empty */
+       | INTO IDENTIFIER
+         {
+               $$ = $2;
+         }
+       ;
+       
+orderby_clause
+       : ORDERBY orderings
+         {
+               $$ = $2;
+         }
+       ;
+       
+orderings
+       : order_by
+       | order_by COMMA orderings_then_by
+         {
+               ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$3;
+               $$ = $1;
+         }
+       ;
+       
+orderings_then_by
+       : then_by
+         {
+               $$ = $1;
+         }
+       | orderings_then_by COMMA then_by
+         {
+               ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$3;
+               $$ = $1;
+         }
+       ;       
+       
+order_by
+       : expression
+         {
+               $$ = new Linq.OrderByAscending ((Expression)$1);        
+         }
+       | expression ASCENDING
+         {
+               $$ = new Linq.OrderByAscending ((Expression)$1);        
+         }
+       | expression DESCENDING
+         {
+               $$ = new Linq.OrderByDescending ((Expression)$1);       
+         }
+       ;
+
+then_by
+       : expression
+         {
+               $$ = new Linq.ThenByAscending ((Expression)$1); 
+         }
+       | expression ASCENDING
+         {
+               $$ = new Linq.ThenByAscending ((Expression)$1); 
+         }
+       | expression DESCENDING
+         {
+               $$ = new Linq.ThenByDescending ((Expression)$1);        
+         }     
+       ;
+
+
+opt_query_continuation
+       : /* empty */
+       | INTO IDENTIFIER
+         {
+               // 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, GetLocation ($1));
+               
+               LocatedToken lt = (LocatedToken) $2;
+               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
+                       lt.Value, lt.Location);
+         }
+         query_body
+         {
+               $$ = new Linq.QueryExpression ((LocatedToken) $2,
+                       (Linq.AQueryClause)$4);
+         }
+       ;
+       
 %%
 
 // <summary>
@@ -4740,9 +5653,6 @@ public class VariableDeclaration {
        {
                this.identifier = lt.Value;
                if (eoai is ArrayList) {
-                       if (CSharpParser.current_array_type == null)
-                               Report.Error (622, lt.Location,
-                                       "Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
                        this.expression_or_array_initializer = new ArrayCreation (CSharpParser.current_array_type, "", (ArrayList)eoai, lt.Location);
                } else {
                        this.expression_or_array_initializer = (Expression)eoai;
@@ -4850,6 +5760,11 @@ static void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier m
                Parameter.GetModifierSignature (mod));
 }
 
+static void Error_TypeExpected (Location loc)
+{
+       Report.Error (1031, loc, "Type expected");
+}
+
 void push_current_class (TypeContainer tc, object partial_token)
 {
        if (partial_token != null)
@@ -5080,8 +5995,6 @@ Location GetLocation (object obj)
        return lexer.Location;
 }
 
-static GenericMethod current_generic_method = null;
-
 void start_block (Location loc)
 {
        if (current_block == null || parsing_anonymous_method) {