Fix typos.
[mono.git] / mcs / mcs / cs-parser.jay
index 56d46534556e6f554a5f0ba17bc6616773e65a27..23d58af14cb72a40ba42504cb661ebd739210d3e 100755 (executable)
@@ -1,8 +1,14 @@
 %{
 //
+// OPTIMIZATION:
+//   This loop is pointless:
+//    while (current_block != prev_block)
+//       current_block = current_block.Parent;
+//
 // cs-parser.jay: The Parser for the C# compiler
 //
 // Author: Miguel de Icaza (miguel@gnu.org)
+//         Ravi Pratap     (ravi@ximian.com)
 //
 // Licensed under the terms of the GNU GPL
 //
 //      separate problem
 //
 using System.Text;
-using CIR;
 using System;
 
-namespace CIR
+namespace Mono.CSharp
 {
        using System.Collections;
        using Mono.Languages;
@@ -61,10 +66,11 @@ namespace CIR
 
                // <summary>
                //   Using during property parsing to describe the implicit
-               //   value parameter that is passed to the "set" accesor
-               //   method
+               //   value parameter that is passed to the "set" and "get"accesor
+               //   methods (properties and indexers).
                // </summary>
-               Parameter [] implicit_value_parameters;
+               string     implicit_value_parameter_type;
+               Parameters indexer_parameters;
 
                // <summary>
                //   Used to determine if we are parsing the get/set pair
@@ -72,13 +78,10 @@ namespace CIR
                // </summmary>
                bool  parsing_indexer;
 
-               // <summary>
-               //   Used to record all types defined
-               // </summary>
-               Tree tree;
-
-               RootContext rc; 
-
+               //
+               // An out-of-band stack.
+               //
+               Stack oob_stack;
 %}
 
 %token EOF
@@ -92,6 +95,7 @@ namespace CIR
 %token ABSTRACT        
 %token AS
 %token ADD
+%token ASSEMBLY
 %token BASE    
 %token BOOL    
 %token BREAK   
@@ -148,6 +152,7 @@ namespace CIR
 %token SEALED  
 %token SHORT   
 %token SIZEOF  
+%token STACKALLOC
 %token STATIC  
 %token STRING  
 %token STRUCT  
@@ -165,6 +170,7 @@ namespace CIR
 %token USING   
 %token VIRTUAL 
 %token VOID    
+%token VOLATILE
 %token WHILE   
 
 /* C# keywords which are not really keywords */
@@ -251,16 +257,29 @@ namespace CIR
 %nonassoc HIGHPREC
 
 %start compilation_unit
-/*%start namespace_declaration */
 %%
 
 compilation_unit
-       : opt_using_directives opt_attributes opt_namespace_member_declarations EOF
-         {
-               // Check that using comes only before namespace elements
-         }
+        : outer_declarations opt_EOF
+        | outer_declarations attribute_sections opt_EOF
+        | attribute_sections opt_EOF
+        ;
+       
+opt_EOF
+       : /* empty */
+       | EOF
        ;
 
+outer_declarations
+        : outer_declaration
+        | outer_declarations outer_declaration
+        ;
+outer_declaration
+        : using_directive
+        | namespace_member_declaration
+        ;
+  
 using_directives
        : using_directive 
        | using_directives using_directive
@@ -275,7 +294,7 @@ using_alias_directive
        : USING IDENTIFIER ASSIGN 
          namespace_or_type_name SEMICOLON
          {
-                 // FIXME : Need to implement actual action.
+                 current_namespace.UsingAlias ((string) $2, (string) $4, lexer.Location);
          }
        ;
 
@@ -286,16 +305,24 @@ using_namespace_directive
           }
        ;
 
-//  namespace_declarations
-//     : namespace_declaration
-//     | namespace_declarations namespace_declaration
-
+//
+// Strictly speaking, namespaces don't have attributes but
+// we parse global attributes along with namespace declarations and then
+// detach them
+// 
 namespace_declaration
-       : NAMESPACE qualified_identifier 
-         {
-               current_namespace = new Namespace (current_namespace, (string) $2);
-               tree.RecordNamespace ((string) $2, current_namespace);
-         } 
+       : opt_attributes NAMESPACE qualified_identifier 
+       {
+               Attributes attrs = (Attributes) $1;
+
+               if (attrs != null) {
+                       foreach (AttributeSection asec in attrs.AttributeSections)
+                               if (asec.Target == "assembly")
+                                       RootContext.AddGlobalAttribute (asec, lexer.Location);
+               }
+
+               current_namespace = RootContext.Tree.RecordNamespace (current_namespace, name, (string) $3);
+       } 
          namespace_body opt_semicolon
          { 
                current_namespace = current_namespace.Parent;
@@ -350,8 +377,8 @@ namespace_member_declarations
 namespace_member_declaration
        : type_declaration
          {
-               int mod_flags = 0;
                string name = "";
+               int mod_flags;
 
                if ($1 is Class){
                        Class c = (Class) $1;
@@ -364,12 +391,12 @@ namespace_member_declaration
                } else
                        break;
 
-               //
-               // We remove this error until we can 
-               //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
-               //      error (1527, "Namespace elements cant be explicitly " +
-               //                   "declared private or protected in `" + name + "'");
-               //}
+               if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
+                       Report.Error (
+                               1527, lexer.Location, 
+                               "Namespace elements cant be explicitly " +
+                               "declared private or protected in `" + name + "'");
+               }
          }
        | namespace_declaration
        ;
@@ -379,23 +406,46 @@ type_declaration
        | struct_declaration            
        | interface_declaration         
        | enum_declaration              
-       | delegate_declaration         
+       | delegate_declaration
+//
+// Enable this when we have handled all errors, because this acts as a generic fallback
+//
+//     | error {
+//             Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
+//       }
        ;
 
 //
 // Attributes 17.2
 //
+
 opt_attributes
-       : /* empty */ { $$ = null; }
-       | attribute_section opt_attributes
+        : /* empty */
+       | attribute_sections { $$ = $1; }
+        ;
+attribute_sections
+       : attribute_section
+          {
+               AttributeSection sect = (AttributeSection) $1;
+
+               if (sect.Target == "assembly")
+                       RootContext.AddGlobalAttribute (sect, lexer.Location);
+                 
+               $$ = new Attributes ((AttributeSection) $1, lexer.Location);
+          }
+       | attribute_sections attribute_section
          {
-               Attributes attrs;
-               
-               if ($2 != null) {
-                       attrs = (Attributes) $2;
-                       attrs.AddAttribute ((Attribute) $1);
-               } else
-                       attrs = new Attributes ((Attribute) $1);
+               Attributes attrs = null;
+               AttributeSection sect = (AttributeSection) $2;
+
+               if (sect.Target == "assembly")
+                       RootContext.AddGlobalAttribute (sect, lexer.Location);
+
+               if ($1 != null) {
+                       attrs = (Attributes) $1;
+                       attrs.AddAttribute (sect);
+               }
                
                $$ = attrs;
          }
@@ -409,11 +459,11 @@ attribute_section
                if ($2 != null)
                        target = (string) $2;
                
-               $$ = new Attribute (target, (ArrayList) $3);
+               $$ = new AttributeSection (target, (ArrayList) $3);
          }
         | OPEN_BRACKET attribute_list CLOSE_BRACKET
          {
-               $$ = new Attribute (null, (ArrayList) $2);
+               $$ = new AttributeSection (null, (ArrayList) $2);
          }
        ;
  
@@ -453,9 +503,13 @@ attribute_list
        ;
 
 attribute
-       : attribute_name opt_attribute_arguments
+       : attribute_name
          {
-               $$ = new DictionaryEntry ($1, $2);
+               $$ = lexer.Location;
+         }
+         opt_attribute_arguments
+         {
+               $$ = new Attribute ((string) $1, (ArrayList) $3, (Location) $2);
          }
        ;
 
@@ -471,24 +525,87 @@ opt_attribute_arguments
          }
        ;
 
+
 attribute_arguments
-       : expression
+       : opt_positional_argument_list
+         {
+               if ($1 == null)
+                       $$ = null;
+               else {
+                       ArrayList args = new ArrayList ();
+                       args.Add ($1);
+               
+                       $$ = args;
+               }
+         }
+        | positional_argument_list COMMA named_argument_list
          {
                ArrayList args = new ArrayList ();
                args.Add ($1);
+               args.Add ($3);
+
+               $$ = args;
+         }
+        | named_argument_list
+         {
+               ArrayList args = new ArrayList ();
+               args.Add (null);
+               args.Add ($1);
                
                $$ = args;
          }
-       | attribute_arguments COMMA expression
+        ;
+
+
+opt_positional_argument_list
+       : /* empty */           { $$ = null; } 
+       | positional_argument_list
+       ;
+
+positional_argument_list
+       : expression
+         {
+               ArrayList args = new ArrayList ();
+               args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
+
+               $$ = args;
+         }
+        | positional_argument_list COMMA expression
+        {
+               ArrayList args = (ArrayList) $1;
+               args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
+
+               $$ = args;
+        }
+        ;
+
+named_argument_list
+       : named_argument
          {
+               ArrayList args = new ArrayList ();
+               args.Add ($1);
+
+               $$ = args;
+         }
+        | named_argument_list COMMA named_argument
+         {       
                ArrayList args = (ArrayList) $1;
                args.Add ($3);
 
                $$ = args;
          }
-       ;
+        ;
 
+named_argument
+       : IDENTIFIER ASSIGN expression
+         {
+               $$ = new DictionaryEntry (
+                       (string) $1, 
+                       new Argument ((Expression) $3, Argument.AType.Expression));
+         }
+       ;
 
+                 
 class_body
        :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
        ;
@@ -525,11 +642,11 @@ struct_declaration
                Struct new_struct;
                string full_struct_name = MakeName ((string) $4);
 
