Fix typos.
[mono.git] / mcs / mcs / cs-parser.jay
index 0946dd37f6283dfb7c3d308c77fc2ae2ae9f7ba2..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
 //
@@ -89,6 +95,7 @@ namespace Mono.CSharp
 %token ABSTRACT        
 %token AS
 %token ADD
+%token ASSEMBLY
 %token BASE    
 %token BOOL    
 %token BREAK   
@@ -145,6 +152,7 @@ namespace Mono.CSharp
 %token SEALED  
 %token SHORT   
 %token SIZEOF  
+%token STACKALLOC
 %token STATIC  
 %token STRING  
 %token STRUCT  
@@ -249,21 +257,29 @@ namespace Mono.CSharp
 %nonassoc HIGHPREC
 
 %start compilation_unit
-/*%start namespace_declaration */
 %%
 
 compilation_unit
-       : opt_using_directives opt_namespace_member_declarations opt_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
@@ -278,7 +294,7 @@ using_alias_directive
        : USING IDENTIFIER ASSIGN 
          namespace_or_type_name SEMICOLON
          {
-                 current_namespace.UsingAlias ((string) $2, (string) $4);
+                 current_namespace.UsingAlias ((string) $2, (string) $4, lexer.Location);
          }
        ;
 
@@ -289,15 +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 = RootContext.Tree.RecordNamespace (current_namespace, name, (string) $2);
-         } 
+       : 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;
@@ -367,8 +392,10 @@ namespace_member_declaration
                        break;
 
                if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
-                       error (1527, "Namespace elements cant be explicitly " +
-                                    "declared private or protected in `" + name + "'");
+                       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 ((AttributeSection) $1);
-               } else
-                       attrs = new Attributes ((AttributeSection) $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;
          }
@@ -477,12 +527,16 @@ opt_attribute_arguments
 
 
 attribute_arguments
-       : positional_argument_list
+       : opt_positional_argument_list
          {
-               ArrayList args = new ArrayList ();
-               args.Add ($1);
+               if ($1 == null)
+                       $$ = null;
+               else {
+                       ArrayList args = new ArrayList ();
+                       args.Add ($1);
                
-               $$ = args;
+                       $$ = args;
+               }
          }
         | positional_argument_list COMMA named_argument_list
          {
@@ -503,6 +557,11 @@ attribute_arguments
         ;
 
 
+opt_positional_argument_list
+       : /* empty */           { $$ = null; } 
+       | positional_argument_list
+       ;
+
 positional_argument_list
        : expression
          {
@@ -587,7 +646,7 @@ struct_declaration
                                         (Attributes) $1, lexer.Location);
                current_container = new_struct;
                current_container.Namespace = current_namespace;
-               RootContext.Tree.RecordStruct (full_struct_name, new_struct);
+               RootContext.Tree.RecordDecl (full_struct_name, new_struct);
          }
          opt_struct_interfaces
          struct_body
@@ -596,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;
          }
        ;
@@ -656,12 +715,14 @@ constant_declaration
          SEMICOLON
          {
                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,
-                               constant.Location);
+                               (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);
                }
          }
        ;
@@ -699,10 +760,13 @@ field_declaration
                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.Location);
+                                                var.expression_or_array_initializer, 
+                                                (Attributes) $1, l);
 
-                       CheckDef (current_container.AddField (field), field.Name);
+                       CheckDef (current_container.AddField (field), field.Name, l);
                }
          }
        ;
@@ -739,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
@@ -750,18 +818,24 @@ 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;
          }
@@ -926,10 +1000,11 @@ property_declaration
                if (pair.Second != null)
                        set_block = (Block) pair.Second;
 
+               Location loc = (Location) $6;
                prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block,
-                                    (Attributes) $1, (Location) $6);
+                                    (Attributes) $1, loc);
                
-               CheckDef (current_container.AddProperty (prop), prop.Name);
+               CheckDef (current_container.AddProperty (prop), prop.Name, loc);
                implicit_value_parameter_type = null;
          }
        ;