-               new_struct = new Struct (rc, current_container, full_struct_name, (int) $2, 
+               new_struct = new Struct (current_container, full_struct_name, (int) $2, 
                                         (Attributes) $1, lexer.Location);
                current_container = new_struct;
                current_container.Namespace = current_namespace;
-               tree.RecordStruct (full_struct_name, new_struct);
+               RootContext.Tree.RecordDecl (full_struct_name, new_struct);
          }
          opt_struct_interfaces
          struct_body
@@ -538,7 +655,7 @@ struct_declaration
                Struct new_struct = (Struct) current_container;
 
                current_container = current_container.Parent;
-               CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
+               CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
                $$ = new_struct;
          }
        ;
@@ -581,6 +698,12 @@ struct_member_declaration
        | operator_declaration
        | constructor_declaration
        | type_declaration
+
+       /*
+        * This is only included so we can flag error 575: 
+        * destructors only allowed on class types
+        */
+       | destructor_declaration 
        ;
 
 constant_declaration
@@ -591,12 +714,15 @@ constant_declaration
          constant_declarators
          SEMICOLON
          {
-               foreach (DictionaryEntry constant in (ArrayList) $5){
-                       Constant c = new Constant (
-                               (string) $4, (string) constant.Key, 
-                               (Expression) constant.Value, (int) $2, (Attributes) $1);
+               foreach (VariableDeclaration constant in (ArrayList) $5){
+                       Location l = constant.Location;
+
+                       Const c = new Const (
+                               (string) $4, (string) constant.identifier, 
+                               (Expression) constant.expression_or_array_initializer, (int) $2, 
+                               (Attributes) $1, l);
 
-                       CheckDef (current_container.AddConstant (c), c.Name);
+                       CheckDef (current_container.AddConstant (c), c.Name, l);
                }
          }
        ;
@@ -619,7 +745,7 @@ constant_declarators
 constant_declarator
        : IDENTIFIER ASSIGN constant_expression
          {
-               $$ = new DictionaryEntry ($1, $3);
+               $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
          }
        ;
 
@@ -629,18 +755,20 @@ field_declaration
          type 
          variable_declarators
          SEMICOLON
-       { 
+         
                string type = (string) $3;
                int mod = (int) $2;
 
                foreach (VariableDeclaration var in (ArrayList) $4){
+                       Location l = var.Location;
+
                        Field field = new Field (type, mod, var.identifier, 
-                                                var.expression_or_array_initializer, (Attributes) $1);
+                                                var.expression_or_array_initializer, 
+                                                (Attributes) $1, l);
 
-                       CheckDef (current_container.AddField (field), field.Name);
+                       CheckDef (current_container.AddField (field), field.Name, l);
                }
-       }
-
+         }
        ;
 
 variable_declarators
@@ -675,9 +803,13 @@ variable_initializer
                $$ = $1;
          }
        | array_initializer
-       {
+         {
                $$ = $1;
-       }
+         }
+       | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
+         {
+               $$ = new StackAlloc ((string) $2, (Expression) $4, lexer.Location);
+         }
        ;
 
 method_declaration
@@ -686,23 +818,48 @@ method_declaration
          {
                Method method = (Method) $1;
                Block b = (Block) $2;
-               
+               const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
+
                if (b == null){
-                       if ((method.ModFlags & (Modifiers.EXTERN | Modifiers.ABSTRACT)) == 0){
+                       if ((method.ModFlags & extern_abstract) == 0){
                                Report.Error (
-                                       501, lexer.Location, "`" + 
-                                       current_container.Name + "." + method.Name + "'" +
+                                       501, lexer.Location,  current_container.MakeName (method.Name) +
                                        "must declare a body because it is not marked abstract or extern");
                        }
+               } else {
+                       if ((method.ModFlags & Modifiers.EXTERN) != 0){
+                               Report.Error (
+                                       179, lexer.Location, current_container.MakeName (method.Name) +
+                                       " is declared extern, but has a body");
+                       }
                }
 
                method.Block = (Block) $2;
-               CheckDef (current_container.AddMethod (method), method.Name);
+               CheckDef (current_container.AddMethod (method), method.Name, method.Location);
 
                current_local_parameters = null;
          }
        ;
 
+opt_error_modifier
+       : /* empty */
+       | modifiers 
+         {
+               int m = (int) $1;
+               int i = 1;
+
+               while (m != 0){
+                       if ((i & m) != 0){
+                               Report.Error (
+                                       1585, lexer.Location, "Member modifier `" + 
+                                       Modifiers.Name (i) + "' must precede member type and name");
+                       }
+                       m &= ~i;
+                       i = i << 1;
+               }
+         }
+       ;
+
 method_header
        : opt_attributes
          opt_modifiers
@@ -737,7 +894,7 @@ method_body
        ;
 
 opt_formal_parameter_list
-       : /* empty */                   { $$ = new Parameters (null, null); }
+       : /* empty */                   { $$ = Parameters.GetEmptyReadOnlyParameters (); }
        | formal_parameter_list
        ;
 
@@ -749,7 +906,7 @@ formal_parameter_list
                Parameter [] pars = new Parameter [pars_list.Count];
                pars_list.CopyTo (pars);
 
-               $$ = new Parameters (pars, null); 
+               $$ = new Parameters (pars, null, lexer.Location); 
          } 
        | fixed_parameters COMMA parameter_array
          {
@@ -758,11 +915,11 @@ formal_parameter_list
                Parameter [] pars = new Parameter [pars_list.Count];
                pars_list.CopyTo (pars);
 
-               $$ = new Parameters (pars, (Parameter) $3); 
+               $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
          }
        | parameter_array 
          {
-               $$ = new Parameters (null, (Parameter) $1);
+               $$ = new Parameters (null, (Parameter) $1, lexer.Location);
          }
        ;
 
@@ -812,8 +969,7 @@ parameter_array
        ;
 
 member_name 
-       : IDENTIFIER { $$ = $1.ToString (); }
-       | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
+       : qualified_identifier
        ;
 
 property_declaration
@@ -822,45 +978,45 @@ property_declaration
          type member_name
          OPEN_BRACE 
          {
-               Parameter implicit_value_parameter;
-               implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE, null);
+               implicit_value_parameter_type = (string) $3;
 
-               lexer.properties = true;
-               
-               implicit_value_parameters = new Parameter [1];
-               implicit_value_parameters [0] = implicit_value_parameter;
+               lexer.PropertyParsing = true;
+
+               $$ = lexer.Location;
          }
          accessor_declarations 
          {
-               lexer.properties = false;
+               lexer.PropertyParsing = false;
          }
          CLOSE_BRACE
          { 
                Property prop;
-               DictionaryEntry pair = (DictionaryEntry) $7;
+               Pair pair = (Pair) $7;
                Block get_block = null;
                Block set_block = null;
 
-               if (pair.Key != null)
-                       get_block = (Block) pair.Key;
-               if (pair.Value != null)
-                       set_block = (Block) pair.Value;
+               if (pair.First != null)
+                       get_block = (Block) pair.First;
+               if (pair.Second != null)
+                       set_block = (Block) pair.Second;
 
-               prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block, (Attributes) $1);
+               Location loc = (Location) $6;
+               prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block,
+                                    (Attributes) $1, loc);
                
-               CheckDef (current_container.AddProperty (prop), prop.Name);
-               implicit_value_parameters = null;
+               CheckDef (current_container.AddProperty (prop), prop.Name, loc);
+               implicit_value_parameter_type = null;
          }
        ;
 
 accessor_declarations
        : get_accessor_declaration opt_set_accessor_declaration
          { 
-               $$ = new DictionaryEntry ($1, $2);
+               $$ = new Pair ($1, $2);
          }
        | set_accessor_declaration opt_get_accessor_declaration
          {
-               $$ = new DictionaryEntry ($2, $1);
+               $$ = new Pair ($2, $1);
          }
        ;
 
@@ -879,34 +1035,55 @@ get_accessor_declaration
          {
                // If this is not the case, then current_local_parameters has already
                // been set in indexer_declaration
-                 if (parsing_indexer == false)
-                         current_local_parameters = new Parameters (implicit_value_parameters, null);
-
-               
+               if (parsing_indexer == false)
+                       current_local_parameters = null;
+               else 
+                       current_local_parameters = indexer_parameters;
+               lexer.PropertyParsing = false;
          }
           accessor_body
          {
                $$ = $4;
                current_local_parameters = null;
+               lexer.PropertyParsing = true;
          }
        ;
 
 set_accessor_declaration
        : opt_attributes SET 
          {
-                 if (parsing_indexer == false)  
-                         current_local_parameters = new Parameters (implicit_value_parameters, null);
+               Parameter [] args;
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null);
+
+               if (parsing_indexer == false) {
+                       args  = new Parameter [1];
+                       args [0] = implicit_value_parameter;
+               } else {
+                       Parameter [] fp = indexer_parameters.FixedParameters;
+                       int count = fp.Length;
+
+                       args = new Parameter [count + 1];
+       
+                       fp.CopyTo (args, 0);
+                       args [count] = implicit_value_parameter;
+               }
+               
+               current_local_parameters = new Parameters (args, null, lexer.Location);
+               lexer.PropertyParsing = false;
          }
          accessor_body
          {
                $$ = $4;
                current_local_parameters = null;
+               lexer.PropertyParsing = true;
          }
        ;
 
 accessor_body
        : block 
-       | SEMICOLON             { $$ = new Block (null); }
+       | SEMICOLON             { $$ = null; }
        ;
 
 interface_declaration
@@ -917,17 +1094,18 @@ interface_declaration
                Interface new_interface;
                string full_interface_name = MakeName ((string) $4);
 
-               new_interface = new Interface (rc, current_container, full_interface_name, (int) $2, 
+               new_interface = new Interface (current_container, full_interface_name, (int) $2, 
                                               (Attributes) $1, lexer.Location);
                if (current_interface != null) {
                        Location l = lexer.Location;
                        Report.Error (-2, l, "Internal compiler error: interface inside interface");
                }
                current_interface = new_interface;
-               tree.RecordInterface (full_interface_name, new_interface);
+               new_interface.Namespace = current_namespace;
+               RootContext.Tree.RecordDecl (full_interface_name, new_interface);
          }
          opt_interface_base
-         interface_body
+         interface_body opt_semicolon
          { 
                Interface new_interface = (Interface) current_interface;
 
@@ -935,7 +1113,8 @@ interface_declaration
                        new_interface.Bases = (ArrayList) $6;
 
                current_interface = null;
-               CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
+               CheckDef (current_container.AddInterface (new_interface), 
+                         new_interface.Name, new_interface.Location);
          }
        ;
 
@@ -985,25 +1164,25 @@ interface_member_declaration
          { 
                InterfaceMethod m = (InterfaceMethod) $1;
 
-               CheckDef (current_interface.AddMethod (m), m.Name);
+               CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
          }
        | interface_property_declaration        
          { 
                InterfaceProperty p = (InterfaceProperty) $1;
 
-               CheckDef (current_interface.AddProperty (p), p.Name);
+               CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
           }
        | interface_event_declaration 
           { 
                InterfaceEvent e = (InterfaceEvent) $1;
 
-               CheckDef (current_interface.AddEvent (e), e.Name);
+               CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
          }
        | interface_indexer_declaration
          { 
                InterfaceIndexer i = (InterfaceIndexer) $1;
 
-               CheckDef (current_interface.AddIndexer (i), "indexer");
+               CheckDef (current_interface.AddIndexer (i), "indexer", i.Location);
          }
        ;
 
@@ -1017,13 +1196,15 @@ interface_method_declaration
          OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
          SEMICOLON
          {
-               $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
+               $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, 
+                                         (Parameters) $6, (Attributes) $1, lexer.Location);
          }
        | opt_attributes opt_new VOID IDENTIFIER 
          OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
          SEMICOLON
          {
-               $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
+               $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, 
+                                         (Attributes) $1, lexer.Location);
          }
        ;
 
@@ -1032,15 +1213,16 @@ interface_property_declaration
          opt_new
          type IDENTIFIER 
          OPEN_BRACE 
-         { lexer.properties = true; }
+         { lexer.PropertyParsing = true; }
          interface_accesors 
-         { lexer.properties = false; }
+         { lexer.PropertyParsing = false; }
          CLOSE_BRACE
          {
                int gs = (int) $7;
 
                $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2, 
-                                           (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1);
+                                           (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1,
+                                           lexer.Location);
          }
        ;
 
@@ -1064,9 +1246,9 @@ interface_indexer_declaration
        : opt_attributes opt_new type THIS 
          OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
          OPEN_BRACE 
-         { lexer.properties = true; }
+         { lexer.PropertyParsing = true; }
          interface_accesors 
-         { lexer.properties = false; }
+         { lexer.PropertyParsing = false; }
          CLOSE_BRACE
          {
                int a_flags = (int) $10;
@@ -1074,12 +1256,13 @@ interface_indexer_declaration
                bool do_get = (a_flags & 1) == 1;
                bool do_set = (a_flags & 2) == 2;
 
-               $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2, (Attributes) $1);
+               $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set,
+                                          (bool) $2, (Attributes) $1, lexer.Location);
          }
        ;
 
 operator_declaration
-       : opt_attributes opt_modifiers operator_declarator block
+       : opt_attributes opt_modifiers operator_declarator operator_body
          {
                OperatorDeclaration decl = (OperatorDeclaration) $3;
                
@@ -1088,9 +1271,15 @@ operator_declaration
 
                // Note again, checking is done in semantic analysis
                current_container.AddOperator (op);
+
+               current_local_parameters = null;
          }
        ;
 
+operator_body 
+       : block
+       | SEMICOLON { $$ = null; }
+       ; 
 operator_declarator
        : type OPERATOR overloadable_operator 
          OPEN_PARENS type IDENTIFIER CLOSE_PARENS
@@ -1104,6 +1293,12 @@ operator_declarator
                if (op == Operator.OpType.Subtraction)
                        op = Operator.OpType.UnaryNegation;
 
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
+
+               current_local_parameters = new Parameters (pars, null, lexer.Location);
+
                $$ = new OperatorDeclaration (op, (string) $1, (string) $5, (string) $6,
                                              null, null, lexer.Location);
        }
@@ -1114,6 +1309,13 @@ operator_declarator
          CLOSE_PARENS
         {
               CheckBinaryOperator ((Operator.OpType) $3);
+
+              Parameter [] pars = new Parameter [2];
+
+              pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
+              pars [1] = new Parameter ((string) $8, (string) $9, Parameter.Modifier.NONE, null);
+
+              current_local_parameters = new Parameters (pars, null, lexer.Location);
               
               $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
                                             (string) $8, (string) $9, lexer.Location);
@@ -1152,44 +1354,68 @@ overloadable_operator
 conversion_operator_declarator
        : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
          {
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
+
+               current_local_parameters = new Parameters (pars, null, lexer.Location);  
+                 
                $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
                                              null, null, lexer.Location);
          }
        | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
          {
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
+
+               current_local_parameters = new Parameters (pars, null, lexer.Location);  
+                 
                $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
                                              null, null, lexer.Location);
          }
+       | IMPLICIT error 
+         {
+               syntax_error (lexer.Location, "'operator' expected");
+         }
+       | EXPLICIT error 
+         {
+               syntax_error (lexer.Location, "'operator' expected");
+         }
        ;
 
 constructor_declaration
        : opt_attributes
          opt_modifiers
          constructor_declarator
-         block
+         constructor_body
          { 
                Constructor c = (Constructor) $3;
                c.Block = (Block) $4;
                c.ModFlags = (int) $2;
+               c.OptAttributes = (Attributes) $1;
 
                if ((c.ModFlags & Modifiers.STATIC) != 0){
                        if ((c.ModFlags & Modifiers.Accessibility) != 0) {
-                               Location l = lexer.Location;
-                               Report.Error (515, l, "Access modifiers are not allowed on static constructors");
+                               Report.Error (
+                                       515, c.Location, 
+                                       "Access modifiers are not allowed on static constructors");
                        }
 
                        if (c.Initializer != null){
-                               Location l = lexer.Location;
-                               Report.Error (514, l, "Static constructors can not have an explicit this or base constructor invocations");
+                               Report.Error (
+                                       514, c.Location, 
+                                       "Static constructors can not have an explicit this or base " +
+                                       "constructor invocations");
                        }
 
                        if (!c.Parameters.Empty){
-                               Location l = lexer.Location;
-                               Report.Error (103, l, "Static constructors should not have parameters");
+                               Report.Error (
+                                       132, c.Location, "Static constructors should not have parameters");
                        }
                } 
                
-               CheckDef (current_container.AddConstructor (c), c.Name);
+               CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
 
                current_local_parameters = null;
          }
@@ -1198,14 +1424,21 @@ constructor_declaration
 constructor_declarator
        : IDENTIFIER 
          OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
-         opt_constructor_initializer
          {
-               Location l = lexer.Location;
+               oob_stack.Push (lexer.Location);
 
-               $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $5, l);
-       
                current_local_parameters = (Parameters) $3;
          }
+         opt_constructor_initializer
+         {
+               Location l = (Location) oob_stack.Pop ();
+               $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $6, l);
+         }
+       ;
+
+constructor_body
+       : block
+       | SEMICOLON             { $$ = null; }
        ;
 
 opt_constructor_initializer
@@ -1227,11 +1460,22 @@ constructor_initializer
 destructor_declaration
        : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
          {
-               Method d = new Method ("System.Void", 0, "Finalize", 
-                                      new Parameters (null, null), (Attributes) $1, lexer.Location);
+               if ((string) $3 != current_container.Basename){
+                       Report.Error (574, lexer.Location, "Name of destructor must match name of class");
+               } else if (!(current_container is Class)){
+                       Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
+               } else {
+                       Location l = lexer.Location;
+
+                       Method d = new Method (
+                               "System.Void", 
+                               Modifiers.PROTECTED | Modifiers.OVERRIDE, 
+                               "Finalize", 
+                               new Parameters (null, null, l), (Attributes) $1, l);
                  
-               d.Block = (Block) $6;
-               CheckDef (current_container.AddMethod (d), d.Name);
+                       d.Block = (Block) $6;
+                       CheckDef (current_container.AddMethod (d), d.Name, d.Location);
+               }
          }
        ;
 
@@ -1242,57 +1486,96 @@ event_declaration
          {
                foreach (VariableDeclaration var in (ArrayList) $5) {
 
-                       // FIXME : Is this right ?
                        Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
-                                            (int) $2, null, null, (Attributes) $1);
+                                            (int) $2, null, null, (Attributes) $1, lexer.Location);
 
-                       CheckDef (current_container.AddEvent (e), e.Name);
+                       CheckDef (current_container.AddEvent (e), e.Name, e.Location);
                                       
                }
          }
        | opt_attributes
          opt_modifiers
-         EVENT type member_name 
-         OPEN_BRACE event_accessor_declarations CLOSE_BRACE
-       {
-               DictionaryEntry pair = (DictionaryEntry) $7;
+         EVENT type member_name
+         OPEN_BRACE
+         {
+               implicit_value_parameter_type = (string) $4;  
+               lexer.EventParsing = true;
+               oob_stack.Push (lexer.Location);
+         }
+         event_accessor_declarations
+         {
+               lexer.EventParsing = false;  
+         }
+         CLOSE_BRACE
+         {
+               Location loc = (Location) oob_stack.Pop ();
+
+               Pair pair = (Pair) $8;
                Block add_block = null;
                Block rem_block = null;
 
-               if (pair.Key != null)
-                       add_block = (Block) pair.Key;
-               if (pair.Value != null)
-                       rem_block = (Block) pair.Value;
+               if (pair.First != null)
+                       add_block = (Block) pair.First;
+               if (pair.Second != null)
+                       rem_block = (Block) pair.Second;
                
-               Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);
+               Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block,
+                                    (Attributes) $1, loc);
                