@@ -1008,7 +1083,7 @@ set_accessor_declaration
 
 accessor_body
        : block 
-       | SEMICOLON             { $$ = new Block (null); }
+       | SEMICOLON             { $$ = null; }
        ;
 
 interface_declaration
@@ -1027,10 +1102,10 @@ interface_declaration
                }
                current_interface = new_interface;
                new_interface.Namespace = current_namespace;
-               RootContext.Tree.RecordInterface (full_interface_name, new_interface);
+               RootContext.Tree.RecordDecl (full_interface_name, new_interface);
          }
          opt_interface_base
-         interface_body
+         interface_body opt_semicolon
          { 
                Interface new_interface = (Interface) current_interface;
 
@@ -1038,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);
          }
        ;
 
@@ -1088,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);
          }
        ;
 
@@ -1186,7 +1262,7 @@ interface_indexer_declaration
        ;
 
 operator_declaration
-       : opt_attributes opt_modifiers operator_declarator block
+       : opt_attributes opt_modifiers operator_declarator operator_body
          {
                OperatorDeclaration decl = (OperatorDeclaration) $3;
                
@@ -1200,6 +1276,10 @@ operator_declaration
          }
        ;
 
+operator_body 
+       : block
+       | SEMICOLON { $$ = null; }
+       ; 
 operator_declarator
        : type OPERATOR overloadable_operator 
          OPEN_PARENS type IDENTIFIER CLOSE_PARENS
@@ -1308,7 +1388,7 @@ constructor_declaration
        : opt_attributes
          opt_modifiers
          constructor_declarator
-         block
+         constructor_body
          { 
                Constructor c = (Constructor) $3;
                c.Block = (Block) $4;
@@ -1317,22 +1397,25 @@ constructor_declaration
 
                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 (132, 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;
          }
@@ -1353,6 +1436,11 @@ constructor_declarator
          }
        ;
 
+constructor_body
+       : block
+       | SEMICOLON             { $$ = null; }
+       ;
+
 opt_constructor_initializer
        : /* empty */                   { $$ = null; }
        | constructor_initializer
@@ -1380,11 +1468,13 @@ destructor_declaration
                        Location l = lexer.Location;
 
                        Method d = new Method (
-                               "System.Void", 0, "Finalize", 
+                               "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);
+                       CheckDef (current_container.AddMethod (d), d.Name, d.Location);
                }
          }
        ;
@@ -1399,7 +1489,7 @@ event_declaration
                        Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
                                             (int) $2, null, null, (Attributes) $1, lexer.Location);
 
-                       CheckDef (current_container.AddEvent (e), e.Name);
+                       CheckDef (current_container.AddEvent (e), e.Name, e.Location);
                                       
                }
          }
@@ -1410,6 +1500,7 @@ event_declaration
          {
                implicit_value_parameter_type = (string) $4;  
                lexer.EventParsing = true;
+               oob_stack.Push (lexer.Location);
          }
          event_accessor_declarations
          {
@@ -1417,6 +1508,8 @@ event_declaration
          }
          CLOSE_BRACE
          {
+               Location loc = (Location) oob_stack.Pop ();
+
                Pair pair = (Pair) $8;
                Block add_block = null;
                Block rem_block = null;
@@ -1427,9 +1520,9 @@ event_declaration
                        rem_block = (Block) pair.Second;
                
                Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block,
-                                    (Attributes) $1, lexer.Location);
+                                    (Attributes) $1, loc);
                
-               CheckDef (current_container.AddEvent (e), e.Name);
+               CheckDef (current_container.AddEvent (e), e.Name, loc);
                implicit_value_parameter_type = null;
          }
        ;
@@ -1535,35 +1628,56 @@ indexer_declaration
        ;
 
 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 qualified_identifier 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
          { 
+               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, lexer.Location);
+               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,
-                                                  (Location) ev.Location),
-                                 ev.identifier);
+                                                  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);
+
          }
        ;
 