-               CheckDef (current_container.AddEvent (e), e.Name);
-       }
+               CheckDef (current_container.AddEvent (e), e.Name, loc);
+               implicit_value_parameter_type = null;
+         }
        ;
 
 event_accessor_declarations
        : add_accessor_declaration remove_accessor_declaration
        {
-               $$ = new DictionaryEntry ($1, $2);
+               $$ = new Pair ($1, $2);
        }
        | remove_accessor_declaration add_accessor_declaration
        {
-               $$ = new DictionaryEntry ($2, $1);
+               $$ = new Pair ($2, $1);
        }       
        ;
 
 add_accessor_declaration
-       : opt_attributes ADD block
+       : opt_attributes ADD
+         {
+               Parameter [] args = new Parameter [1];
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null);
+
+               args [0] = implicit_value_parameter;
+               
+               current_local_parameters = new Parameters (args, null, lexer.Location);  
+               lexer.EventParsing = false;
+         }
+          block
          {
-               $$ = $3;
+               $$ = $4;
+               lexer.EventParsing = true;
          }
        ;
 
 remove_accessor_declaration
-       : opt_attributes REMOVE block
-       {
-               $$ = $3;
-       }
+       : opt_attributes REMOVE
+         {
+               Parameter [] args = new Parameter [1];
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null);
+
+               args [0] = implicit_value_parameter;
+               
+               current_local_parameters = new Parameters (args, null, lexer.Location);  
+               lexer.EventParsing = false;
+         }
+          block
+         {
+               $$ = $4;
+               lexer.EventParsing = true;
+         }
        ;
 
 indexer_declaration
@@ -1300,15 +1583,18 @@ indexer_declaration
          OPEN_BRACE 
          {
                IndexerDeclaration decl = (IndexerDeclaration) $3;
-                 
-               lexer.properties = true;
+
+               implicit_value_parameter_type = decl.type;
+               
+               lexer.PropertyParsing = true;
                parsing_indexer  = true;
                
-               current_local_parameters = decl.param_list;
+               indexer_parameters = decl.param_list;
+               $$ = lexer.Location;
          }
           accessor_declarations 
          {
-                 lexer.properties = false;
+                 lexer.PropertyParsing = false;
                  parsing_indexer  = false;
          }
          CLOSE_BRACE
@@ -1318,17 +1604,17 @@ indexer_declaration
 
                Indexer indexer;
                IndexerDeclaration decl = (IndexerDeclaration) $3;
-               DictionaryEntry pair = (DictionaryEntry) $6;
+               Pair pair = (Pair) $6;
                Block get_block = null;
                Block set_block = null;
 
-               if (pair.Key != null)
-                       get_block = (Block) pair.Key;
-               if (pair.Value != null)
-                       set_block = (Block) pair.Value;
+               if (pair.First != null)
+                       get_block = (Block) pair.First;
+               if (pair.Second != null)
+                       set_block = (Block) pair.Second;
 
                indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
-                                      get_block, set_block, (Attributes) $1);
+                                      get_block, set_block, (Attributes) $1, (Location) $5);
 
                // Note that there is no equivalent of CheckDef for this case
                // We shall handle this in semantic analysis
@@ -1336,44 +1622,68 @@ indexer_declaration
                current_container.AddIndexer (indexer);
                
                current_local_parameters = null;
+               implicit_value_parameter_type = null;
+               indexer_parameters = null;
          }
        ;
 
 indexer_declarator
-       : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+       : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
          {
-               $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
+               Parameters pars = (Parameters) $4;
+
+               if (pars.FixedParameters == null){
+                       Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
+               }
+
+               $$ = new IndexerDeclaration ((string) $1, null, pars);
          }
-       | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+       | type qualified_identifier DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
          {
-               $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
+               Parameters pars = (Parameters) $6;
+
+               if (pars.FixedParameters == null){
+                       Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
+               }
+               $$ = new IndexerDeclaration ((string) $1, (string) $2, pars);
          }
        ;
 
 enum_declaration
        : opt_attributes
          opt_modifiers
-         ENUM IDENTIFIER
+         ENUM IDENTIFIER 
          opt_enum_base
          enum_body
          opt_semicolon
          { 
-               string name = (string) $4;
-               Enum e = new Enum ((string) $5, (int) $2, name, (Attributes) $1, lexer.Location);
+               Location enum_location = lexer.Location;
+
+               string full_name = MakeName ((string) $4);
+               Enum e = new Enum (
+                               current_container, (string) $5, (int) $2, full_name, 
+                               (Attributes) $1, enum_location);
 
                foreach (VariableDeclaration ev in (ArrayList) $6){
+                       Location loc = (Location) ev.Location;
+
                        CheckDef (e.AddEnumMember (ev.identifier, 
-                                                  (Expression) ev.expression_or_array_initializer),
-                                 ev.identifier);
+                                                  (Expression) ev.expression_or_array_initializer,
+                                                  loc),
+                                 ev.identifier, loc);
                }
 
-               CheckDef (current_container.AddEnum (e), name);
+               e.Namespace = current_namespace;
+
+               CheckDef (current_container.AddEnum (e), full_name, enum_location);
+               RootContext.Tree.RecordDecl (full_name, e);
+
          }
        ;
 
 opt_enum_base
-       : /* empty */                   { $$ = "System.Int32"; }
-       | COLON integral_type           { $$ = $2;   }
+       : /* empty */           { $$ = "System.Int32"; }
+       | COLON type            { $$ = $2;   }
        ;
 
 enum_body
@@ -1411,9 +1721,13 @@ enum_member_declaration
          {
                $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
          }
-       | opt_attributes IDENTIFIER ASSIGN expression
+       | opt_attributes IDENTIFIER
+         {
+                 $$ = lexer.Location;
+         }
+          ASSIGN expression
          { 
-               $$ = new VariableDeclaration ((string) $2, $4, lexer.Location);
+               $$ = new VariableDeclaration ((string) $2, $5, lexer.Location);
          }
        ;
 
@@ -1422,28 +1736,34 @@ delegate_declaration
          opt_modifiers
          DELEGATE type   
          IDENTIFIER OPEN_PARENS 
-         formal_parameter_list
+         opt_formal_parameter_list
          CLOSE_PARENS 
          SEMICOLON
          {
-               Delegate del = new Delegate (rc, (string) $4, (int) $2, 
+               Location l = lexer.Location;
+               Delegate del = new Delegate (current_container, (string) $4, (int) $2, 
                                             MakeName ((string) $5), (Parameters) $7, 
-                                            (Attributes) $1, lexer.Location);
+                                            (Attributes) $1, l);
                  
-               CheckDef (current_container.AddDelegate (del), del.Name);
+               del.Namespace = current_namespace;
+               CheckDef (current_container.AddDelegate (del), del.Name, l);
          }     
        | opt_attributes
          opt_modifiers
          DELEGATE VOID   
          IDENTIFIER OPEN_PARENS 
-         formal_parameter_list
+         opt_formal_parameter_list
          CLOSE_PARENS 
          SEMICOLON
          {
-               Delegate del = new Delegate (rc, "System.Void", (int) $2, (string) $5, (Parameters) $7, 
-                                            (Attributes) $1, lexer.Location);
+               Location l = lexer.Location;
+               Delegate del = new Delegate (
+                       current_container,
+                       "System.Void", (int) $2, MakeName ((string) $5), (Parameters) $7, 
+                       (Attributes) $1, l);
 
-               CheckDef (current_container.AddDelegate (del), del.Name);
+               del.Namespace = current_namespace;
+               CheckDef (current_container.AddDelegate (del), del.Name, l);
          }
        ;
 
@@ -1471,6 +1791,47 @@ type
          }
        | builtin_types
        | array_type
+       | pointer_type    
+       ;
+
+
+pointer_type
+       : type STAR
+         {
+               //
+               // Note that here only unmanaged types are allowed but we
+               // can't perform checks during this phase - we do it during
+               // semantic analysis.
+               //
+               $$ = (string) $1 + "*";
+         }
+       | VOID STAR
+         {
+               $$ = "System.Void*";
+         }
+       ;
+
+non_expression_type
+       : builtin_types 
+         {
+               $$ = new SimpleName ((string) $1, lexer.Location);
+         }
+       | non_expression_type rank_specifier
+         {
+               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+       | non_expression_type STAR
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+       | expression rank_specifiers 
+         {
+               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+       | expression STAR 
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
        ;
 
 type_list
@@ -1514,6 +1875,7 @@ integral_type
        | LONG          { $$ = "System.Int64"; }
        | ULONG         { $$ = "System.UInt64"; }
        | CHAR          { $$ = "System.Char"; }
+       | VOID          { $$ = "System.Void"; }
        ;
 
 interface_type
@@ -1556,6 +1918,9 @@ primary_expression
        | sizeof_expression
        | checked_expression
        | unchecked_expression
+       | pointer_member_access
+       // TODO: pointer_element_access
+       // TODO: sizeof-expression
        ;
 
 literal
@@ -1564,7 +1929,7 @@ literal
        | real_literal
        | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
        | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
-       | NULL                  { $$ = new NullLiteral (); }
+       | NULL                  { $$ = NullLiteral.Null; }
        ;
 
 real_literal
@@ -1611,7 +1976,7 @@ member_access
          }
        | predefined_type DOT IDENTIFIER
          {
-               $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
+               $$ = new MemberAccess (new SimpleName ((string) $1, lexer.Location), (string) $3, lexer.Location);
          }
        ;
 
@@ -1622,17 +1987,11 @@ predefined_type
 invocation_expression
        : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
          {
-               // FIXME:
-               // if $1 is MethodGroup
-               //      $$ = new Call ($1, $3);
-               // else 
-               //      $$ = new DelegateCall ($1, $3);
                if ($1 == null) {
                        Location l = lexer.Location;
                        Report.Error (1, l, "THIS IS CRAZY");
                }
                $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
-               
          }
        ; 
 
@@ -1680,6 +2039,28 @@ element_access
          {
                $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
          }
+       | primary_expression rank_specifiers
+         {
+               // So the super-trick is that primary_expression
+               // can only be either a SimpleName or a MemberAccess. 
+               // The MemberAccess case arises when you have a fully qualified type-name like :
+               // Foo.Bar.Blah i;
+               // SimpleName is when you have
+               // Blah i;
+                 
+               Expression expr = (Expression) $1;  
+               if (!(expr is SimpleName || expr is MemberAccess)) {
+                       Location l = lexer.Location;
+                       Report.Error (-1, l, "Invalid Type definition");
+                       $$ = "System.Object";
+               }
+               
+               //
+               // So we extract the string corresponding to the SimpleName
+               // or MemberAccess
+               // 
+               $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
+         }
        ;
 
 expression_list
@@ -1707,25 +2088,27 @@ this_access
 base_access
        : BASE DOT IDENTIFIER
          {
-               $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);
+               $$ = new BaseAccess ((string) $3, lexer.Location);
          }
        | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
          {
-               $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);
+               $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
          }
        ;
 
 post_increment_expression
        : primary_expression OP_INC
          {
-               $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1, lexer.Location);
+               $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
+                                      (Expression) $1, lexer.Location);
          }
        ;
 
 post_decrement_expression
        : primary_expression OP_DEC
          {
-               $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1, lexer.Location);
+               $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
+                                      (Expression) $1, lexer.Location);
          }
        ;
 