@@ -1626,11 +1740,13 @@ delegate_declaration
          CLOSE_PARENS 
          SEMICOLON
          {
-               Delegate del = new Delegate ((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
@@ -1640,10 +1756,14 @@ delegate_declaration
          CLOSE_PARENS 
          SEMICOLON
          {
-               Delegate del = new Delegate ("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);
          }
        ;
 
@@ -1700,10 +1820,18 @@ non_expression_type
          {
                $$ = 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
@@ -1747,6 +1875,7 @@ integral_type
        | LONG          { $$ = "System.Int64"; }
        | ULONG         { $$ = "System.UInt64"; }
        | CHAR          { $$ = "System.Char"; }
+       | VOID          { $$ = "System.Void"; }
        ;
 
 interface_type
@@ -1789,6 +1918,9 @@ primary_expression
        | sizeof_expression
        | checked_expression
        | unchecked_expression
+       | pointer_member_access
+       // TODO: pointer_element_access
+       // TODO: sizeof-expression
        ;
 
 literal
@@ -1844,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);
          }
        ;
 
@@ -2004,6 +2136,10 @@ array_creation_expression
          {
                $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
          }
+       | NEW type error 
+         {
+               Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
+         }
        ;
 
 opt_rank_specifier
@@ -2104,7 +2240,7 @@ typeof_expression
 
 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");
@@ -2125,6 +2261,15 @@ 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
        | BANG prefixed_unary_expression
@@ -2350,91 +2495,111 @@ assignment_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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        | 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);
          }
        ;
 
@@ -2468,7 +2633,7 @@ class_declaration
                                       (Attributes) $1, lexer.Location);
                current_container = new_class;
                current_container.Namespace = current_namespace;
-               RootContext.Tree.RecordClass (name, new_class);
+               RootContext.Tree.RecordDecl (name, new_class);
          }
          opt_class_base
          class_body 
@@ -2480,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;
          }
@@ -2520,6 +2685,7 @@ modifier
        | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
        | EXTERN                { $$ = Modifiers.EXTERN; }
        | VOLATILE              { $$ = Modifiers.VOLATILE; }
+       | UNSAFE                { $$ = Modifiers.UNSAFE; }
        ;
 
 opt_class_base
@@ -2547,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;
          }
        ;
@@ -2599,6 +2766,7 @@ embedded_statement
        | lock_statement
        | using_statement
        | unsafe_statement
+       | fixed_statement
        ;
 
 empty_statement