@@ -1746,7 +2129,16 @@ array_creation_expression
          opt_rank_specifier
          opt_array_initializer
          {
-               $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
+               $$ = new ArrayCreation ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, 
+                                       lexer.Location);
+         }
+       | NEW type rank_specifiers array_initializer
+         {
+               $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
+         }
+       | NEW type error 
+         {
+               Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
          }
        ;
 
@@ -1842,13 +2234,13 @@ variable_initializer_list
 typeof_expression
        : TYPEOF OPEN_PARENS type CLOSE_PARENS
          {
-               $$ = new TypeOf ((string) $3);
+               $$ = new TypeOf ((string) $3, lexer.Location);
          }
        ;
 
 sizeof_expression
        : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
-               $$ = new SizeOf ((string) $3);
+               $$ = new SizeOf ((string) $3, lexer.Location);
 
                note ("Verify type is unmanaged"); 
                note ("if (5.8) builtin, yield constant expression");
@@ -1869,94 +2261,98 @@ unchecked_expression
          }
        ;
 
+pointer_member_access 
+       : primary_expression OP_PTR IDENTIFIER
+         {
+               Expression deref;
+
+               deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lexer.Location);
+               $$ = new MemberAccess (deref, (string) $3, lexer.Location);
+         }
+
 unary_expression
        : primary_expression
-       | PLUS unary_expression
+       | BANG prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
+         }
+       | TILDE prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
+         }
+        | OPEN_PARENS expression CLOSE_PARENS unary_expression
+         {
+                 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
+         }
+        | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
+         {
+                 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
+         }
+       ;
+
+       //
+       // The idea to split this out is from Rhys' grammar
+       // to solve the problem with casts.
+       //
+prefixed_unary_expression
+       : unary_expression
+       | PLUS prefixed_unary_expression
          { 
                $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
          } 
-       | MINUS unary_expression 
+       | MINUS prefixed_unary_expression 
          { 
                $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
          }
-       | BANG unary_expression 
+       | OP_INC prefixed_unary_expression 
          {
-               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
+                                      (Expression) $2, lexer.Location);
          }
-       | TILDE unary_expression
+       | OP_DEC prefixed_unary_expression 
          {
-               $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
+                                      (Expression) $2, lexer.Location);
          }
-       | STAR unary_expression
+       | STAR prefixed_unary_expression
          {
                $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
          }
-       | BITWISE_AND unary_expression
+       | BITWISE_AND prefixed_unary_expression
          {
                $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
          }
-       | OP_INC unary_expression 
-         {
-               $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
-         }
-       | OP_DEC unary_expression 
-         {
-               $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);
-         }
-        | cast_expression 
-       /*
-        we can not do cast expressions at this level,
-        as there is an ambiguity.  Check "Cast Expressions" 7.6.8
-        for the recipe to handle this.
-        */
        ;
 
 pre_increment_expression
-       : OP_INC unary_expression 
+       : OP_INC prefixed_unary_expression 
          {
-               $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
+                                      (Expression) $2, lexer.Location);
          }
        ;
 
 pre_decrement_expression
-       : OP_DEC unary_expression 
+       : OP_DEC prefixed_unary_expression 
          {
-               $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);
-         }
-       ;
-
-cast_expression
-       /* 
-        * FIXME: This is actually wrong, it should be `type' but that
-        * introduces a lot of {shift,reduce}/reduces
-        *
-        * This is really really wrong.  We need to track down
-        * the source of problems with QIs because expressions like:
-        * foreach (string s in (string []) object) wont be parsed.
-        */
-       : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
-         {
-               $$ = new Cast ((string) $2, (Expression) $4, lexer.Location);
-         }
-       | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
-         {
-               $$ = new Cast ((string) $2, (Expression) $4, lexer.Location);
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
+                                      (Expression) $2, lexer.Location);
          }
        ;
 
 multiplicative_expression
-       : unary_expression
-       | multiplicative_expression STAR unary_expression
+       : prefixed_unary_expression
+       | multiplicative_expression STAR prefixed_unary_expression
          {
                $$ = new Binary (Binary.Operator.Multiply, 
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | multiplicative_expression DIV unary_expression
+       | multiplicative_expression DIV prefixed_unary_expression
          {
                $$ = new Binary (Binary.Operator.Division, 
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | multiplicative_expression PERCENT unary_expression 
+       | multiplicative_expression PERCENT prefixed_unary_expression 
          {
                $$ = new Binary (Binary.Operator.Modulus, 
                                 (Expression) $1, (Expression) $3, lexer.Location);
@@ -2015,13 +2411,11 @@ relational_expression
          }
        | relational_expression IS type
          {
-               $$ = new Probe (Probe.Operator.Is, 
-                                (Expression) $1, (string) $3);
+               $$ = new Is ((Expression) $1, (string) $3, lexer.Location);
          }
        | relational_expression AS type
          {
-               $$ = new Probe (Probe.Operator.As, 
-                                (Expression) $1, (string) $3);
+               $$ = new As ((Expression) $1, (string) $3, lexer.Location);
          }
        ;
 
@@ -2093,99 +2487,119 @@ conditional_expression
        ;
 
 assignment_expression
-       : unary_expression ASSIGN expression
+       : prefixed_unary_expression ASSIGN expression
          {
                $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
          }
-       | unary_expression OP_MULT_ASSIGN expression
+       | prefixed_unary_expression OP_MULT_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.Multiply, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.Multiply, 
+                                    (Expression) $1,
+                                    (Expression) $3, l), 
+                       (Expression) $3, l);
          }
-       | unary_expression OP_DIV_ASSIGN expression
+       | prefixed_unary_expression OP_DIV_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.Division, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.Division, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
-       | unary_expression OP_MOD_ASSIGN expression
+       | prefixed_unary_expression OP_MOD_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.Modulus, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.Modulus, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
-       | unary_expression OP_ADD_ASSIGN expression
+       | prefixed_unary_expression OP_ADD_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.Addition, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.Addition, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
-       | unary_expression OP_SUB_ASSIGN expression
+       | prefixed_unary_expression OP_SUB_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.Subtraction, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.Subtraction, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
-       | unary_expression OP_SHIFT_LEFT_ASSIGN expression
+       | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.LeftShift, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.LeftShift, 
+                                    (Expression) $1,
+                                    (Expression) $3, l), 
+                       (Expression) $3, l);
          }
-       | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
+       | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.RightShift, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.RightShift, 
+                                    (Expression) $1,
+                                    (Expression) $3, l), 
+                       (Expression) $3, l);
          }
-       | unary_expression OP_AND_ASSIGN expression
+       | prefixed_unary_expression OP_AND_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.BitwiseAnd, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.BitwiseAnd, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
-       | unary_expression OP_OR_ASSIGN expression
+       | prefixed_unary_expression OP_OR_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.BitwiseOr, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.BitwiseOr, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
-       | unary_expression OP_XOR_ASSIGN expression
+       | prefixed_unary_expression OP_XOR_ASSIGN expression
          {
                Location l = lexer.Location;
 
-               $$ = new Assign ((Expression) $1,
-                                new Binary (Binary.Operator.ExclusiveOr, 
-                                            (Expression) $1,
-                                            (Expression) $3, l), l);
+               $$ = new CompoundAssign (
+                       (Expression) $1,
+                       new Binary (Binary.Operator.ExclusiveOr, 
+                                    (Expression) $1,
+                                    (Expression) $3, l),
+                       (Expression) $3, l);
          }
        ;
 
@@ -2199,7 +2613,7 @@ constant_expression
        ;
 
 boolean_expression
-       : expression    { CheckBoolean ((Expression) $1); $$ = $1; } 
+       : expression
        ;
 
 //
@@ -2211,13 +2625,15 @@ class_declaration
          CLASS IDENTIFIER
          {
                Class new_class;
-               string full_class_name = MakeName ((string) $4);
+               string name;
 
-               new_class = new Class (rc, current_container, full_class_name, (int) $2, 
+               name = MakeName ((string) $4);
+
+               new_class = new Class (current_container, name, (int) $2, 
                                       (Attributes) $1, lexer.Location);
                current_container = new_class;
                current_container.Namespace = current_namespace;
-               tree.RecordClass (full_class_name, new_class);
+               RootContext.Tree.RecordDecl (name, new_class);
          }
          opt_class_base
          class_body 
@@ -2229,7 +2645,7 @@ class_declaration
                        new_class.Bases = (ArrayList) $6;
 
                current_container = current_container.Parent;
-               CheckDef (current_container.AddClass (new_class), new_class.Name);
+               CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
 
                $$ = new_class;
          }
@@ -2249,7 +2665,7 @@ modifiers
 
                if ((m1 & m2) != 0) {
                        Location l = lexer.Location;
-                       Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
+                       Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
                }
                $$ = (int) (m1 | m2);
          }
@@ -2268,6 +2684,8 @@ modifier
        | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
        | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
        | EXTERN                { $$ = Modifiers.EXTERN; }
+       | VOLATILE              { $$ = Modifiers.VOLATILE; }
+       | UNSAFE                { $$ = Modifiers.UNSAFE; }
        ;
 
 opt_class_base
@@ -2295,13 +2713,14 @@ class_base
 block
        : OPEN_BRACE 
          {
-               current_block = new Block (current_block);
+               current_block = new Block (current_block, lexer.Location, Location.Null);
          } 
          opt_statement_list CLOSE_BRACE 
          { 
                while (current_block.Implicit)
                        current_block = current_block.Parent;
                $$ = current_block;
+               current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
          }
        ;
@@ -2326,12 +2745,12 @@ statement
          }
        | embedded_statement
          {
+               Statement s = (Statement) $1;
+
+
                current_block.AddStatement ((Statement) $1);
          }
-       | labeled_statement 
-         {
-               current_block.AddStatement ((Statement) $1);
-         }
+       | labeled_statement
        ;
 
 embedded_statement
@@ -2346,6 +2765,8 @@ embedded_statement
        | unchecked_statement
        | lock_statement
        | using_statement
+       | unsafe_statement
+       | fixed_statement
        ;
 
 empty_statement
@@ -2356,26 +2777,33 @@ empty_statement
        ;
 
 labeled_statement
-       : IDENTIFIER COLON statement
+       : IDENTIFIER COLON 
          {
-               string lab = (String) $1;
-               Block block;
+               LabeledStatement labeled = new LabeledStatement ((string) $1);
 
-               block = new Block (current_block, lab);
-               block.AddStatement ((Statement) $3);
-               $$ = block;
-
-               if (!current_block.AddLabel (lab, block)){
+               if (!current_block.AddLabel ((string) $1, labeled)){
                        Location l = lexer.Location;
-                       Report.Error (140, l, "The label '" + lab + "' is a duplicate");
-                       $$ = $3;
+                       Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
                }       
+               current_block.AddStatement (labeled);
          }
+         statement
        ;
 
 declaration_statement
-       : local_variable_declaration SEMICOLON          // done
-       | local_constant_declaration SEMICOLON          // finishme
+       : local_variable_declaration SEMICOLON
+         {
+               DictionaryEntry de = (DictionaryEntry) $1;
+
+               $$ = declare_local_variables ((string) de.Key, (ArrayList) de.Value, lexer.Location);
+         }
+
+       | local_constant_declaration SEMICOLON
+         {
+               DictionaryEntry de = (DictionaryEntry) $1;
+
+               $$ = declare_local_constant ((string) de.Key, (VariableDeclaration) de.Value);
+         }
        ;
 
 /* 
@@ -2395,16 +2823,26 @@ local_variable_type
                // creeps up.  If you use qualified_identifier (which is all we need
                // really) two shift/reduces appear.
                // 
-               // So, instead we do a super trick: we just allow ($1) to be a 
-               // SimpleName Expression.
-               //
-               if (((Expression) $1) is SimpleName)
-                       $$ = ((SimpleName) $1).Name;
-               else {
+
+               // So the super-trick is that primary_expression
+               // can only be either a SimpleName or a MemberAccess. 
+               // The MemberAccess case arises when you have a fully qualified type-name like :
+               // Foo.Bar.Blah i;
+               // SimpleName is when you have
+               // Blah i;
+                 
+               Expression expr = (Expression) $1;  
+               if (!(expr is SimpleName || expr is MemberAccess)) {
                        Location l = lexer.Location;
                        Report.Error (-1, l, "Invalid Type definition");
                        $$ = "System.Object";
                }
+               
+               //
+               // So we extract the string corresponding to the SimpleName
+               // or MemberAccess
+               // 
+               $$ = GetQualifiedIdentifier (expr) + (string) $2;
          }
        | builtin_types opt_rank_specifier
          {
@@ -2412,25 +2850,48 @@ local_variable_type
          }
         ;
 
-// FIXME : How can the type of a local variable be void ? I don't quite see ;-)
-//          | VOID 
-//       {
-//             // FIXME: this is a string that represents the type
-//             // Figure out something to make this work.
-//             $$ = "void";
-//       }
-//     ;
+local_variable_pointer_type
+       : primary_expression STAR
+         {
+               Expression expr = (Expression) $1;  
+               if (!(expr is SimpleName || expr is MemberAccess)) {
+                       Location l = lexer.Location;
+                       Report.Error (-1, l, "Invalid Type definition");
+                       $$ = "System.Object";
+               }
+               
+               $$ = GetQualifiedIdentifier (expr) + "*";
+         }
+        | builtin_types STAR
+         {
+               $$ = (string) $1 + "*";
+         }
+        | VOID STAR
+         {
+               $$ = "System.Void*";
+         }
+       | local_variable_pointer_type STAR
+          {
+               $$ = (string) $1 + "*";
+         }
+        ;
 
 local_variable_declaration
        : local_variable_type variable_declarators
          {
-               $$ = declare_local_variables ((string) $1, (ArrayList) $2);
+               $$ = new DictionaryEntry ($1, $2);
          }
-       ;
+        | local_variable_pointer_type opt_rank_specifier variable_declarators
+       {
+               $$ = new DictionaryEntry ((string) $1 + (string) $2, $3);
+       }
+       ;
 
 local_constant_declaration
-       : CONST type constant_declarator
-               // finishme     
+       : CONST local_variable_type constant_declarator
+         {
+               $$ = new DictionaryEntry ($2, $3);
+         }
        ;
 
 expression_statement
@@ -2445,13 +2906,16 @@ expression_statement
        // because statement_expression is used for example in for_statement
        //
 statement_expression
-       : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
-       | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1); }
-       | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
-       | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
-       | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
-       | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
-       | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
+       : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | error {
+               Report.Error (1002, lexer.Location, "Expecting `;'");
+         }
        ;
 
 object_creation_expression
@@ -2465,23 +2929,51 @@ selection_statement
        ; 
 
 if_statement
-       : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
+       : if_statement_open if_statement_rest
+         {
+               $$ = $2;
+         }
+       ;
+
+if_statement_open
+       : IF OPEN_PARENS 
+         {
+               oob_stack.Push (lexer.Location);
+         }
+       ;
+
+if_statement_rest
+       : boolean_expression CLOSE_PARENS 
          embedded_statement
          { 
-               $$ = new If ((Expression) $3, (Statement) $5);
+               Location l = (Location) oob_stack.Pop ();
+
+               $$ = new If ((Expression) $1, (Statement) $3, l);
+
+               if (RootContext.WarningLevel >= 3){
+                       if ($3 is EmptyStatement)
+                               Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
+               }
+
          }
-       | IF OPEN_PARENS boolean_expression CLOSE_PARENS
+       | boolean_expression CLOSE_PARENS
          embedded_statement ELSE embedded_statement
          {
-               $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
+               Location l = (Location) oob_stack.Pop ();
+
+               $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
          }
        ;
 
 switch_statement
-       : SWITCH OPEN_PARENS expression CLOSE_PARENS 
+       : SWITCH OPEN_PARENS 
+         { 
+               oob_stack.Push (lexer.Location);
+         }
+         expression CLOSE_PARENS 
          switch_block
          {
-               $$ = new Switch ((Expression) $3, (ArrayList) $5);
+               $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
          }
        ;
 
@@ -2495,7 +2987,10 @@ switch_block
        ;
 
 opt_switch_sections
-       : /* empty */           { $$ = new ArrayList (); }
+       : /* empty */           
+          {
+               Report.Error (1522, lexer.Location, "Empty switch block"); 
+         }
        | switch_sections
        ;
 
@@ -2548,8 +3043,13 @@ switch_labels
        ;
 
 switch_label
-       : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2); }
-       | DEFAULT COLON                         { $$ = new SwitchLabel (null); }
+       : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
+       | DEFAULT COLON                         { $$ = new SwitchLabel (null, lexer.Location); }
+       | error {
+               Report.Error (
+                       1523, lexer.Location, 
+                       "The keyword case or default must precede code in switch block");
+         }
        ;
 
 iteration_statement
@@ -2560,9 +3060,19 @@ iteration_statement
        ;
 
 while_statement
-       : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
+       : WHILE OPEN_PARENS 
        {
-               $$ = new While ((Expression) $3, (Statement) $5);
+               oob_stack.Push (lexer.Location);
+       }
+       boolean_expression CLOSE_PARENS embedded_statement
+       {
+               Location l = (Location) oob_stack.Pop ();
+               $$ = new While ((Expression) $4, (Statement) $6, l);
+       
+               if (RootContext.WarningLevel >= 3){
+                       if ($6 is EmptyStatement)
+                               Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
+               }
        }
        ;
 
@@ -2570,18 +3080,81 @@ do_statement
        : DO embedded_statement 
          WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
          {
-               $$ = new Do ((Statement) $2, (Expression) $5);
+               $$ = new Do ((Statement) $2, (Expression) $5, lexer.Location);
          }
        ;
 
 for_statement
        : FOR OPEN_PARENS 
          opt_for_initializer SEMICOLON