@@ -2738,13 +2906,13 @@ 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 `;'");
          }
@@ -2761,15 +2929,39 @@ 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);
          }
        ;
 
@@ -2795,7 +2987,10 @@ switch_block
        ;
 
 opt_switch_sections
-       : /* empty */           { $$ = new ArrayList (); }
+       : /* empty */           
+          {
+               Report.Error (1522, lexer.Location, "Empty switch block"); 
+         }
        | switch_sections
        ;
 
@@ -2850,6 +3045,11 @@ switch_labels
 switch_label
        : 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
@@ -2860,9 +3060,19 @@ iteration_statement
        ;
 
 while_statement
-       : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
+       : WHILE OPEN_PARENS 
+       {
+               oob_stack.Push (lexer.Location);
+       }
+       boolean_expression CLOSE_PARENS embedded_statement
        {
-               $$ = new While ((Expression) $3, (Statement) $5);
+               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");
+               }
        }
        ;
 
@@ -2870,7 +3080,7 @@ 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);
          }
        ;
 
@@ -2889,13 +3099,15 @@ for_statement
 
                        foreach (VariableDeclaration decl in var_declarators){
 
-                               if (!current_block.AddVariable (type, decl.identifier, current_local_parameters,
-                                                               decl.Location)) {
+                               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");
+                                                     "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){
@@ -2917,18 +3129,26 @@ for_statement
                                        
                                        Assign a = new Assign (var, expr, decl.Location);
                                        
-                                       assign_block.AddStatement (new StatementExpression (a));
+                                       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
          {
-               For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10);
+               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)
@@ -2965,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;
@@ -2986,26 +3207,39 @@ foreach_statement
          }
          expression CLOSE_PARENS 
          {
+               oob_stack.Push (current_block);
+
                Block foreach_block = new Block (current_block, true);
                LocalVariableReference v;
                Location l = lexer.Location;
+               VariableInfo vi;
 
-               foreach_block.AddVariable ((string) $3, (string) $4, current_local_parameters, l);
-               v = new LocalVariableReference (foreach_block, (string) $4, l);
+               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");
+               }
 
-               current_block.AddStatement (foreach_block);
+               v = new LocalVariableReference (foreach_block, (string) $4, l);
                current_block = foreach_block;
 
-               oob_stack.Push (foreach_block);
                oob_stack.Push (v);
+               oob_stack.Push (current_block);
          } 
          embedded_statement 
          {
-               LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
                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 ();
 
-               $$ = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
+               current_block = prev_block;
+
+               Foreach f = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
+               foreach_block.AddStatement (f);
+
+               $$ = foreach_block;
          }
        ;
 
@@ -3087,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
@@ -3196,11 +3437,79 @@ unchecked_statement
        ;
 
 unsafe_statement
-       : UNSAFE block
+       : UNSAFE 
        {
-               $$ = new Unsafe ((Block) $2);
+               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 
@@ -3229,8 +3538,9 @@ using_statement
                        ArrayList var_declarators = (ArrayList) de.Value;
 
                        foreach (VariableDeclaration decl in var_declarators){
-                               if (!current_block.AddVariable (type, decl.identifier, current_local_parameters,
-                                                               decl.Location)){
+                               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");
@@ -3268,7 +3578,7 @@ using_statement
                                vars.Add (new DictionaryEntry (var, expr));                             
 
                                // Assign a = new Assign (var, expr, decl.Location);
-                               // assign_block.AddStatement (new StatementExpression (a));
+                               // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
                        }
                        $3 = new DictionaryEntry (type, vars);
                 }
@@ -3374,16 +3684,14 @@ MakeName (string class_name)
 //   in the current declaration space
 // </summary>
 void 
-CheckDef (AdditionResult result, string name)
+CheckDef (AdditionResult result, string name, Location l)
 {
        if (result == AdditionResult.Success)
                return;
 
-       Location l = lexer.Location;
-       
        switch (result){
        case AdditionResult.NameExists:
-               Report.Error (102, l, "The namespace `" + current_container.Name + 
+               Report.Error (102, l, "The container `" + current_container.Name + 
                                 "' already contains a definition for `"+
                                 name + "'");
                break;
@@ -3411,13 +3719,18 @@ CheckDef (AdditionResult result, string name)
 }
 
 void 
-CheckDef (bool result, string name)
+CheckDef (bool result, string name, Location l)
 {
        if (result)
                return;
-       CheckDef (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, Location loc)
 {
@@ -3426,10 +3739,6 @@ SimpleLookup (string name, Location loc)
        // 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, loc);
-       }
 
        if (current_local_parameters != null){
                int idx;
@@ -3498,13 +3807,13 @@ Block declare_local_variables (string type, ArrayList variable_declarators, Loca
        // 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, current_local_parameters, 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 ();
@@ -3541,7 +3850,7 @@ Block declare_local_variables (string type, ArrayList variable_declarators, Loca
 
                assign = new Assign (var, expr, decl.Location);
 
-               implicit_block.AddStatement (new StatementExpression (assign));
+               implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
        }
        
        return implicit_block;
@@ -3574,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;
        }
 
@@ -3670,8 +3979,6 @@ public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
 
 public override int parse ()
 {
-       StringBuilder value = new StringBuilder ();
-
        global_errors = 0;
        try {
                if (yacc_verbose_flag)