+         {
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               if ($3 is DictionaryEntry){
+                       DictionaryEntry de = (DictionaryEntry) $3;
+                       
+                       string type = (string) de.Key;
+                       ArrayList var_declarators = (ArrayList) de.Value;
+
+                       foreach (VariableDeclaration decl in var_declarators){
+
+                               VariableInfo vi;
+
+                               vi = current_block.AddVariable (
+                                       type, decl.identifier, current_local_parameters, decl.Location);
+                               if (vi == null){
+                                       Report.Error (128, decl.Location, 
+                                                     "A local variable `" + decl.identifier + 
+                                                     "' is already defined in this scope");
+                               } else {
+                                       Location l = lexer.Location;
+                                       Expression expr;
+                                       if (decl.expression_or_array_initializer is Expression){
+                                               expr = (Expression) decl.expression_or_array_initializer;
+                                               
+                                       } else {
+                                               
+                                               ArrayList init = (ArrayList) decl.expression_or_array_initializer;
+                                               
+                                               string base_type = type.Substring (0, type.IndexOf ("["));
+                                               string rank = type.Substring (type.IndexOf ("["));
+                                               
+                                               expr = new ArrayCreation (base_type, rank, init, decl.Location);
+                                       }
+                                       
+                                       LocalVariableReference var;
+                                       var = new LocalVariableReference (
+                                                                         assign_block, decl.identifier, l);
+                                       
+                                       Assign a = new Assign (var, expr, decl.Location);
+                                       
+                                       assign_block.AddStatement (new StatementExpression (a, lexer.Location));
+                               }
+                       }
+                       
+                       $3 = null;
+               } 
+               oob_stack.Push (lexer.Location);
+         } 
          opt_for_condition SEMICOLON
          opt_for_iterator CLOSE_PARENS 
          embedded_statement
          {
-               $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
+               Location l = (Location) oob_stack.Pop ();
+
+               For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
+
+               if (RootContext.WarningLevel >= 3){
+                       if ($10 is EmptyStatement)
+                               Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
+               }
+
+               current_block.AddStatement (f);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
          }
        ;
 
@@ -2591,18 +3164,12 @@ opt_for_initializer
        ;
 
 for_initializer
-       : local_variable_declaration 
-         {
-               if ((Block) $1 != current_block){
-                       current_block.AddStatement ((Statement) $1);
-                       current_block = (Block) $1;
-               }
-         }
+       : local_variable_declaration
        | statement_expression_list
        ;
 
 opt_for_condition
-       : /* empty */           { $$ = new BoolLiteral (true); }
+       : /* empty */           { $$ = null; }
        | boolean_expression
        ;
 
@@ -2618,7 +3185,8 @@ for_iterator
 statement_expression_list
        : statement_expression  
          {
-               Block b = new Block (null, true);
+               // CHANGE: was `null'
+               Block b = new Block (current_block, true);   
 
                b.AddStatement ((Statement) $1);
                $$ = b;
@@ -2634,19 +3202,43 @@ statement_expression_list
 
 foreach_statement
        : FOREACH OPEN_PARENS type IDENTIFIER IN 
-         { 
-               $1 = lexer.Location;
-         } 
+         {
+               oob_stack.Push (lexer.Location);
+         }
          expression CLOSE_PARENS 
-         embedded_statement
          {
+               oob_stack.Push (current_block);
+
                Block foreach_block = new Block (current_block, true);
                LocalVariableReference v;
+               Location l = lexer.Location;
+               VariableInfo vi;
+
+               vi = foreach_block.AddVariable ((string) $3, (string) $4, current_local_parameters, l);
+               if (vi == null){
+                       Report.Error (
+                               128, l, "A local variable `" + (string) $4 + "' is already "+
+                               "defined in this scope");
+               }
+
+               v = new LocalVariableReference (foreach_block, (string) $4, l);
+               current_block = foreach_block;
+
+               oob_stack.Push (v);
+               oob_stack.Push (current_block);
+         } 
+         embedded_statement 
+         {
+               Block foreach_block = (Block) oob_stack.Pop ();
+               LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
+               Block prev_block = (Block) oob_stack.Pop ();
+               Location l = (Location) oob_stack.Pop ();
+
+               current_block = prev_block;
+
+               Foreach f = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
+               foreach_block.AddStatement (f);
 
-               foreach_block.AddVariable ((string) $3, (string) $4, (Location) $1);
-               v = new LocalVariableReference (foreach_block, (string) $4);
-               foreach_block.AddStatement (new Foreach ((string) $3, v, (Expression) $7, 
-                                           (Statement) $9, (Location) $1));
                $$ = foreach_block;
          }
        ;
@@ -2676,15 +3268,15 @@ continue_statement
 goto_statement
        : GOTO IDENTIFIER SEMICOLON 
          {
-               $$ = new Goto ((string) $2, lexer.Location);
+               $$ = new Goto (current_block, (string) $2, lexer.Location);
          }
        | GOTO CASE constant_expression SEMICOLON
          {
-               // FIXME
+               $$ = new GotoCase ((Expression) $3, lexer.Location);
          }
        | GOTO DEFAULT SEMICOLON 
          {
-               // FIXME
+               $$ = new GotoDefault (lexer.Location);
          }
        ; 
 
@@ -2698,7 +3290,7 @@ return_statement
 throw_statement
        : THROW opt_expression SEMICOLON
          {
-               $$ = new Throw ((Expression) $2);
+               $$ = new Throw ((Expression) $2, lexer.Location);
          }
        ;
 
@@ -2729,16 +3321,23 @@ try_statement
          {
                Catch g = null;
                ArrayList s = new ArrayList ();
-               
-               foreach (Catch cc in (ArrayList) $3) {
-                       if (cc.Type == null)
-                               g = cc;
-                       else
-                               s.Add (cc);
+               ArrayList catch_list = (ArrayList) $3;
+
+               if (catch_list != null){
+                       foreach (Catch cc in catch_list) {
+                               if (cc.Type == null)
+                                       g = cc;
+                               else
+                                       s.Add (cc);
+                       }
                }
 
                $$ = new Try ((Block) $2, s, g, (Block) $5);
          }
+       | TRY block error 
+         {
+               Report.Error (1524, lexer.Location, "Expected catch or finally");
+         }
        ;
 
 opt_catch_clauses
@@ -2780,11 +3379,13 @@ catch_clause
 
                        if (id != null){
                                ArrayList one = new ArrayList ();
-                               one.Add (new VariableDeclaration (id, null, lexer.Location));
+                               Location loc = lexer.Location;
+
+                               one.Add (new VariableDeclaration (id, null, loc));
 
                                $1 = current_block;
                                current_block = new Block (current_block);
-                               Block b = declare_local_variables (type, one);
+                               Block b = declare_local_variables (type, one, loc);
                                current_block = b;
 
                                
@@ -2805,7 +3406,7 @@ catch_clause
                }
 
 
-               $$ = new Catch (type, id , (Block) $4);
+               $$ = new Catch (type, id , (Block) $4, lexer.Location);
        }
         ;
 
@@ -2835,25 +3436,167 @@ unchecked_statement
          }
        ;
 
+unsafe_statement
+       : UNSAFE 
+       {
+               if (!RootContext.Unsafe){
+                       Report.Error (227, lexer.Location, 
+                               "Unsafe code can only be used if --unsafe is used");
+               }
+       } block {
+               $$ = new Unsafe ((Block) $3);
+       }
+       ;
+
+fixed_statement
+       : FIXED OPEN_PARENS 
+         pointer_type fixed_pointer_declarators 
+         CLOSE_PARENS 
+         {
+               Block assign_block = new Block (current_block, true);
+               ArrayList list = (ArrayList) $4;
+               string type = (string) $3;
+               Location l = lexer.Location;
+               int top = list.Count;
+
+               for (int i = 0; i < top; i++){
+                       Pair p = (Pair) list [i];
+                       VariableInfo v;
+
+                       v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
+                       if (v == null){
+                               Report.Error (
+                                       128, l, "A local variable `" + (string) p.First + "' is already "+
+                                       "defined in this scope");
+                       }
+                       v.ReadOnly = true;
+                       p.First = v;
+                       list [i] = p;
+               }
+               current_block.AddStatement (assign_block);
+               current_block = assign_block;
+               oob_stack.Push (assign_block);
+               oob_stack.Push (l);
+         }
+         embedded_statement 
+         {
+               Location l = (Location) oob_stack.Pop ();
+               Block assign_block = (Block) oob_stack.Pop ();
+
+               ArrayList list = (ArrayList) $4;
+               int top = list.Count;
+
+               $$ = new Fixed ((string) $3, (ArrayList) $4, (Statement) $7, l);
+         }
+       ;
+
+fixed_pointer_declarators
+       : fixed_pointer_declarator      { 
+               ArrayList declarators = new ArrayList (); 
+               declarators.Add ($1);
+               $$ = declarators;
+         }
+       | fixed_pointer_declarators COMMA fixed_pointer_declarator
+         {
+               ArrayList declarators = (ArrayList) $1;
+               declarators.Add ($3);
+               $$ = declarators;
+         }
+       ;
+
+fixed_pointer_declarator
+       : IDENTIFIER ASSIGN expression
+         {     
+               $$ = new Pair ($1, $3);
+         }
+       ;
+
 lock_statement
-       : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
+       : LOCK OPEN_PARENS expression CLOSE_PARENS 
+         {
+               //
+         } 
+         embedded_statement
          {
-               $$ = new Lock ((Expression) $3, (Statement) $5);
+               $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
          }
        ;
 
 using_statement
-       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
-         // finishme
+       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
+         {
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               oob_stack.Push (lexer.Location);
+               
+               if ($3 is DictionaryEntry){
+                       DictionaryEntry de = (DictionaryEntry) $3;
+                       Location l = lexer.Location;
+
+                       string type = (string) de.Key;
+                       ArrayList var_declarators = (ArrayList) de.Value;
+
+                       foreach (VariableDeclaration decl in var_declarators){
+                               if (current_block.AddVariable (
+                                       type, decl.identifier, 
+                                       current_local_parameters, decl.Location) == null){
+                                       Report.Error (128, decl.Location, 
+                                       "A local variable `" + decl.identifier + "' is already" +
+                                       "defined in this scope");
+                               }
+                       }
+
+                       ArrayList vars = new ArrayList ();
+
+                       foreach (VariableDeclaration decl in var_declarators){
+
+                               Expression expr;
+                               if (decl.expression_or_array_initializer is Expression){
+                                       expr = (Expression) decl.expression_or_array_initializer;
+                                       
+                               } else {
+
+                                       ArrayList init = (ArrayList) decl.expression_or_array_initializer;
+                                       
+                                       string base_type = type.Substring (0, type.IndexOf ("["));
+                                       string rank = type.Substring (type.IndexOf ("["));
+                                       
+                                       expr = new ArrayCreation (base_type, rank, init, decl.Location);
+                               }
+
+                               LocalVariableReference var;
+                               VariableInfo vi;
+
+                               var = new LocalVariableReference (assign_block, decl.identifier, l);
+                               vi = var.VariableInfo;
+                               vi.ReadOnly = true;
+
+                               // This is so that it is not a warning on using variables
+                               vi.Used = true;
+
+                               vars.Add (new DictionaryEntry (var, expr));                             
+
+                               // Assign a = new Assign (var, expr, decl.Location);
+                               // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
+                       }
+                       $3 = new DictionaryEntry (type, vars);
+                }
+         } 
+         embedded_statement
+         {
+               Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
+               current_block.AddStatement (u);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
        ; 
 
 resource_acquisition
        : local_variable_declaration
-         {
-               // FIXME: Add the current block chaining for local_variable_decl
-         }
-         expression
-         // finishme
+       | expression
        ;
 
 %%
@@ -2941,59 +3684,61 @@ MakeName (string class_name)
 //   in the current declaration space
 // </summary>
 void 
-CheckDef (DeclSpace.AdditionResult result, string name)
+CheckDef (AdditionResult result, string name, Location l)
 {
-       if (result == DeclSpace.AdditionResult.Success)
+       if (result == AdditionResult.Success)
                return;
 
-       Location l = lexer.Location;
-       
        switch (result){
-       case DeclSpace.AdditionResult.NameExists:
-               Report.Error (102, l, "The namespace `" + current_container.Name + 
+       case AdditionResult.NameExists:
+               Report.Error (102, l, "The container `" + current_container.Name + 
                                 "' already contains a definition for `"+
                                 name + "'");
                break;
 
 
-//     NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
-//
-//     case DeclSpace.AdditionResult.MethodDuplicated:
-//             error (111, "Class `"+current_container.Name+
-//                         "' already defines a member called '" + 
-//                         name + "' with the same parameter types");
-//             break;
-
-       case DeclSpace.AdditionResult.EnclosingClash:
+               //
+               // This is handled only for static Constructors, because
+               // in reality we handle these by the semantic analysis later
+               //
+       case AdditionResult.MethodExists:
+               Report.Error (
+                       111, l, "Class `"+current_container.Name+
+                       "' already defines a member called '" + 
+                       name + "' with the same parameter types (more than one default constructor)");
+               break;
+
+       case AdditionResult.EnclosingClash:
                Report.Error (542, l, "Member names cannot be the same as their enclosing type");
                break;
                
-       case DeclSpace.AdditionResult.NotAConstructor:
+       case AdditionResult.NotAConstructor:
                Report.Error (1520, l, "Class, struct, or interface method must have a return type");
                break;
        }
 }
 
 void 
-CheckDef (bool result, string name)
+CheckDef (bool result, string name, Location l)
 {
        if (result)
                return;
-       CheckDef (DeclSpace.AdditionResult.NameExists, name);
+       CheckDef (AdditionResult.NameExists, name, l);
 }
 
+//
+// This routine should be removed soon.  I am in the process of making
+// changes to never keep anything but SimpleNames during parsing, as
+// that breaks some kinds of code (documented in the ChangeLog).
+//
 Expression
-SimpleLookup (string name)
+SimpleLookup (string name, Location loc)
 {
        //
        // we need to check against current_block not being null
        // as `expression' is allowed in argument_lists, which 
        // do not exist inside a block.  
        //
-       if (current_block != null){
-               if (current_block.IsVariableDefined (name))
-                       return new LocalVariableReference (current_block, name);
-       }
 
        if (current_local_parameters != null){
                int idx;
@@ -3005,26 +3750,43 @@ SimpleLookup (string name)
        return null;
 }
 
-Expression DecomposeQI (string name, Location l)
+Expression DecomposeQI (string name, Location loc)
 {
        Expression o;
 
        if (name.IndexOf ('.') == -1){
-               o = SimpleLookup (name);
+               o = SimpleLookup (name, loc);
                if (o == null)
-                       return new SimpleName (name, l);
+                       return new SimpleName (name, loc);
                return o;
        } else {
                int pos = name.LastIndexOf (".");
                string left = name.Substring (0, pos);
                string right = name.Substring (pos + 1);
 
-               o = DecomposeQI (left, l);
-               return new MemberAccess (o, right, l);
+               o = DecomposeQI (left, loc);
+               return new MemberAccess (o, right, loc);
        }
 }
 
-Block declare_local_variables (string type, ArrayList variable_declarators)
+// <summary>
+//  This method is used to get at the complete string representation of
+//  a fully-qualified type name, hiding inside a MemberAccess ;-)
+//  This is necessary because local_variable_type admits primary_expression
+//  as the type of the variable. So we do some extra checking
+// </summary>
+string GetQualifiedIdentifier (Expression expr)
+{
+       if (expr is SimpleName)
+               return ((SimpleName)expr).Name;
+       else if (expr is MemberAccess)
+               return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
+       else 
+               throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
+       
+}
+
+Block declare_local_variables (string type, ArrayList variable_declarators, Location loc)
 {
        Block implicit_block;
        ArrayList inits = null;
@@ -3045,20 +3807,20 @@ Block declare_local_variables (string type, ArrayList variable_declarators)
        // int j = 1;  int k = j + 1;
        //
        if (current_block.Used)
-               implicit_block = new Block (current_block, true);
+               implicit_block = new Block (current_block, true, loc, Location.Null);
        else
                implicit_block = current_block;
 
        foreach (VariableDeclaration decl in variable_declarators){
-               if (implicit_block.AddVariable (type, decl.identifier, decl.Location)){
+
+               if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
                        if (decl.expression_or_array_initializer != null){
                                if (inits == null)
                                        inits = new ArrayList ();
                                inits.Add (decl);
                        }
                } else {
-                       Location l = lexer.Location;
-                       Report.Error (128, l, "A local variable `" + decl.identifier +
+                       Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
                                         "' is already defined in this scope");
                }
        }
@@ -3067,30 +3829,49 @@ Block declare_local_variables (string type, ArrayList variable_declarators)
                return implicit_block;
 
        foreach (VariableDeclaration decl in inits){
+               Assign assign;
+               Expression expr;
+               
                if (decl.expression_or_array_initializer is Expression){
-                       Expression expr = (Expression) decl.expression_or_array_initializer;
-                       Assign assign;
-                       
-                       assign = new Assign (new LocalVariableReference (
-                                            implicit_block, decl.identifier), 
-                                            expr, lexer.Location);
-                       implicit_block.AddStatement (new StatementExpression (assign));
+                       expr = (Expression) decl.expression_or_array_initializer;
+
                } else {
-                       Console.WriteLine ("Not handling Array initializers yet");
+                       ArrayList init = (ArrayList) decl.expression_or_array_initializer;
+                       
+                       string base_type = type.Substring (0, type.IndexOf ("["));
+                       string rank = type.Substring (type.IndexOf ("["));
+
+                       expr = new ArrayCreation (base_type, rank, init, decl.Location);
+                       
                }
+
+               LocalVariableReference var;
+               var = new LocalVariableReference (implicit_block, decl.identifier, loc);
+
+               assign = new Assign (var, expr, decl.Location);
+
+               implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
        }
-                       
+       
        return implicit_block;
 }
 
-void CheckConstant (Expression expr)
+Block declare_local_constant (string type, VariableDeclaration decl)
 {
-       // finishme
-}
+       Block implicit_block;
 
-void CheckBoolean (Expression expr)
-{
-       // finishme
+       if (current_block.Used)
+               implicit_block = new Block (current_block, true);
+       else
+               implicit_block = current_block;
+
+       if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
+                                         current_local_parameters, decl.Location))){
+               Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
+                             "' is already defined in this scope");
+       }
+       
+       return implicit_block;
 }
 
 void CheckAttributeTarget (string a)
@@ -3102,7 +3883,7 @@ void CheckAttributeTarget (string a)
                
        default :
                Location l = lexer.Location;
-               Report.Error (658, l, "Invalid attribute target");
+               Report.Error (658, l, "`" + a + "' is an invalid attribute target");
                break;
        }
 
@@ -3161,6 +3942,11 @@ void CheckBinaryOperator (Operator.OpType op)
        
 }
 
+void syntax_error (Location l, string msg)
+{
+       Report.Error (1003, l, "Syntax error, " + msg);
+}
+
 void output (string s)
 {
        Console.WriteLine (s);
@@ -3179,23 +3965,20 @@ public Tokenizer Lexer {
        }
 }                 
 
-public CSharpParser(RootContext rc, string name, System.IO.Stream input)
+public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
 {
        current_namespace = new Namespace (null, "");
-       this.rc = rc;
-       this.tree = rc.Tree;
        this.name = name;
        this.input = input;
-       current_container = tree.Types;
+       current_container = RootContext.Tree.Types;
        current_container.Namespace = current_namespace;
+       oob_stack = new Stack ();
 
-       lexer = new Tokenizer (input, name);
+       lexer = new Tokenizer (input, name, defines);
 }
 
 public override int parse ()
 {
-       StringBuilder value = new StringBuilder ();
-
        global_errors = 0;
        try {
                if (yacc_verbose_flag)
@@ -3206,6 +3989,10 @@ public override int parse ()
                // Console.WriteLine ("Fatal error: " + name);
                // Console.WriteLine (lexer.location);
 
+               // 
+               // Please do not remove this, it is used during debugging
+               // of the grammar
+               //
                Console.WriteLine (lexer.location + "  : Parsing error ");
                Console.WriteLine (e);
                global_errors++;
@@ -3214,6 +4001,5 @@ public override int parse ()
        return global_errors;
 }
 
-
 /* end end end */
 }