2001-10-04 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
index 1373998e72333281dbd809ebe006b8f019fe564b..1b546238bf049a033fd610de63ce0ab82b573f84 100755 (executable)
-%{\r
-//\r
-// cs-parser.jay: The Parser for the C# compiler\r
-//\r
-// Author: Miguel de Icaza (miguel@gnu.org)\r
-//\r
-// Licensed under the terms of the GNU GPL\r
-//\r
-// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
-//\r
-// TODO:\r
-//   (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM\r
-//       And come to think of it, it is not that great, it duplicates a lot of code\r
-//       for something which is not really needed.  We still have piles of typecasts\r
-//       anwyays (due to the nature of the stack being a collection of Objects).\r
-//\r
-//   (2) Figure out why error productions dont work.  `type-declaration' is a\r
-//       great spot to put an `error' because you can reproduce it with this input:\r
-//      "public X { }"\r
-//\r
-//   (3) Move Modifier checking from each object into the parser itself, that will\r
-//       get rid of the global "error" symbol that we use now to report errors. \r
-//       We still need to pass a pointer to the tree.ErrorHandler, but that is a \r
-//      separate problem\r
-//\r
-using System.Text;\r
-using CSC;\r
-using System;\r
-\r
-namespace CSC\r
-{\r
-       using System.Collections;\r
-       using CSC;\r
-       using CIR;\r
-\r
-       /// <summary>\r
-       ///    The C# Parser\r
-       /// </summary>\r
-       public class CSharpParser {\r
-               static int global_errors;\r
-\r
-               Namespace     current_namespace;\r
-               TypeContainer current_container;\r
-       \r
-               // <summary>\r
-               //   Current block is used to add statements as we find\r
-               //   them.  \r
-               // </summary>\r
-\r
-               Block      current_block;\r
-\r
-               // <summary>\r
-               //   Current interface is used by the various declaration\r
-               //   productions in the interface declaration to "add"\r
-               //   the interfaces as we find them.\r
-               // </summary>\r
-               Interface  current_interface;\r
-\r
-               // <summary>\r
-               //   This is used by the unary_expression code to resolve\r
-               //   a name against a parameter.  \r
-               // </summary>\r
-               Parameters current_local_parameters;\r
-\r
-               // <summary>\r
-               //   Using during property parsing to describe the implicit\r
-               //   value parameter that is passed to the "set" accesor\r
-               //   method\r
-               // </summary>\r
-               ParameterCollection implicit_value_parameters;\r
-\r
-               // <summary>\r
-               //   Here we keep track of type references. \r
-               // </summary>\r
-               TypeRefManager type_references;\r
-\r
-               // <summary>\r
-               //   Used to record all types defined\r
-               // </summary>\r
-               CIR.Tree tree;\r
-\r
-               // Name of the file we are parsing\r
-               public string name;\r
-\r
-               // Input stream to parse from.\r
-               public System.IO.Stream input;\r
-\r
-%}\r
-\r
-%token EOF\r
-%token NONE   /* This token is never returned by our lexer */\r
-%token ERROR           // This is used not by the parser, but by the tokenizer.\r
-                       // do not remove.\r
-\r
-/*\r
- *These are the C# keywords\r
- */\r
-%token ABSTRACT        \r
-%token AS\r
-%token ADD\r
-%token BASE    \r
-%token BOOL    \r
-%token BREAK   \r
-%token BYTE    \r
-%token CASE    \r
-%token CATCH   \r
-%token CHAR    \r
-%token CHECKED \r
-%token CLASS   \r
-%token CONST   \r
-%token CONTINUE        \r
-%token DECIMAL \r
-%token DEFAULT \r
-%token DELEGATE        \r
-%token DO      \r
-%token DOUBLE  \r
-%token ELSE    \r
-%token ENUM    \r
-%token EVENT   \r
-%token EXPLICIT        \r
-%token EXTERN  \r
-%token FALSE   \r
-%token FINALLY \r
-%token FIXED   \r
-%token FLOAT   \r
-%token FOR     \r
-%token FOREACH \r
-%token GOTO    \r
-%token IF      \r
-%token IMPLICIT        \r
-%token IN      \r
-%token INT     \r
-%token INTERFACE\r
-%token INTERNAL        \r
-%token IS      \r
-%token LOCK    \r
-%token LONG    \r
-%token NAMESPACE\r
-%token NEW     \r
-%token NULL    \r
-%token OBJECT  \r
-%token OPERATOR        \r
-%token OUT     \r
-%token OVERRIDE        \r
-%token PARAMS  \r
-%token PRIVATE \r
-%token PROTECTED\r
-%token PUBLIC  \r
-%token READONLY        \r
-%token REF     \r
-%token RETURN  \r
-%token REMOVE\r
-%token SBYTE   \r
-%token SEALED  \r
-%token SHORT   \r
-%token SIZEOF  \r
-%token STATIC  \r
-%token STRING  \r
-%token STRUCT  \r
-%token SWITCH  \r
-%token THIS    \r
-%token THROW   \r
-%token TRUE    \r
-%token TRY     \r
-%token TYPEOF  \r
-%token UINT    \r
-%token ULONG   \r
-%token UNCHECKED\r
-%token UNSAFE  \r
-%token USHORT  \r
-%token USING   \r
-%token VIRTUAL \r
-%token VOID    \r
-%token WHILE   \r
-\r
-/* C# keywords which are not really keywords */\r
-%token GET           "get"\r
-%token SET           "set"\r
-\r
-/* C# single character operators/punctuation. */\r
-%token OPEN_BRACE    "{"\r
-%token CLOSE_BRACE   "}"\r
-%token OPEN_BRACKET  "["\r
-%token CLOSE_BRACKET "]"\r
-%token OPEN_PARENS   "("\r
-%token CLOSE_PARENS  ")"\r
-%token DOT           "."\r
-%token COMMA         ","\r
-%token COLON         ":"\r
-%token SEMICOLON     ";"\r
-%token TILDE         "~"\r
-\r
-%token PLUS           "+"\r
-%token MINUS          "-"\r
-%token BANG           "!"\r
-%token ASSIGN         "="\r
-%token OP_LT          "<"\r
-%token OP_GT          ">"\r
-%token BITWISE_AND    "&"\r
-%token BITWISE_OR     "|"\r
-%token STAR           "*"\r
-%token PERCENT        "%"\r
-%token DIV            "/"\r
-%token CARRET         "^"\r
-%token INTERR         "?"\r
-\r
-/* C# multi-character operators. */\r
-%token OP_INC                 "++"\r
-%token OP_DEC                 "--"\r
-%token OP_SHIFT_LEFT          "<<"\r
-%token OP_SHIFT_RIGHT         ">>"\r
-%token OP_LE                  "<="\r
-%token OP_GE                  ">="\r
-%token OP_EQ                  "=="\r
-%token OP_NE                  "!="\r
-%token OP_AND                 "&&"\r
-%token OP_OR                  "||"\r
-%token OP_MULT_ASSIGN         "*="\r
-%token OP_DIV_ASSIGN          "/="\r
-%token OP_MOD_ASSIGN          "%="\r
-%token OP_ADD_ASSIGN          "+="\r
-%token OP_SUB_ASSIGN          "-="\r
-%token OP_SHIFT_LEFT_ASSIGN   "<<="\r
-%token OP_SHIFT_RIGHT_ASSIGN  ">>="\r
-%token OP_AND_ASSIGN          "&="\r
-%token OP_XOR_ASSIGN          "^="\r
-%token OP_OR_ASSIGN           "|="\r
-%token OP_PTR                 "->"\r
-\r
-/* Numbers */\r
-%token LITERAL_INTEGER           "int literal"\r
-%token LITERAL_FLOAT             "float literal"\r
-%token LITERAL_DOUBLE            "double literal"\r
-%token LITERAL_DECIMAL           "decimal literal"\r
-%token LITERAL_CHARACTER         "character literal"\r
-%token LITERAL_STRING            "string literal"\r
-\r
-%token IDENTIFIER\r
-\r
-/* Add precedence rules to solve dangling else s/r conflict */\r
-%nonassoc LOWPREC\r
-%nonassoc IF\r
-%nonassoc ELSE\r
-%right ASSIGN\r
-%left OP_OR\r
-%left OP_AND\r
-%left BITWISE_OR\r
-%left BITWISE_AND\r
-%left OP_SHIFT_LEFT OP_SHIFT_RIGHT\r
-%left PLUS MINUS\r
-%left STAR DIV PERCENT\r
-%right BANG CARRET UMINUS\r
-%nonassoc OP_INC OP_DEC\r
-%left OPEN_PARENS\r
-%left OPEN_BRACKET OPEN_BRACE\r
-%left DOT\r
-%nonassoc HIGHPREC\r
-\r
-%start compilation_unit\r
-/*%start namespace_declaration */\r
-%%\r
-\r
-compilation_unit\r
-       : opt_using_directives opt_attributes opt_namespace_member_declarations \r
-         EOF\r
-         {\r
-               // At some point check that using only comes *before* any namespaces\r
-         }\r
-       ;\r
-\r
-using_directives\r
-       : using_directive \r
-       | using_directives using_directive \r
-       ;\r
-\r
-using_directive\r
-       : using_alias_directive\r
-       | using_namespace_directive\r
-       ;\r
-\r
-using_alias_directive\r
-       : USING IDENTIFIER ASSIGN \r
-         namespace_or_type_name SEMICOLON {\r
-         }\r
-       ;\r
-\r
-using_namespace_directive\r
-       : USING namespace_name SEMICOLON \r
-         {\r
-               current_namespace.Using ((string) $2);\r
-          }\r
-       ;\r
-\r
-namespace_declarations\r
-       : namespace_declaration\r
-       | namespace_declarations namespace_declaration\r
-\r
-namespace_declaration\r
-       : NAMESPACE qualified_identifier \r
-         {\r
-               current_namespace = new Namespace (current_namespace, (string) $2); \r
-         } \r
-         namespace_body opt_semicolon\r
-         { \r
-               current_namespace = current_namespace.Parent;\r
-         }\r
-       ;\r
-\r
-opt_semicolon\r
-       : /* empty */\r
-       | SEMICOLON\r
-       ;\r
-\r
-opt_comma\r
-       : /* empty */\r
-       | COMMA\r
-       ;\r
-\r
-qualified_identifier\r
-       : IDENTIFIER\r
-       | qualified_identifier DOT IDENTIFIER { \r
-           $$ = (($1).ToString ()) + "." + ($3.ToString ()); }\r
-       ;\r
-\r
-\r
-namespace_name\r
-       : namespace_or_type_name\r
-       ;\r
-\r
-namespace_body\r
-       : OPEN_BRACE\r
-         opt_using_directives\r
-         opt_namespace_member_declarations\r
-         CLOSE_BRACE {\r
-         }\r
-       ;\r
-\r
-opt_using_directives\r
-       : /* empty */\r
-       | using_directives\r
-       ;\r
-\r
-opt_namespace_member_declarations\r
-       : /* empty */\r
-       | namespace_member_declarations\r
-       ;\r
-\r
-namespace_member_declarations\r
-       : namespace_member_declaration\r
-       | namespace_member_declarations namespace_member_declaration\r
-       ;\r
-\r
-namespace_member_declaration\r
-       : type_declaration\r
-         {\r
-               int mod_flags = 0;\r
-               string name = "";\r
-\r
-               if ($1 is Class){\r
-                       Class c = (Class) $1;\r
-                       mod_flags = c.ModFlags;\r
-                       name = c.Name;\r
-               } else if ($1 is Struct){\r
-                       Struct s = (Struct) $1;\r
-                       mod_flags = s.ModFlags;\r
-                       name = s.Name;\r
-               } else\r
-                       break;\r
-\r
-               //\r
-               // We remove this error until we can \r
-               //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){\r
-               //      error (1527, "Namespace elements cant be explicitly " +\r
-               //                   "declared private or protected in `" + name + "'");\r
-               //}\r
-         }\r
-       | namespace_declaration\r
-       ;\r
-\r
-type_declaration\r
-       : class_declaration             \r
-       | struct_declaration            \r
-       | interface_declaration         \r
-       | enum_declaration              \r
-       | delegate_declaration          // finishme\r
-       ;\r
-\r
-//\r
-// Attributes 17.2\r
-//\r
-opt_attributes\r
-       : /* empty */\r
-       | attribute_section opt_attributes\r
-       ;\r
-\r
-attribute_section\r
-       : OPEN_BRACKET\r
-         opt_attribute_target_specifier attribute_list \r
-         /* FIXME: opt_comma */ \r
-         CLOSE_BRACKET \r
-       ;\r
-\r
-opt_attribute_target_specifier\r
-       : /* empty */\r
-       | attribute_target_specifier\r
-       ;\r
-\r
-attribute_target_specifier\r
-       : attribute_target COLON\r
-       ;\r
-\r
-attribute_target\r
-       : IDENTIFIER  { \r
-            // if (Collection.Contains ($$))... FIXME\r
-            note  ("Allows: assembly, field, method, module, param, property, type"); \r
-       }\r
-       | EVENT\r
-       | RETURN \r
-       ;\r
-\r
-attribute_list\r
-       : attribute\r
-       | attribute_list COMMA attribute\r
-       ;\r
-\r
-attribute\r
-       : attribute_name\r
-       | opt_attribute_arguments\r
-       ;\r
-\r
-attribute_name\r
-       : type_name             { /* reserved attribute name or identifier: 17.4 */ }\r
-       ;\r
-\r
-opt_attribute_arguments\r
-       : /* empty */\r
-       | OPEN_PARENS attribute_arguments CLOSE_PARENS\r
-       ;\r
-\r
-attribute_arguments\r
-       : expression\r
-       | attribute_arguments COMMA expression\r
-       ;\r
-\r
-\r
-opt_dimension_separators\r
-       : /* empty */\r
-       | dimension_separators\r
-       ;\r
-\r
-dimension_separators\r
-       : COMMA \r
-       | dimension_separators COMMA \r
-       ;\r
-\r
-class_body\r
-       :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE\r
-       ;\r
-\r
-opt_class_member_declarations\r
-       : /* empty */\r
-       | class_member_declarations\r
-       ;\r
-\r
-class_member_declarations\r
-       : class_member_declaration\r
-       | class_member_declarations \r
-         class_member_declaration\r
-       ;\r
-\r
-class_member_declaration\r
-       : constant_declaration                  // done\r
-       | field_declaration                     // done\r
-       | method_declaration                    // done\r
-       | property_declaration                  // done\r
-       | event_declaration                     // finishme\r
-       | indexer_declaration                   // finishme\r
-       | operator_declaration                  // finishme\r
-       | constructor_declaration               // done\r
-       | destructor_declaration                // done\r
-       | type_declaration\r
-       ;\r
-\r
-struct_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         STRUCT IDENTIFIER\r
-         { \r
-               Struct new_struct;\r
-               string full_struct_name = MakeName ((string) $4);\r
-\r
-               new_struct = new Struct (current_container, full_struct_name, (int) $2);\r
-               current_container = new_struct;\r
-               current_container.Namespace = current_namespace;\r
-               tree.RecordType (full_struct_name, new_struct);\r
-         }\r
-         opt_struct_interfaces\r
-         struct_body\r
-         opt_semicolon\r
-         {\r
-               Struct new_struct = (Struct) current_container;\r
-\r
-               current_container = current_container.Parent;\r
-               CheckDef (current_container.AddStruct (new_struct), new_struct.Name);\r
-               $$ = new_struct;\r
-         }\r
-       ;\r
-\r
-opt_struct_interfaces\r
-       : /* empty */\r
-       | struct_interfaces\r
-       ;\r
-\r
-struct_interfaces\r
-       : struct_interface\r
-       | struct_interfaces struct_interface\r
-       ; \r
-\r
-struct_interface\r
-       : COLON type_list\r
-       ;\r
-\r
-struct_body\r
-       : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE\r
-       ;\r
-\r
-opt_struct_member_declarations\r
-       : /* empty */\r
-       | struct_member_declarations\r
-       ;\r
-\r
-struct_member_declarations\r
-       : struct_member_declaration\r
-       | struct_member_declarations struct_member_declaration\r
-       ;\r
-\r
-struct_member_declaration\r
-       : constant_declaration\r
-       | field_declaration\r
-       | method_declaration\r
-       | property_declaration\r
-       | event_declaration\r
-       | indexer_declaration\r
-       | operator_declaration\r
-       | constructor_declaration\r
-       | type_declaration\r
-       ;\r
-\r
-constant_declaration\r
-       : opt_attributes \r
-         opt_modifiers\r
-         CONST\r
-         type\r
-         constant_declarators\r
-         SEMICOLON\r
-         { \r
-               Modifiers.Check (Constant.AllowedModifiers, (int) $2, Modifiers.PRIVATE);\r
-\r
-               foreach (DictionaryEntry constant in (ArrayList) $5){\r
-                       Constant c = new Constant (\r
-                               (TypeRef) $4, (string) constant.Key, \r
-                               (Expression) constant.Value);\r
-\r
-                       CheckDef (current_container.AddConstant (c), c.Name);\r
-               }\r
-         }\r
-       ;\r
-\r
-constant_declarators\r
-       : constant_declarator \r
-         {\r
-               ArrayList constants = new ArrayList ();\r
-               constants.Add ($1);\r
-               $$ = constants;\r
-         }\r
-       | constant_declarators COMMA constant_declarator\r
-         {\r
-               ArrayList constants = (ArrayList) $1;\r
-\r
-               constants.Add ($3);\r
-         }\r
-       ;\r
-\r
-constant_declarator\r
-       : IDENTIFIER ASSIGN constant_expression {\r
-               $$ = new DictionaryEntry ($1, $3);\r
-         }\r
-       ;\r
-\r
-field_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         type \r
-         variable_declarators\r
-         SEMICOLON\r
-       { \r
-               TypeRef typeref = (TypeRef) $3;\r
-               int mod = (int) $2;\r
-\r
-               foreach (VariableDeclaration var in (ArrayList) $4){\r
-                       Field field = new Field (typeref, mod, var.identifier, \r
-                                                var.expression_or_array_initializer);\r
-\r
-                       CheckDef (current_container.AddField (field), field.Name);\r
-               }\r
-       }\r
-\r
-       ;\r
-\r
-variable_declarators\r
-       : variable_declarator \r
-         {\r
-               ArrayList decl = new ArrayList ();\r
-               $$ = decl;\r
-               decl.Add ($1);\r
-         }\r
-       | variable_declarators COMMA variable_declarator\r
-         {\r
-               ArrayList decls = (ArrayList) $1;\r
-               decls.Add ($3);\r
-               $$ = $1;\r
-         }\r
-       ;\r
-\r
-variable_declarator\r
-       : IDENTIFIER ASSIGN variable_initializer\r
-         {\r
-               $$ = new VariableDeclaration ((string) $1, $3);\r
-         }\r
-       | IDENTIFIER\r
-         {\r
-               $$ = new VariableDeclaration ((string) $1, null);\r
-         }\r
-       ;\r
-\r
-variable_initializer\r
-       : expression\r
-       | array_initializer\r
-       ;\r
-\r
-method_declaration\r
-       : method_header\r
-         method_body\r
-         {\r
-               Method method = (Method) $1;\r
-\r
-               method.Block = (Block) $2;\r
-               CheckDef (current_container.AddMethod (method), method.Name);\r
-\r
-               current_local_parameters = null;\r
-         }\r
-       ;\r
-\r
-method_header\r
-       : opt_attributes\r
-         opt_modifiers\r
-         type\r
-         member_name\r
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
-         {\r
-               Method method = new Method ((TypeRef) $3, (int) $2, (string) $4, (Parameters) $6);\r
-\r
-               current_local_parameters = (Parameters) $6;\r
-\r
-               $$ = method;\r
-         }\r
-       | opt_attributes\r
-         opt_modifiers\r
-         VOID\r
-         member_name\r
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
-         {\r
-               Method method = new Method (type ("void"), (int) $2, (string) $4, (Parameters) $6);\r
-\r
-               current_local_parameters = (Parameters) $6;\r
-               $$ = method;\r
-         }\r
-       ;\r
-\r
-method_body\r
-       : block\r
-       | SEMICOLON             { $$ = null; }\r
-       ;\r
-\r
-opt_formal_parameter_list\r
-       : /* empty */                   { $$ = new Parameters (null, null); }\r
-       | formal_parameter_list\r
-       ;\r
-\r
-formal_parameter_list\r
-       : fixed_parameters              \r
-         { \r
-               $$ = new Parameters ((ParameterCollection) $1, null); \r
-         } \r
-       | fixed_parameters COMMA parameter_array\r
-         {\r
-               $$ = new Parameters ((ParameterCollection) $1, (Parameter) $3); \r
-         }\r
-       | parameter_array \r
-         {\r
-               $$ = new Parameters (null, (Parameter) $1);\r
-         }\r
-       ;\r
-\r
-fixed_parameters\r
-       : fixed_parameter       \r
-         {\r
-               ParameterCollection pars = new ParameterCollection ();\r
-               pars.Add ((Parameter) $1);\r
-               $$ = pars;\r
-         }\r
-       | fixed_parameters COMMA fixed_parameter\r
-         {\r
-               ParameterCollection pars = (ParameterCollection) $1;\r
-               pars.Add ((Parameter) $3);\r
-               $$ = $1;\r
-         }\r
-       ;\r
-\r
-fixed_parameter\r
-       : opt_attributes\r
-         opt_parameter_modifier\r
-         type\r
-         IDENTIFIER\r
-         {\r
-               $$ = new Parameter ((TypeRef) $3, (string) $4, (Parameter.Modifier) $2);\r
-         }\r
-       ;\r
-\r
-opt_parameter_modifier\r
-       : /* empty */           { $$ = Parameter.Modifier.NONE; }\r
-       | parameter_modifier\r
-       ;\r
-\r
-parameter_modifier\r
-       : REF                   { $$ = Parameter.Modifier.REF; }\r
-       | OUT                   { $$ = Parameter.Modifier.OUT; }\r
-       ;\r
-\r
-parameter_array\r
-       : opt_attributes PARAMS type IDENTIFIER\r
-         { \r
-               $$ = new Parameter ((TypeRef) $3, (string) $4, Parameter.Modifier.PARAMS);\r
-               note ("type must be a single-dimension array type"); \r
-         }\r
-       ;\r
-\r
-member_name \r
-       : IDENTIFIER { $$ = $1.ToString (); }\r
-       | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }\r
-       ;\r
-\r
-property_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         type member_name\r
-         OPEN_BRACE \r
-         {\r
-               Parameter implicit_value_parameter;\r
-               implicit_value_parameter = new Parameter ((TypeRef) $3, "value", Parameter.Modifier.NONE);\r
-\r
-               lexer.properties = true;\r
-               \r
-               implicit_value_parameters = new ParameterCollection ();\r
-               implicit_value_parameters.Add (implicit_value_parameter);\r
-         }\r
-         accessor_declarations \r
-         {\r
-               lexer.properties = false;\r
-         }\r
-         CLOSE_BRACE\r
-         { \r
-               Property prop;\r
-               DictionaryEntry pair = (DictionaryEntry) $7;\r
-               Block get_block = null;\r
-               Block set_block = null;\r
-\r
-               if (pair.Key != null)\r
-                       get_block = (Block) pair.Key;\r
-               if (pair.Value != null)\r
-                       set_block = (Block) pair.Value;\r
-\r
-               prop = new Property ((TypeRef) $3, (string) $4, (int) $2, get_block, set_block);\r
-               \r
-               CheckDef (current_container.AddProperty (prop), prop.Name);\r
-               implicit_value_parameters = null;\r
-         }\r
-       ;\r
-\r
-accessor_declarations\r
-       : get_accessor_declaration opt_set_accessor_declaration\r
-         { \r
-               $$ = new DictionaryEntry ($1, $2);\r
-         }\r
-       | set_accessor_declaration opt_get_accessor_declaration\r
-         {\r
-               $$ = new DictionaryEntry ($2, $1);\r
-         }\r
-       ;\r
-\r
-opt_get_accessor_declaration\r
-       : /* empty */                   { $$ = null; }\r
-       | get_accessor_declaration\r
-       ;\r
-\r
-opt_set_accessor_declaration\r
-       : /* empty */                   { $$ = null; }\r
-       | set_accessor_declaration\r
-       ;\r
-\r
-get_accessor_declaration\r
-       : opt_attributes GET accessor_body \r
-         {\r
-               $$ = $3;\r
-         }\r
-       ;\r
-\r
-set_accessor_declaration\r
-       : opt_attributes SET \r
-         { \r
-               current_local_parameters = new Parameters (implicit_value_parameters, null);\r
-         }\r
-         accessor_body\r
-         {\r
-               $$ = $4;\r
-               current_local_parameters = null;\r
-         }\r
-       ;\r
-\r
-accessor_body\r
-       : block \r
-       | SEMICOLON             { $$ = new Block (null); }\r
-       ;\r
-\r
-interface_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         INTERFACE IDENTIFIER\r
-         {\r
-               Interface new_interface;\r
-               string full_interface_name = MakeName ((string) $4);\r
-\r
-               new_interface = new Interface (current_container, full_interface_name, (int) $2);\r
-               if (current_interface != null)\r
-                       error (-2, "Internal compiler error: interface inside interface");\r
-               current_interface = new_interface;\r
-               tree.RecordType (full_interface_name, new_interface);\r
-         }\r
-         opt_interface_base\r
-         interface_body\r
-         { \r
-               Interface new_interface = (Interface) current_interface;\r
-\r
-               if ($6 != null)\r
-                       new_interface.Bases = (ArrayList) $6;\r
-\r
-               current_interface = null;\r
-               CheckDef (current_container.AddInterface (new_interface), new_interface.Name);\r
-         }\r
-       ;\r
-\r
-opt_interface_base\r
-       : /* empty */                     { $$ = null; }\r
-       | interface_base\r
-       ;\r
-\r
-interface_base\r
-       : COLON interface_type_list       { $$ = $2; }\r
-       ;\r
-\r
-interface_type_list\r
-       : interface_type\r
-         {\r
-               ArrayList interfaces = new ArrayList ();\r
-\r
-               interfaces.Add ($1);\r
-         }\r
-       | interface_type_list COMMA interface_type\r
-         {\r
-               ArrayList interfaces = (ArrayList) $1;\r
-               interfaces.Add ($3);\r
-               $$ = interfaces;\r
-         }\r
-       ;\r
-\r
-interface_body\r
-       : OPEN_BRACE\r
-         opt_interface_member_declarations\r
-         CLOSE_BRACE\r
-       ;\r
-\r
-opt_interface_member_declarations\r
-       : /* empty */\r
-       | interface_member_declarations\r
-       ;\r
-\r
-interface_member_declarations\r
-       : interface_member_declaration\r
-       | interface_member_declarations interface_member_declaration\r
-       ;\r
-\r
-interface_member_declaration\r
-       : interface_method_declaration          \r
-         { \r
-               InterfaceMethod m = (InterfaceMethod) $1;\r
-\r
-               CheckDef (current_interface.AddMethod (m), m.Name);\r
-         }\r
-       | interface_property_declaration        \r
-         { \r
-               InterfaceProperty p = (InterfaceProperty) $1;\r
-\r
-               CheckDef (current_interface.AddProperty (p), p.Name);\r
-          }\r
-       | interface_event_declaration \r
-          { \r
-               InterfaceEvent e = (InterfaceEvent) $1;\r
-\r
-               CheckDef (current_interface.AddEvent (e), e.Name);\r
-         }\r
-       | interface_indexer_declaration\r
-         { \r
-               InterfaceIndexer i = (InterfaceIndexer) $1;\r
-\r
-               CheckDef (current_interface.AddIndexer (i), "indexer");\r
-         }\r
-       ;\r
-\r
-opt_new\r
-       : /* empty */   { $$ = false; }\r
-       | NEW           { $$ = true; }\r
-       ;\r
-\r
-interface_method_declaration\r
-       : opt_attributes opt_new type IDENTIFIER \r
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS\r
-         SEMICOLON\r
-         {\r
-               $$ = new InterfaceMethod ((TypeRef) $3, (string) $4, (bool) $2, (Parameters) $6);\r
-         }\r
-       | opt_attributes opt_new VOID IDENTIFIER \r
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS\r
-         SEMICOLON\r
-         {\r
-               $$ = new InterfaceMethod (type ("void"), (string) $4, (bool) $2, (Parameters) $6);\r
-         }\r
-       ;\r
-\r
-interface_property_declaration\r
-       : opt_attributes\r
-         opt_new\r
-         type IDENTIFIER \r
-         OPEN_BRACE \r
-         { lexer.properties = true; }\r
-         interface_accesors \r
-         { lexer.properties = false; }\r
-         CLOSE_BRACE\r
-         {\r
-               int gs = (int) $7;\r
-\r
-               $$ = new InterfaceProperty ((TypeRef) $3, (string) $4, (bool) $2, \r
-                                           (gs & 1) == 1, (gs & 2) == 2);\r
-         }\r
-       ;\r
-\r
-interface_accesors\r
-       : opt_attributes GET SEMICOLON          { $$ = 1; }\r
-       | opt_attributes SET SEMICOLON          { $$ = 2; }\r
-       | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON \r
-         { $$ = 3; }\r
-       | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON\r
-         { $$ = 3; }\r
-       ;\r
-\r
-interface_event_declaration\r
-       : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON\r
-         {\r
-               $$ = new InterfaceEvent ((TypeRef) $4, (string) $5, (bool) $2);\r
-         }\r
-       ;\r
-\r
-interface_indexer_declaration \r
-       : opt_attributes opt_new type THIS \r
-         OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
-         OPEN_BRACE \r
-         { lexer.properties = true; }\r
-         interface_accesors \r
-         { lexer.properties = false; }\r
-         CLOSE_BRACE\r
-         {\r
-               int a_flags = (int) $10;\r
-\r
-               bool do_get = (a_flags & 1) == 1;\r
-               bool do_set = (a_flags & 2) == 2;\r
-\r
-               $$ = new InterfaceIndexer ((TypeRef) $3, (Parameters) $6, do_get, do_set, (bool) $2);\r
-         }\r
-       ;\r
-\r
-operator_declaration\r
-       : opt_attributes opt_modifiers operator_declarator block\r
-         {\r
-               // FIXME: validate that opt_modifiers is exactly: PUBLIC and STATIC\r
-         }\r
-       ;\r
-\r
-operator_declarator\r
-       : type OPERATOR overloadable_operator \r
-         OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
-         {\r
-               // FIXME: since reduce/reduce on this\r
-               // rule, validate overloadable_operator is unary\r
-         }\r
-       | type OPERATOR overloadable_operator\r
-         OPEN_PARENS \r
-               type IDENTIFIER COMMA\r
-               type IDENTIFIER \r
-         CLOSE_PARENS\r
-         {\r
-               // FIXME: because of the reduce/reduce on PLUS and MINUS\r
-               // validate overloadable_operator is binary\r
-         }\r
-       | conversion_operator_declarator\r
-       ;\r
-\r
-overloadable_operator\r
-// Unary operators:\r
-       : BANG\r
-       | TILDE\r
-       | OP_INC\r
-       | OP_DEC\r
-       | TRUE\r
-       | FALSE\r
-// Unary and binary:\r
-       | PLUS \r
-       | MINUS\r
-// Binary:\r
-       | STAR \r
-       | DIV \r
-       | PERCENT \r
-       | BITWISE_AND \r
-       | BITWISE_OR \r
-       | CARRET \r
-       | OP_SHIFT_LEFT\r
-       | OP_SHIFT_RIGHT\r
-       | OP_EQ\r
-       | OP_NE\r
-       | OP_GT\r
-       | OP_LT\r
-       | OP_GE\r
-       | OP_LE\r
-       ;\r
-\r
-conversion_operator_declarator\r
-       : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
-       | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
-       ;\r
-\r
-constructor_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         constructor_declarator\r
-         block\r
-         { \r
-               Constructor c = (Constructor) $3;\r
-               c.Block = (Block) $4;\r
-               c.ModFlags = (int) $2;\r
-\r
-               if ((c.ModFlags & Modifiers.STATIC) != 0){\r
-                       if ((c.ModFlags & Modifiers.Accessibility) != 0){\r
-                               error (515, "Access modifiers are not allowed on static constructors");\r
-                       }\r
-               }\r
-               CheckDef (current_container.AddConstructor (c), c.Name);\r
-\r
-               current_local_parameters = null;\r
-         }\r
-       ;\r
-\r
-constructor_declarator\r
-       : IDENTIFIER \r
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
-         opt_constructor_initializer\r
-         {\r
-               ConstructorInitializer i = null;\r
-\r
-               if ($5 != null)\r
-                       i = (ConstructorInitializer) $5;\r
-\r
-               $$ = new Constructor ((string) $1, (Parameters) $3, i);\r
-       \r
-               current_local_parameters = (Parameters) $3;\r
-         }\r
-       ;\r
-\r
-opt_constructor_initializer\r
-       : /* empty */                   { $$ = null; }\r
-       | constructor_initializer\r
-       ;\r
-\r
-constructor_initializer\r
-       : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS\r
-         {\r
-               $$ = new ConstructorBaseInitializer ((ArrayList) $4);\r
-         }\r
-       | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS\r
-         {\r
-               $$ = new ConstructorThisInitializer ((ArrayList) $4);\r
-         }\r
-       ;\r
-\r
-destructor_declaration\r
-       : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block\r
-         {\r
-               Method d = new Method (type ("void"), 0, "Finalize", new Parameters (null, null));\r
-\r
-               d.Block = (Block) $6;\r
-               CheckDef (current_container.AddMethod (d), d.Name);\r
-         }\r
-       ;\r
-\r
-event_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         EVENT type variable_declarators SEMICOLON\r
-         { note ("validate that the flags only contain new public protected internal private static virtual sealed override abstract"); }\r
-       | opt_attributes\r
-         opt_modifiers\r
-         EVENT type member_name \r
-         OPEN_BRACE event_accesor_declarations CLOSE_BRACE SEMICOLON\r
-         { note ("validate that the flags only contain new public protected internal private static virtual sealed override abstract"); }\r
-       ;\r
-\r
-event_accesor_declarations\r
-       : add_accessor_declaration remove_accessor_declaration\r
-       | remove_accessor_declaration add_accessor_declaration\r
-       ;\r
-\r
-add_accessor_declaration\r
-       : opt_attributes ADD block\r
-       ;\r
-\r
-remove_accessor_declaration\r
-       : opt_attributes REMOVE block\r
-       ;\r
-\r
-indexer_declaration\r
-       : opt_attributes opt_modifiers indexer_declarator \r
-         OPEN_BRACE \r
-         { lexer.properties = true; }\r
-         accessor_declarations \r
-         { lexer.properties = false; }\r
-         CLOSE_BRACE\r
-         { \r
-               // The signature is computed from the signature of the indexer.  Look\r
-               // at section 3.6 on the spec\r
-               note ("verify modifiers are NEW PUBLIC PROTECTED INTERNAL PRIVATE VIRTUAL SEALED OVERRIDE ABSTRACT"); \r
-         }\r
-       ;\r
-\r
-indexer_declarator\r
-       : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
-       | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
-       ;\r
-\r
-enum_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         ENUM IDENTIFIER\r
-         opt_enum_base\r
-         enum_body\r
-         opt_semicolon\r
-         { \r
-               string name = (string) $4;\r
-               Enum e = new Enum ((TypeRef) $5, (int) $2, name);\r
-\r
-               foreach (VariableDeclaration ev in (ArrayList) $6){\r
-                       CheckDef (\r
-                               e.AddEnum (\r
-                                       ev.identifier, \r
-                                       (Expression) ev.expression_or_array_initializer),\r
-                               ev.identifier);\r
-               }\r
-\r
-               CheckDef (current_container.AddEnum (e), name);\r
-         }\r
-       ;\r
-\r
-opt_enum_base\r
-       : /* empty */                   { $$ = type ("System.Int32"); }\r
-       | COLON integral_type           { $$ = $2;   }\r
-       ;\r
-\r
-enum_body\r
-       : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE\r
-         {\r
-               $$ = $2;\r
-         }\r
-       ;\r
-\r
-opt_enum_member_declarations\r
-       : /* empty */                   { $$ = new ArrayList (); }\r
-       | enum_member_declarations opt_comma { $$ = $1; }\r
-       ;\r
-\r
-enum_member_declarations\r
-       : enum_member_declaration \r
-         {\r
-               ArrayList l = new ArrayList ();\r
-\r
-               l.Add ($1);\r
-               $$ = l;\r
-         }\r
-       | enum_member_declarations COMMA enum_member_declaration\r
-         {\r
-               ArrayList l = (ArrayList) $1;\r
-\r
-               l.Add ($3);\r
-\r
-               $$ = l;\r
-         }\r
-       ;\r
-\r
-enum_member_declaration\r
-       : opt_attributes IDENTIFIER \r
-         {\r
-               $$ = new VariableDeclaration ((string) $2, null);\r
-         }\r
-       | opt_attributes IDENTIFIER ASSIGN expression\r
-         { \r
-               $$ = new VariableDeclaration ((string) $2, $4);\r
-         }\r
-       ;\r
-\r
-delegate_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         DELEGATE type   \r
-         IDENTIFIER OPEN_PARENS \r
-         formal_parameter_list\r
-         CLOSE_PARENS \r
-         SEMICOLON\r
-         { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }\r
-\r
-       | opt_attributes\r
-         opt_modifiers\r
-         DELEGATE VOID   \r
-         IDENTIFIER OPEN_PARENS \r
-         formal_parameter_list\r
-         CLOSE_PARENS \r
-         SEMICOLON\r
-         { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }\r
-       ;\r
-\r
-type_name\r
-       : namespace_or_type_name\r
-       ;\r
-\r
-namespace_or_type_name\r
-       : qualified_identifier\r
-       ;\r
-\r
-/* \r
- * Before you think of adding a return_type, notice that we have been\r
- * using two rules in the places where it matters (one rule using type\r
- * and another identical one that uses VOID as the return type).  This\r
- * gets rid of a shift/reduce couple\r
- */\r
-type\r
-       : type_name {   /* class_type */\r
-               /* \r
-                  This does interfaces, delegates, struct_types, class_types, \r
-                  parent classes, and more! 4.2 \r
-                */\r
-               $$ = type ((string) $1); \r
-         }\r
-       | builtin_types\r
-       | array_type\r
-       ;\r
-\r
-type_list\r
-       : type\r
-         {\r
-               ArrayList types = new ArrayList ();\r
-\r
-               types.Add ($1);\r
-               $$ = types;\r
-         }\r
-       | type_list COMMA type\r
-         {\r
-               ArrayList types = new ArrayList ();\r
-               types.Add ($2);\r
-               $$ = types;\r
-         }\r
-       ;\r
-\r
-/*\r
- * replaces all the productions for isolating the various\r
- * simple types, but we need this to reuse it easily in local_variable_type\r
- */\r
-builtin_types\r
-       : OBJECT        { $$ = type ("System.Object"); }\r
-       | STRING        { $$ = type ("System.String"); }\r
-       | BOOL          { $$ = type ("System.Boolean"); }\r
-       | DECIMAL       { $$ = type ("System.Decimal"); }\r
-       | FLOAT         { $$ = type ("System.Single"); }\r
-       | DOUBLE        { $$ = type ("System.Double"); }\r
-       | integral_type\r
-       ;\r
-\r
-integral_type\r
-       : SBYTE         { $$ = type ("System.SByte"); }\r
-       | BYTE          { $$ = type ("System.Byte"); }\r
-       | SHORT         { $$ = type ("System.Int16"); }\r
-       | USHORT        { $$ = type ("System.UInt16"); }\r
-       | INT           { $$ = type ("System.Int32"); }\r
-       | UINT          { $$ = type ("System.UInt32"); }\r
-       | LONG          { $$ = type ("System.Int64"); }\r
-       | ULONG         { $$ = type ("System.UInt64"); }\r
-       | CHAR          { $$ = type ("System.Char"); }\r
-       ;\r
-\r
-interface_type\r
-       : type_name\r
-       ;\r
-\r
-array_type\r
-       : type rank_specifiers\r
-         {\r
-               $$ = $1;\r
-               // FIXME: We need to create a type for the nested thing.\r
-         }\r
-       ;\r
-\r
-//\r
-// Expressions, section 7.5\r
-//\r
-primary_expression\r
-       : literal\r
-         {\r
-               // 7.5.1: Literals\r
-               \r
-         }\r
\r
-       | qualified_identifier\r
-         {\r
-               string name = (string) $1;\r
-\r
-               $$ = null;\r
-               if (name.IndexOf ('.') == -1){\r
-                       //\r
-                       // we need to check against current_block not being null\r
-                       // as `expression' is allowed in argument_lists, which \r
-                       // do not exist inside a block.  \r
-                       //\r
-                       if (current_block != null){\r
-                               if (current_block.IsVariableDefined (name))\r
-                                       $$ = new LocalVariableReference (current_block, name);\r
-                       }\r
-                       if (($$ == null) && (current_local_parameters != null)){\r
-                               Parameter par = current_local_parameters.GetParameterByName (name);\r
-                               if (par != null)\r
-                                       $$ = new ParameterReference (current_local_parameters, name);\r
-                       }\r
-               }\r
-               if ($$ == null)\r
-                       $$ = new SimpleName (name);\r
-         }\r
-       | parenthesized_expression\r
-       | member_access\r
-       | invocation_expression\r
-       | element_access\r
-       | this_access\r
-       | base_access\r
-       | post_increment_expression\r
-       | post_decrement_expression\r
-       | new_expression\r
-       | typeof_expression\r
-       | sizeof_expression\r
-       | checked_expression\r
-       | unchecked_expression\r
-       ;\r
-\r
-literal\r
-       : boolean_literal\r
-       | integer_literal\r
-       | real_literal\r
-       | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }\r
-       | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }\r
-       | NULL                  { $$ = new NullLiteral (); }\r
-       ;\r
-\r
-real_literal\r
-       : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }\r
-       | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }\r
-       | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }\r
-       ;\r
-\r
-integer_literal\r
-       : LITERAL_INTEGER       { $$ = new IntLiteral ((Int32) lexer.Value); }\r
-       ;\r
-\r
-boolean_literal\r
-       : TRUE                  { $$ = new BoolLiteral (true); }\r
-       | FALSE                 { $$ = new BoolLiteral (false); }\r
-       ;\r
-\r
-parenthesized_expression\r
-       : OPEN_PARENS expression CLOSE_PARENS\r
-         { $$ = $2; }\r
-       ;\r
-\r
-member_access\r
-       : primary_expression DOT IDENTIFIER\r
-         {\r
-               $$ = new MemberAccess ((Expression) $1, (string) $3);\r
-         }\r
-       | predefined_type DOT IDENTIFIER\r
-         {\r
-               $$ = new BuiltinTypeAccess ((TypeRef) $1, (string) $3);\r
-         }\r
-       ;\r
-\r
-predefined_type\r
-       : builtin_types\r
-       ;\r
-\r
-invocation_expression\r
-       : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS\r
-         {\r
-               // FIXME:\r
-               // if $1 is MethodGroup\r
-               //      $$ = new Call ($1, $3);\r
-               // else \r
-               //      $$ = new DelegateCall ($1, $3);\r
-               if ($1 == null)\r
-                       error (1, "THIS IS CRAZY");\r
-\r
-               $$ = new Invocation ((Expression) $1, (ArrayList) $3);\r
-         }\r
-       ; \r
-\r
-opt_argument_list\r
-       : /* empty */           { $$ = new ArrayList (); }\r
-       | argument_list\r
-       ;\r
-\r
-argument_list\r
-       : argument              \r
-         { \r
-               ArrayList list = new ArrayList ();\r
-               list.Add ($1);\r
-               $$ = list;\r
-         }\r
-       | argument_list COMMA argument\r
-         {\r
-               ArrayList list = (ArrayList) $1;\r
-               list.Add ($3);\r
-               $$ = list;\r
-         }\r
-       ;\r
-\r
-argument\r
-       : expression\r
-         {\r
-               $$ = new Argument ((Expression) $1, Argument.AType.Expression);\r
-         }\r
-       | REF variable_reference \r
-         { \r
-               $$ = new Argument ((Expression) $2, Argument.AType.Ref);\r
-         }\r
-       | OUT variable_reference \r
-         { \r
-               $$ = new Argument ((Expression) $2, Argument.AType.Out);\r
-         }\r
-       ;\r
-\r
-variable_reference\r
-       : expression { note ("section 5.4"); $$ = $1; }\r
-       ;\r
-\r
-element_access\r
-       : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET \r
-       // finishme\r
-       ;\r
-\r
-expression_list\r
-       : expression\r
-       | expression_list COMMA expression\r
-       ;\r
-\r
-this_access\r
-       : THIS\r
-         {\r
-               $$ = new This ();\r
-         }\r
-       ;\r
-\r
-base_access\r
-       : BASE DOT IDENTIFIER\r
-       // finishme\r
-       | BASE OPEN_BRACKET expression_list CLOSE_BRACKET\r
-       // finishme\r
-       ;\r
-\r
-post_increment_expression\r
-       : primary_expression OP_INC\r
-         {\r
-               $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);\r
-         }\r
-       ;\r
-\r
-post_decrement_expression\r
-       : primary_expression OP_DEC\r
-         {\r
-               $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);\r
-         }\r
-       ;\r
-\r
-new_expression\r
-       : object_or_delegate_creation_expression\r
-       | array_creation_expression\r
-       ;\r
-\r
-object_or_delegate_creation_expression\r
-       : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS\r
-         {\r
-               $$ = new New ((TypeRef) $2, (ArrayList) $4);\r
-         }\r
-       ;\r
-\r
-array_creation_expression\r
-       : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET \r
-         opt_rank_specifier\r
-         opt_array_initializer\r
-       // finishme\r
-       ;\r
-\r
-opt_rank_specifier\r
-       : /* empty */\r
-       | rank_specifiers\r
-       ;\r
-\r
-rank_specifiers\r
-       : rank_specifier\r
-       | rank_specifier rank_specifiers\r
-       // finishme\r
-       ;\r
-\r
-rank_specifier\r
-       : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
-       // finishme\r
-       ;\r
-\r
-opt_dim_separators\r
-       : /* empty */\r
-       | dim_separators\r
-       // finishme\r
-       ;\r
-\r
-dim_separators\r
-       : COMMA\r
-       | dim_separators COMMA\r
-       // finishme\r
-       ;\r
-\r
-opt_array_initializer\r
-       : /* empty */\r
-       | array_initializer\r
-       ;\r
-\r
-array_initializer\r
-       : OPEN_BRACE CLOSE_BRACE\r
-       | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE\r
-       // finishme\r
-       ;\r
-\r
-variable_initializer_list\r
-       : variable_initializer\r
-       | variable_initializer_list COMMA variable_initializer\r
-       // finishme\r
-       ;\r
-\r
-typeof_expression\r
-       : TYPEOF OPEN_PARENS type CLOSE_PARENS\r
-         {\r
-               $$ = new TypeOf ((TypeRef) $3);\r
-         }\r
-       ;\r
-\r
-sizeof_expression\r
-       : SIZEOF OPEN_PARENS type CLOSE_PARENS { \r
-               $$ = new SizeOf ((TypeRef) $3);\r
-\r
-               note ("Verify type is unmanaged"); \r
-               note ("if (5.8) builtin, yield constant expression");\r
-         }\r
-       ;\r
-\r
-checked_expression\r
-       : CHECKED OPEN_PARENS expression CLOSE_PARENS\r
-       ;\r
-\r
-unchecked_expression\r
-       : UNCHECKED OPEN_PARENS expression CLOSE_PARENS\r
-       ;\r
-\r
-unary_expression\r
-       : primary_expression\r
-       | PLUS unary_expression         { \r
-               $$ = new Unary (Unary.Operator.Plus, (Expression) $2);\r
-         } \r
-       | MINUS unary_expression \r
-         { \r
-               $$ = new Unary (Unary.Operator.Minus, (Expression) $2);\r
-         }\r
-       | BANG unary_expression \r
-         {\r
-               $$ = new Unary (Unary.Operator.Negate, (Expression) $2);\r
-         }\r
-       | TILDE unary_expression\r
-         {\r
-               $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);\r
-         }\r
-       | STAR unary_expression\r
-         {\r
-               $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);\r
-         }\r
-       | BITWISE_AND unary_expression\r
-         {\r
-               $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);\r
-         }\r
-       | OP_INC unary_expression \r
-         {\r
-               $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);\r
-         }\r
-       | OP_DEC unary_expression \r
-         {\r
-               $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);\r
-         }\r
-        | cast_expression \r
-       /*\r
-        we can not do cast expressions at this level,\r
-        as there is an ambiguity.  Check "Cast Expressions" 7.6.8\r
-        for the recipe to handle this.\r
-        */\r
-       ;\r
-\r
-pre_increment_expression\r
-       : OP_INC unary_expression \r
-         {\r
-               $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);\r
-         }\r
-       ;\r
-\r
-pre_decrement_expression\r
-       : OP_DEC unary_expression \r
-         {\r
-               $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);\r
-         }\r
-       ;\r
-\r
-cast_expression\r
-       /* \r
-        * FIXME: This is actually wrong, it should be `type' but that\r
-        * introduces a lot of {shift,reduce}/reduces\r
-        *\r
-        * This is really really wrong.  We need to track down\r
-        * the source of problems with QIs because expressions like:\r
-        * foreach (string s in (string []) object) wont be parsed.\r
-        */\r
-       : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression\r
-         {\r
-               $$ = new Cast (type ((string) $2), (Expression) $4);\r
-         }\r
-       | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression\r
-         {\r
-               $$ = new Cast ((TypeRef) $2, (Expression) $4);\r
-         }\r
-       ;\r
-\r
-multiplicative_expression\r
-       : unary_expression\r
-       | multiplicative_expression STAR unary_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.Multiply, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | multiplicative_expression DIV unary_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.Divide, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | multiplicative_expression PERCENT unary_expression \r
-         {\r
-               $$ = new Binary (Binary.Operator.Modulo, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-additive_expression\r
-       : multiplicative_expression\r
-       | additive_expression PLUS multiplicative_expression \r
-         {\r
-               $$ = new Binary (Binary.Operator.Add, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | additive_expression MINUS multiplicative_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.Substract, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-shift_expression\r
-       : additive_expression\r
-       | shift_expression OP_SHIFT_LEFT additive_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.ShiftLeft, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | shift_expression OP_SHIFT_RIGHT additive_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.ShiftRight, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ; \r
-\r
-relational_expression\r
-       : shift_expression\r
-       | relational_expression OP_LT shift_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.LessThan, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | relational_expression OP_GT shift_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.GreatherThan, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | relational_expression OP_LE shift_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.LessOrEqual, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | relational_expression OP_GE shift_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.GreatherOrEqual, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | relational_expression IS type\r
-         {\r
-               $$ = new Probe (Probe.Operator.Is, \r
-                                (Expression) $1, (TypeRef) $3);\r
-         }\r
-       | relational_expression AS type\r
-         {\r
-               $$ = new Probe (Probe.Operator.As, \r
-                                (Expression) $1, (TypeRef) $3);\r
-         }\r
-       ;\r
-\r
-equality_expression\r
-       : relational_expression\r
-       | equality_expression OP_EQ relational_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.Equal, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       | equality_expression OP_NE relational_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.NotEqual, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ; \r
-\r
-and_expression\r
-       : equality_expression\r
-       | and_expression BITWISE_AND equality_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.BitwiseAnd, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-exclusive_or_expression\r
-       : and_expression\r
-       | exclusive_or_expression CARRET and_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.ExclusiveOr, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-inclusive_or_expression\r
-       : exclusive_or_expression\r
-       | inclusive_or_expression BITWISE_OR exclusive_or_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.BitwiseOr, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-conditional_and_expression\r
-       : inclusive_or_expression\r
-       | conditional_and_expression OP_AND inclusive_or_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.LogicalAnd, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-conditional_or_expression\r
-       : conditional_and_expression\r
-       | conditional_or_expression OP_OR conditional_and_expression\r
-         {\r
-               $$ = new Binary (Binary.Operator.LogicalOr, \r
-                                (Expression) $1, (Expression) $3);\r
-         }\r
-       ;\r
-\r
-conditional_expression\r
-       : conditional_or_expression\r
-       | conditional_or_expression INTERR expression COLON expression \r
-         {\r
-               $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);\r
-         }\r
-       ;\r
-\r
-assignment_expression\r
-       : unary_expression ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1, (Expression) $3);\r
-         }\r
-       | unary_expression OP_MULT_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.Multiply, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_DIV_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.Divide, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_MOD_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.Modulo, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_ADD_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.Add, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_SUB_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.Substract, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_SHIFT_LEFT_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.ShiftLeft, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_SHIFT_RIGHT_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.ShiftRight, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_AND_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.BitwiseAnd, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_OR_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.BitwiseOr, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       | unary_expression OP_XOR_ASSIGN expression\r
-         {\r
-               $$ = new Assign ((Expression) $1,\r
-                                new Binary (Binary.Operator.ExclusiveOr, \r
-                                            (Expression) $1,\r
-                                            (Expression) $3));\r
-         }\r
-       ;\r
-\r
-expression\r
-       : conditional_expression\r
-       | assignment_expression\r
-       ;\r
-\r
-constant_expression\r
-       : expression\r
-       ;\r
-\r
-boolean_expression\r
-       : expression    { CheckBoolean ((Expression) $1); $$ = $1; } \r
-       ;\r
-\r
-//\r
-// 10 classes\r
-//\r
-class_declaration\r
-       : opt_attributes\r
-         opt_modifiers\r
-         CLASS IDENTIFIER\r
-         {\r
-               Class new_class;\r
-               string full_class_name = MakeName ((string) $4);\r
-\r
-               new_class = new Class (current_container, full_class_name, (int) $2);\r
-               current_container = new_class;\r
-               current_container.Namespace = current_namespace;\r
-               tree.RecordType (full_class_name, new_class);\r
-         }\r
-         opt_class_base\r
-         class_body \r
-         opt_semicolon \r
-         {\r
-               Class new_class = (Class) current_container;\r
-\r
-               if ($6 != null)\r
-                       new_class.Bases = (ArrayList) $6;\r
-\r
-               current_container = current_container.Parent;\r
-               CheckDef (current_container.AddClass (new_class), new_class.Name);\r
-\r
-               $$ = new_class;\r
-         }\r
-       ;       \r
-\r
-opt_modifiers\r
-       : /* empty */           { $$ = (int) 0; }\r
-       | modifiers\r
-       ;\r
-\r
-modifiers\r
-       : modifier\r
-       | modifiers modifier    { \r
-               int m1 = (int) $1;\r
-               int m2 = (int) $2;\r
-\r
-               if ((m1 & m2) != 0)\r
-                       error (1002, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");\r
-\r
-               $$ = (int) (m1 | m2);\r
-         }\r
-       ;\r
-\r
-modifier\r
-       : NEW                   { $$ = Modifiers.NEW; }\r
-       | PUBLIC                { $$ = Modifiers.PUBLIC; }\r
-       | PROTECTED             { $$ = Modifiers.PROTECTED; }\r
-       | INTERNAL              { $$ = Modifiers.INTERNAL; }\r
-       | PRIVATE               { $$ = Modifiers.PRIVATE; }\r
-       | ABSTRACT              { $$ = Modifiers.ABSTRACT; }\r
-       | SEALED                { $$ = Modifiers.SEALED; }\r
-       | STATIC                { $$ = Modifiers.STATIC; }\r
-       | READONLY              { $$ = Modifiers.READONLY; }\r
-       | VIRTUAL               { $$ = Modifiers.VIRTUAL; }\r
-       | OVERRIDE              { $$ = Modifiers.OVERRIDE; }\r
-       | EXTERN                { $$ = Modifiers.EXTERN; }\r
-       ;\r
-\r
-opt_class_base\r
-       : /* empty */           { $$ = null; }\r
-       | class_base            { $$ = $1; }\r
-       ;\r
-\r
-class_base\r
-       : COLON type_list { $$ = $2; }\r
-       ;\r
-\r
-//\r
-// Statements (8.2)\r
-//\r
-\r
-//\r
-// A block is "contained" on the following places:\r
-//     method_body\r
-//     property_declaration as part of the accessor body (get/set)\r
-//      operator_declaration\r
-//     constructor_declaration\r
-//     destructor_declaration\r
-//     event_declaration as part of add_accessor_declaration or remove_accessor_declaration\r
-//      \r
-block\r
-       : OPEN_BRACE \r
-         {\r
-               current_block = new Block (current_block);\r
-         } \r
-         opt_statement_list CLOSE_BRACE \r
-         { \r
-               while (current_block.Implicit)\r
-                       current_block = current_block.Parent;\r
-               $$ = current_block;\r
-               current_block = current_block.Parent;\r
-         }\r
-       ;\r
-\r
-opt_statement_list\r
-       : /* empty */\r
-       | statement_list \r
-       ;\r
-\r
-statement_list\r
-       : statement\r
-       | statement_list statement\r
-       ;\r
-\r
-statement\r
-       : declaration_statement\r
-         {\r
-               if ((Block) $1 != current_block){\r
-                       current_block.AddStatement ((Statement) $1);\r
-                       current_block = (Block) $1;\r
-               }\r
-         }\r
-       | embedded_statement\r
-         {\r
-               current_block.AddStatement ((Statement) $1);\r
-         }\r
-       | labeled_statement \r
-         {\r
-               current_block.AddStatement ((Statement) $1);\r
-         }\r
-       ;\r
-\r
-embedded_statement\r
-       : block\r
-       | empty_statement\r
-        | expression_statement\r
-       | selection_statement\r
-       | iteration_statement\r
-       | jump_statement                  \r
-       | try_statement\r
-       | checked_statement\r
-       | unchecked_statement\r
-       | lock_statement\r
-       | using_statement\r
-       ;\r
-\r
-empty_statement\r
-       : SEMICOLON\r
-         {\r
-                 $$ = new EmptyStatement ();\r
-         }\r
-       ;\r
-\r
-labeled_statement\r
-       : IDENTIFIER COLON statement\r
-         {\r
-               string lab = (String) $1;\r
-               Block block;\r
-\r
-               block = new Block (current_block, lab);\r
-               block.AddStatement ((Statement) $3);\r
-               $$ = block;\r
-\r
-               if (!current_block.AddLabel (lab, block)){\r
-                       error (140, "The label '" + lab + "' is a duplicate");\r
-                       $$ = $3;\r
-               }       \r
-         }\r
-       ;\r
-\r
-declaration_statement\r
-       : local_variable_declaration SEMICOLON          // done\r
-       | local_constant_declaration SEMICOLON          // finishme\r
-       ;\r
-\r
-/* \r
- * The following is from Rhys' grammar:\r
- * > Types in local variable declarations must be recognized as \r
- * > expressions to prevent reduce/reduce errors in the grammar.\r
- * > The expressions are converted into types during semantic analysis.\r
- */\r
-local_variable_type\r
-       : primary_expression type_suffixes\r
-         { \r
-               // FIXME: Do something smart here regarding the composition of the type.\r
-               //\r
-\r
-               // Ok, the above "primary_expression" is there to get rid of\r
-               // both reduce/reduce and shift/reduces in the grammar, it should\r
-               // really just be "type_name".  If you use type_name, a reduce/reduce\r
-               // creeps up.  If you use qualified_identifier (which is all we need\r
-               // really) two shift/reduces appear.\r
-               // \r
-               // So, instead we do a super trick: we just allow ($1) to be a \r
-               // SimpleName Expression.\r
-               //\r
-               if (((Expression) $1) is SimpleName)\r
-                       $$ = type (((SimpleName) $1).Name);\r
-               else {\r
-                       error (-1, "Invalid Type definition");\r
-                       $$ = type ("object");\r
-               }\r
-         }\r
-       | builtin_types type_suffixes\r
-         {\r
-               // FIXME: Do something smart with the type here.\r
-               $$ = $1; \r
-         }\r
-       | VOID type_suffixes\r
-         {\r
-               $$ = type ("VOID SOMETHING TYPE");\r
-         }\r
-       ;\r
-\r
-type_suffixes\r
-       : /* empty */\r
-       | type_suffix_list\r
-       ;\r
-\r
-type_suffix_list \r
-       : type_suffix\r
-       | type_suffix_list type_suffix\r
-       ;\r
-\r
-type_suffix\r
-       : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
-       /* FIXME: | MULTIPLY */\r
-       ;\r
-\r
-local_variable_declaration\r
-       : local_variable_type variable_declarators\r
-         {\r
-               $$ = declare_local_variables ((TypeRef) $1, (ArrayList) $2);\r
-         }\r
-       ;\r
-\r
-local_constant_declaration\r
-       : CONST type constant_declarator\r
-               // finishme     \r
-       ;\r
-\r
-expression_statement\r
-       : statement_expression SEMICOLON\r
-         {\r
-               $$ = $1;\r
-         }\r
-       ;\r
-\r
-       //\r
-       // We have to do the wrapping here and not in the case above,\r
-       // because statement_expression is used for example in for_statement\r
-       //\r
-statement_expression\r
-       : invocation_expression         { $$ = new StatementExpression ((Expression) $1); }\r
-       | object_creation_expression    { $$ = new StatementExpression ((Expression) $1); }\r
-       | assignment_expression         { $$ = new StatementExpression ((Expression) $1); }\r
-       | post_increment_expression     { $$ = new StatementExpression ((Expression) $1); }\r
-       | post_decrement_expression     { $$ = new StatementExpression ((Expression) $1); }\r
-       | pre_increment_expression      { $$ = new StatementExpression ((Expression) $1); }\r
-       | pre_decrement_expression      { $$ = new StatementExpression ((Expression) $1); }\r
-       ;\r
-\r
-object_creation_expression\r
-       : object_or_delegate_creation_expression\r
-         { note ("complain if this is a delegate maybe?"); } \r
-       ;\r
-\r
-selection_statement\r
-       : if_statement\r
-       | switch_statement\r
-       ; \r
-\r
-if_statement\r
-       : IF OPEN_PARENS boolean_expression CLOSE_PARENS \r
-         embedded_statement\r
-         { \r
-               $$ = new If ((Expression) $3, (Statement) $5);\r
-         }\r
-       | IF OPEN_PARENS boolean_expression CLOSE_PARENS\r
-         embedded_statement ELSE embedded_statement\r
-         {\r
-               $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);\r
-         }\r
-       ;\r
-\r
-switch_statement\r
-       : SWITCH OPEN_PARENS expression CLOSE_PARENS \r
-         switch_block\r
-         {\r
-               $$ = new Switch ((Expression) $3, (ArrayList) $5);\r
-         }\r
-       ;\r
-\r
-switch_block\r
-       : OPEN_BRACE\r
-         opt_switch_sections\r
-         CLOSE_BRACE\r
-         {\r
-               $$ = $2;\r
-         }\r
-       ;\r
-\r
-opt_switch_sections\r
-       : /* empty */           { $$ = new ArrayList (); }\r
-       | switch_sections\r
-       ;\r
-\r
-switch_sections\r
-       : switch_section \r
-         {\r
-               ArrayList sections = new ArrayList ();\r
-\r
-               sections.Add ($1);\r
-               $$ = sections;\r
-         }\r
-       | switch_sections switch_section\r
-         {\r
-               ArrayList sections = (ArrayList) $1;\r
-\r
-               sections.Add ($2);\r
-               $$ = sections;\r
-         }\r
-       ;\r
-\r
-switch_section\r
-       : switch_labels\r
-         {\r
-               current_block = new Block (current_block);\r
-         }\r
-         statement_list \r
-         {\r
-               while (current_block.Implicit)\r
-                       current_block = current_block.Parent;\r
-               $$ = new SwitchSection ((ArrayList) $1, current_block);\r
-               current_block = current_block.Parent;\r
-         }\r
-       ;\r
-\r
-switch_labels\r
-       : switch_label \r
-         {\r
-               ArrayList labels = new ArrayList ();\r
-\r
-               labels.Add ($1);\r
-               $$ = labels;\r
-         }\r
-       | switch_labels switch_label \r
-         {\r
-               ArrayList labels = (ArrayList) ($1);\r
-               labels.Add ($2);\r
-\r
-               $$ = labels;\r
-         }\r
-       ;\r
-\r
-switch_label\r
-       : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2); }\r
-       | DEFAULT COLON                         { $$ = new SwitchLabel (null); }\r
-       ;\r
-\r
-iteration_statement\r
-       : while_statement\r
-       | do_statement\r
-       | for_statement\r
-       | foreach_statement\r
-       ;\r
-\r
-while_statement\r
-       : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement\r
-       {\r
-               $$ = new While ((Expression) $3, (Statement) $5);\r
-       }\r
-       ;\r
-\r
-do_statement\r
-       : DO embedded_statement \r
-         WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON\r
-         {\r
-               $$ = new Do ((Statement) $2, (Expression) $5);\r
-         }\r
-       ;\r
-\r
-for_statement\r
-       : FOR OPEN_PARENS \r
-         opt_for_initializer SEMICOLON\r
-         opt_for_condition SEMICOLON\r
-         opt_for_iterator CLOSE_PARENS \r
-         embedded_statement\r
-         {\r
-               $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);\r
-         }\r
-       ;\r
-\r
-opt_for_initializer\r
-       : /* empty */           { $$ = new EmptyStatement (); }\r
-       | for_initializer       \r
-       ;\r
-\r
-for_initializer\r
-       : local_variable_declaration\r
-       | statement_expression_list\r
-       ;\r
-\r
-opt_for_condition\r
-       : /* empty */           { $$ = new BoolLiteral (true); }\r
-       | boolean_expression\r
-       ;\r
-\r
-opt_for_iterator\r
-       : /* empty */           { $$ = new EmptyStatement (); }\r
-       | for_iterator\r
-       ;\r
-\r
-for_iterator\r
-       : statement_expression_list\r
-       ;\r
-\r
-statement_expression_list\r
-       : statement_expression  \r
-         {\r
-               Block b = new Block (null, true);\r
-\r
-               b.AddStatement ((Statement) $1);\r
-               $$ = b;\r
-         }\r
-       | statement_expression_list COMMA statement_expression\r
-         {\r
-               Block b = (Block) $1;\r
-\r
-               b.AddStatement ((Statement) $3);\r
-               $$ = $1;\r
-         }\r
-       ;\r
-\r
-foreach_statement\r
-       : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS \r
-         embedded_statement\r
-         {\r
-               string temp_id = current_block.MakeInternalID ();\r
-               Expression assign_e, ma;\r
-               Statement getcurrent;\r
-               Block foreach_block, child_block;\r
-\r
-               foreach_block = new Block (current_block, true);\r
-\r
-               foreach_block.AddVariable (type ("IEnumerator"), temp_id);\r
-               foreach_block.AddVariable ((TypeRef) $3, (string) $4);\r
-               assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id), \r
-                                      new Invocation (\r
-                                               new MemberAccess ((Expression) $6, "GetEnumerator"), null));\r
-               current_block.AddStatement (new StatementExpression (assign_e));\r
-               ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");\r
-               child_block = new Block (current_block);\r
-\r
-               getcurrent = new StatementExpression (\r
-                       new Assign (\r
-                               new LocalVariableReference (foreach_block, (string) $4),\r
-                               new Cast (\r
-                                       (TypeRef) $3, \r
-                                       new MemberAccess (\r
-                                               new LocalVariableReference (foreach_block, temp_id), "Current"))));\r
-\r
-               child_block.AddStatement (getcurrent);\r
-               child_block.AddStatement ((Statement) $8);\r
-               foreach_block.AddStatement (new While (ma, (Statement) child_block));\r
-\r
-               $$ = foreach_block;\r
-         }\r
-       ;\r
-\r
-jump_statement\r
-       : break_statement\r
-       | continue_statement\r
-       | goto_statement\r
-       | return_statement\r
-       | throw_statement\r
-       ;\r
-\r
-break_statement\r
-       : BREAK SEMICOLON\r
-         {\r
-               $$ = new Break ();\r
-         }\r
-       ;\r
-\r
-continue_statement\r
-       : CONTINUE SEMICOLON\r
-         {\r
-               $$ = new Continue ();\r
-         }\r
-       ;\r
-\r
-goto_statement\r
-       : GOTO IDENTIFIER SEMICOLON \r
-         {\r
-               $$ = new Goto ((string) $2);\r
-         }\r
-       | GOTO CASE constant_expression SEMICOLON\r
-       | GOTO DEFAULT SEMICOLON \r
-       ; \r
-\r
-return_statement\r
-       : RETURN opt_expression SEMICOLON\r
-         {\r
-               $$ = new Return ((Expression) $2);\r
-         }\r
-       ;\r
-\r
-throw_statement\r
-       : THROW opt_expression SEMICOLON\r
-         {\r
-               $$ = new Throw ((Expression) $2);\r
-         }\r
-       ;\r
-\r
-opt_expression\r
-       : /* empty */\r
-       | expression\r
-       ;\r
-\r
-try_statement\r
-       : TRY block catch_clauses \r
-         {\r
-               DictionaryEntry cc = (DictionaryEntry) $3;\r
-               ArrayList s = null;\r
-\r
-               if (cc.Key != null)\r
-                       s = (ArrayList) cc.Key;\r
-\r
-               $$ = new Try ((Block) $2, s, (Catch) cc.Value, null);\r
-         }\r
-       | TRY block FINALLY block\r
-         {\r
-               $$ = new Try ((Block) $2, null, null, (Block) $4);\r
-         }\r
-       | TRY block catch_clauses FINALLY block\r
-         {\r
-               DictionaryEntry cc = (DictionaryEntry) $3;\r
-               ArrayList s = null;\r
-\r
-               if (cc.Key != null)\r
-                       s = (ArrayList) cc.Key;\r
-\r
-               $$ = new Try ((Block) $2, s, (Catch) cc.Value, (Block) $5);\r
-         }\r
-       ;\r
-\r
-catch_clauses\r
-       : specific_catch_clauses opt_general_catch_clause\r
-         {\r
-               DictionaryEntry pair = new DictionaryEntry ();\r
-\r
-               pair.Key = $1; \r
-               pair.Value = $2;\r
-\r
-               $$ = pair;\r
-         }\r
-       | opt_specific_catch_clauses general_catch_clause\r
-         {\r
-               DictionaryEntry pair = new DictionaryEntry ();\r
-               pair.Key = $1;\r
-               pair.Value = $1;\r
-\r
-               $$ = pair;\r
-         }\r
-       ;\r
-\r
-opt_general_catch_clause\r
-       : /* empty */                   { $$ = null; }\r
-       | general_catch_clause \r
-       ;\r
-\r
-opt_specific_catch_clauses\r
-       : /* emtpy */                   { $$ = null; }\r
-       | specific_catch_clauses \r
-       ;\r
-\r
-specific_catch_clauses\r
-       : specific_catch_clause \r
-         {\r
-               ArrayList l = new ArrayList ();\r
-\r
-               l.Add ($1);\r
-               $$ = l;\r
-         }\r
-       | specific_catch_clauses specific_catch_clause\r
-         {\r
-               ArrayList l = (ArrayList) $1;\r
-\r
-               l.Add ($2);\r
-               $$ = l;\r
-         }\r
-       ;\r
-\r
-specific_catch_clause\r
-       : CATCH OPEN_PARENS type opt_identifier CLOSE_PARENS block\r
-         {\r
-               string id = null;\r
-\r
-               if ($4 != null)\r
-                       id = (string) $4;\r
-\r
-               $$ = new Catch ((TypeRef) $3, id, (Block) $6);\r
-         }\r
-       ;\r
-\r
-opt_identifier\r
-       : /* empty */   { $$ = null; }\r
-       | IDENTIFIER\r
-       ;\r
-\r
-general_catch_clause\r
-       : CATCH block\r
-         {\r
-               $$ = new Catch (null, null, (Block) $2);\r
-         }\r
-       ;\r
-\r
-checked_statement\r
-       : CHECKED block\r
-         {\r
-               $$ = new Checked ((Block) $2);\r
-         }\r
-       ;\r
-\r
-unchecked_statement\r
-       : UNCHECKED block\r
-         {\r
-               $$ = new Unchecked ((Block) $2);\r
-         }\r
-       ;\r
-\r
-lock_statement\r
-       : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement\r
-         {\r
-               $$ = new Lock ((Expression) $3, (Statement) $5);\r
-         }\r
-       ;\r
-\r
-using_statement\r
-       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement\r
-         // finishme\r
-       ; \r
-\r
-resource_acquisition\r
-       : local_variable_declaration\r
-         expression\r
-         // finishme\r
-       ;\r
-\r
-%%\r
-\r
-// <summary>\r
-//   A class used to pass around variable declarations and constants\r
-// </summary>\r
-public class VariableDeclaration {\r
-       public string identifier;\r
-       public object expression_or_array_initializer;\r
-\r
-       public VariableDeclaration (string id, object eoai){\r
-               this.identifier = id;\r
-               this.expression_or_array_initializer = eoai;\r
-       }\r
-}\r
-\r
-// <summary>\r
-//   Given the @class_name name, it creates a fully qualified name\r
-//   based on the containing declaration space\r
-// </summary>\r
-string \r
-MakeName (string class_name)\r
-{\r
-       string ns = current_namespace.Name;\r
-       string container_name = current_container.Name;\r
-\r
-       if (container_name == ""){\r
-               if (ns != "")\r
-                       return ns + "." + class_name;\r
-               else\r
-                       return class_name;\r
-       } else\r
-               return container_name + "." + class_name;\r
-}\r
-\r
-// <summary>\r
-//   Used to report back to the user the result of a declaration\r
-//   in the current declaration space\r
-// </summary>\r
-void \r
-CheckDef (DeclSpace.AdditionResult result, string name)\r
-{\r
-       if (result == DeclSpace.AdditionResult.Success)\r
-               return;\r
-\r
-       switch (result){\r
-       case DeclSpace.AdditionResult.NameExists:\r
-               error (102, "The namespace `" + current_container.Name + \r
-                           "' already contains a definition for `"+\r
-                           name + "'");\r
-               break;\r
-\r
-/*\r
-       NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:\r
-\r
-       case DeclSpace.AdditionResult.MethodDuplicated:\r
-               error (111, "Class `"+current_container.Name+\r
-                           "' already defines a member called '" + \r
-                           name + "' with the same parameter types");\r
-               break;\r
-*/\r
-       case DeclSpace.AdditionResult.EnclosingClash:\r
-               error (542, "Member names cannot be the same as their enclosing type");\r
-               break;\r
-\r
-       case DeclSpace.AdditionResult.NotAConstructor:\r
-               error (1520, "Class, struct, or interface method must have a return type");\r
-               break;\r
-       }\r
-}\r
-\r
-void \r
-CheckDef (bool result, string name)\r
-{\r
-       if (result)\r
-               return;\r
-       CheckDef (DeclSpace.AdditionResult.NameExists, name);\r
-}\r
-\r
-Block declare_local_variables (TypeRef typeref, ArrayList variable_declarators)\r
-{\r
-       Block implicit_block;\r
-       ArrayList inits = null;\r
-\r
-       //\r
-       // We use the `Used' property to check whether statements\r
-       // have been added to the current block.  If so, we need\r
-       // to create another block to contain the new declaration\r
-       // otherwise, as an optimization, we use the same block to\r
-       // add the declaration.\r
-       //\r
-       // FIXME: A further optimization is to check if the statements\r
-       // that were added were added as part of the initialization\r
-       // below.  In which case, no other statements have been executed\r
-       // and we might be able to reduce the number of blocks for\r
-       // situations like this:\r
-       //\r
-       // int j = 1;  int k = j + 1;\r
-       //\r
-       if (current_block.Used)\r
-               implicit_block = new Block (current_block, true);\r
-       else\r
-               implicit_block = new Block (current_block, true);\r
-\r
-       foreach (VariableDeclaration decl in variable_declarators){\r
-               if (implicit_block.AddVariable (typeref, decl.identifier)){\r
-                       if (decl.expression_or_array_initializer != null){\r
-                               if (inits == null)\r
-                                       inits = new ArrayList ();\r
-                               inits.Add (decl);\r
-                       }\r
-               } else {\r
-                       error (128, "A local variable `" + decl.identifier +\r
-                                   "' is already defined in this scope");\r
-               }\r
-       }\r
-\r
-       if (inits == null)\r
-               return implicit_block;\r
-\r
-       foreach (VariableDeclaration decl in inits){\r
-               if (decl.expression_or_array_initializer is Expression){\r
-                       Expression expr = (Expression) decl.expression_or_array_initializer;\r
-                       Assign assign;\r
-                       \r
-                       assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);\r
-                       implicit_block.AddStatement (new StatementExpression (assign));\r
-               } else {\r
-               }\r
-       }\r
-                       \r
-       return implicit_block;\r
-}\r
-\r
-void CheckConstant (Expression expr)\r
-{\r
-       // finishme\r
-}\r
-\r
-void CheckBoolean (Expression expr)\r
-{\r
-       // finishme\r
-}\r
-\r
-static public void error (int code, string desc)\r
-{\r
-       Console.WriteLine ("Error CS"+code+": "+desc);\r
-       global_errors++;\r
-}\r
-\r
-void output (string s)\r
-{\r
-       Console.WriteLine (s);\r
-}\r
-\r
-void note (string s)\r
-{\r
-       // Used to put annotations\r
-}\r
-\r
-TypeRef type (string type_name)\r
-{\r
-       return type_references.GetTypeRef (current_container, type_name);\r
-}\r
-\r
-Tokenizer lexer;\r
-\r
-public CSharpParser(CIR.Tree tree, string name, System.IO.Stream input) \r
-{\r
-       current_namespace = new Namespace (null, "");\r
-       this.tree = tree;\r
-       this.name = name;\r
-       this.input = input;\r
-       current_container = tree.Types;\r
-       current_container.Namespace = current_namespace;\r
-\r
-       lexer = new Tokenizer (input, name);\r
-       type_references = new TypeRefManager (); \r
-}\r
-\r
-public int parse ()\r
-{\r
-       StringBuilder value = new StringBuilder ();\r
-\r
-       global_errors = 0;\r
-       try {\r
-               if (yacc_verbose_flag)\r
-                       yyparse (lexer, new yydebug.yyDebugSimple ());\r
-               else\r
-                       yyparse (lexer);\r
-       } catch (Exception e){\r
-               Console.WriteLine ("Fatal error: "+name);\r
-               Console.WriteLine (e);\r
-               Console.WriteLine (lexer.location);\r
-               global_errors++;\r
-       }\r
-       \r
-       return global_errors;\r
-}\r
-\r
-bool yacc_verbose_flag = false;\r
-\r
-public bool yacc_verbose {\r
-       set {\r
-               yacc_verbose_flag = value;\r
-       }\r
-\r
-       get {\r
-               return yacc_verbose_flag;\r
-       }\r
-}\r
-\r
-/* end end end */\r
-}\r
-}\r
-\r
+%{
+//
+// cs-parser.jay: The Parser for the C# compiler
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+// TODO:
+//   (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM
+//       And come to think of it, it is not that great, it duplicates a lot of code
+//       for something which is not really needed.  We still have piles of typecasts
+//       anwyays (due to the nature of the stack being a collection of Objects).
+//
+//   (2) Figure out why error productions dont work.  `type-declaration' is a
+//       great spot to put an `error' because you can reproduce it with this input:
+//      "public X { }"
+//
+//   (3) Move Modifier checking from each object into the parser itself, that will
+//       get rid of the global "error" symbol that we use now to report errors. 
+//       We still need to pass a pointer to the tree.ErrorHandler, but that is a 
+//      separate problem
+//
+using System.Text;
+using CIR;
+using System;
+
+namespace CIR
+{
+       using System.Collections;
+       using Mono.Languages;
+
+       /// <summary>
+       ///    The C# Parser
+       /// </summary>
+       public class CSharpParser : GenericParser {
+               Namespace     current_namespace;
+               TypeContainer current_container;
+       
+               // <summary>
+               //   Current block is used to add statements as we find
+               //   them.  
+               // </summary>
+
+               Block      current_block;
+
+               // <summary>
+               //   Current interface is used by the various declaration
+               //   productions in the interface declaration to "add"
+               //   the interfaces as we find them.
+               // </summary>
+               Interface  current_interface;
+
+               // <summary>
+               //   This is used by the unary_expression code to resolve
+               //   a name against a parameter.  
+               // </summary>
+               Parameters current_local_parameters;
+
+               // <summary>
+               //   Using during property parsing to describe the implicit
+               //   value parameter that is passed to the "set" accesor
+               //   method
+               // </summary>
+               Parameter [] implicit_value_parameters;
+
+               // <summary>
+               //   Used to determine if we are parsing the get/set pair
+               //   of an indexer or a property
+               // </summmary>
+               bool  parsing_indexer;
+
+               // <summary>
+               //   Used to record all types defined
+               // </summary>
+               Tree tree;
+               RootContext rc;
+
+%}
+
+%token EOF
+%token NONE   /* This token is never returned by our lexer */
+%token ERROR           // This is used not by the parser, but by the tokenizer.
+                       // do not remove.
+
+/*
+ *These are the C# keywords
+ */
+%token ABSTRACT        
+%token AS
+%token ADD
+%token BASE    
+%token BOOL    
+%token BREAK   
+%token BYTE    
+%token CASE    
+%token CATCH   
+%token CHAR    
+%token CHECKED 
+%token CLASS   
+%token CONST   
+%token CONTINUE        
+%token DECIMAL 
+%token DEFAULT 
+%token DELEGATE        
+%token DO      
+%token DOUBLE  
+%token ELSE    
+%token ENUM    
+%token EVENT   
+%token EXPLICIT        
+%token EXTERN  
+%token FALSE   
+%token FINALLY 
+%token FIXED   
+%token FLOAT   
+%token FOR     
+%token FOREACH 
+%token GOTO    
+%token IF      
+%token IMPLICIT        
+%token IN      
+%token INT     
+%token INTERFACE
+%token INTERNAL        
+%token IS      
+%token LOCK    
+%token LONG    
+%token NAMESPACE
+%token NEW     
+%token NULL    
+%token OBJECT  
+%token OPERATOR        
+%token OUT     
+%token OVERRIDE        
+%token PARAMS  
+%token PRIVATE 
+%token PROTECTED
+%token PUBLIC  
+%token READONLY        
+%token REF     
+%token RETURN  
+%token REMOVE
+%token SBYTE   
+%token SEALED  
+%token SHORT   
+%token SIZEOF  
+%token STATIC  
+%token STRING  
+%token STRUCT  
+%token SWITCH  
+%token THIS    
+%token THROW   
+%token TRUE    
+%token TRY     
+%token TYPEOF  
+%token UINT    
+%token ULONG   
+%token UNCHECKED
+%token UNSAFE  
+%token USHORT  
+%token USING   
+%token VIRTUAL 
+%token VOID    
+%token WHILE   
+
+/* C# keywords which are not really keywords */
+%token GET           "get"
+%token SET           "set"
+
+/* C# single character operators/punctuation. */
+%token OPEN_BRACE    "{"
+%token CLOSE_BRACE   "}"
+%token OPEN_BRACKET  "["
+%token CLOSE_BRACKET "]"
+%token OPEN_PARENS   "("
+%token CLOSE_PARENS  ")"
+%token DOT           "."
+%token COMMA         ","
+%token COLON         ":"
+%token SEMICOLON     ";"
+%token TILDE         "~"
+
+%token PLUS           "+"
+%token MINUS          "-"
+%token BANG           "!"
+%token ASSIGN         "="
+%token OP_LT          "<"
+%token OP_GT          ">"
+%token BITWISE_AND    "&"
+%token BITWISE_OR     "|"
+%token STAR           "*"
+%token PERCENT        "%"
+%token DIV            "/"
+%token CARRET         "^"
+%token INTERR         "?"
+
+/* C# multi-character operators. */
+%token OP_INC                 "++"
+%token OP_DEC                 "--"
+%token OP_SHIFT_LEFT          "<<"
+%token OP_SHIFT_RIGHT         ">>"
+%token OP_LE                  "<="
+%token OP_GE                  ">="
+%token OP_EQ                  "=="
+%token OP_NE                  "!="
+%token OP_AND                 "&&"
+%token OP_OR                  "||"
+%token OP_MULT_ASSIGN         "*="
+%token OP_DIV_ASSIGN          "/="
+%token OP_MOD_ASSIGN          "%="
+%token OP_ADD_ASSIGN          "+="
+%token OP_SUB_ASSIGN          "-="
+%token OP_SHIFT_LEFT_ASSIGN   "<<="
+%token OP_SHIFT_RIGHT_ASSIGN  ">>="
+%token OP_AND_ASSIGN          "&="
+%token OP_XOR_ASSIGN          "^="
+%token OP_OR_ASSIGN           "|="
+%token OP_PTR                 "->"
+
+/* Numbers */
+%token LITERAL_INTEGER           "int literal"
+%token LITERAL_FLOAT             "float literal"
+%token LITERAL_DOUBLE            "double literal"
+%token LITERAL_DECIMAL           "decimal literal"
+%token LITERAL_CHARACTER         "character literal"
+%token LITERAL_STRING            "string literal"
+
+%token IDENTIFIER
+
+/* Add precedence rules to solve dangling else s/r conflict */
+%nonassoc LOWPREC
+%nonassoc IF
+%nonassoc ELSE
+%right ASSIGN
+%left OP_OR
+%left OP_AND
+%left BITWISE_OR
+%left BITWISE_AND
+%left OP_SHIFT_LEFT OP_SHIFT_RIGHT
+%left PLUS MINUS
+%left STAR DIV PERCENT
+%right BANG CARRET UMINUS
+%nonassoc OP_INC OP_DEC
+%left OPEN_PARENS
+%left OPEN_BRACKET OPEN_BRACE
+%left DOT
+%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
+         }
+       ;
+
+using_directives
+       : using_directive 
+       | using_directives using_directive
+       ;
+
+using_directive
+       : using_alias_directive
+       | using_namespace_directive
+       ;
+
+using_alias_directive
+       : USING IDENTIFIER ASSIGN 
+         namespace_or_type_name SEMICOLON
+         {
+                 // FIXME : Need to implement actual action.
+         }
+       ;
+
+using_namespace_directive
+       : USING namespace_name SEMICOLON 
+         {
+               current_namespace.Using ((string) $2);
+          }
+       ;
+
+//  namespace_declarations
+//     : namespace_declaration
+//     | namespace_declarations namespace_declaration
+
+namespace_declaration
+       : NAMESPACE qualified_identifier 
+         {
+               current_namespace = new Namespace (current_namespace, (string) $2);
+               tree.RecordNamespace ((string) $2, current_namespace);
+         } 
+         namespace_body opt_semicolon
+         { 
+               current_namespace = current_namespace.Parent;
+         }
+       ;
+
+opt_semicolon
+       : /* empty */
+       | SEMICOLON
+       ;
+
+opt_comma
+       : /* empty */
+       | COMMA
+       ;
+
+qualified_identifier
+       : IDENTIFIER
+       | qualified_identifier DOT IDENTIFIER { 
+           $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
+       ;
+
+
+namespace_name
+       : namespace_or_type_name
+       ;
+
+namespace_body
+       : OPEN_BRACE
+         opt_using_directives
+         opt_namespace_member_declarations
+         CLOSE_BRACE
+         {
+         }
+       ;
+
+opt_using_directives
+       : /* empty */
+       | using_directives
+       ;
+
+opt_namespace_member_declarations
+       : /* empty */
+       | namespace_member_declarations
+       ;
+
+namespace_member_declarations
+       : namespace_member_declaration
+       | namespace_member_declarations namespace_member_declaration
+       ;
+
+namespace_member_declaration
+       : type_declaration
+         {
+               int mod_flags = 0;
+               string name = "";
+
+               if ($1 is Class){
+                       Class c = (Class) $1;
+                       mod_flags = c.ModFlags;
+                       name = c.Name;
+               } else if ($1 is Struct){
+                       Struct s = (Struct) $1;
+                       mod_flags = s.ModFlags;
+                       name = s.Name;
+               } 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 + "'");
+               //}
+         }
+       | namespace_declaration
+       ;
+
+type_declaration
+       : class_declaration             
+       | struct_declaration            
+       | interface_declaration         
+       | enum_declaration              
+       | delegate_declaration         
+       ;
+
+//
+// Attributes 17.2
+//
+opt_attributes
+       : /* empty */ { $$ = null; }
+       | attribute_section opt_attributes
+         {
+               Attributes attrs;
+               
+               if ($2 != null) {
+                       attrs = (Attributes) $2;
+                       attrs.AddAttribute ((Attribute) $1);
+               } else
+                       attrs = new Attributes ((Attribute) $1);
+               
+               $$ = attrs;
+         }
+       ;
+
+attribute_section
+       : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
+         {
+               string target = null;
+               
+               if ($2 != null)
+                       target = (string) $2;
+               
+               $$ = new Attribute (target, (ArrayList) $3);
+         }
+        | OPEN_BRACKET attribute_list CLOSE_BRACKET
+         {
+               $$ = new Attribute (null, (ArrayList) $2);
+         }
+       ;
+attribute_target_specifier
+       : attribute_target COLON
+         {
+               $$ = $1;
+         }
+       ;
+
+attribute_target
+       : IDENTIFIER
+         {
+               CheckAttributeTarget ((string) $1);
+               $$ = $1;
+         }
+        | EVENT  { $$ = "event"; }       
+        | RETURN { $$ = "return"; }
+       ;
+
+attribute_list
+       : attribute
+         {
+               ArrayList attrs = new ArrayList ();
+               attrs.Add ($1);
+
+               $$ = attrs;
+              
+         }
+       | attribute_list COMMA attribute
+         {
+               ArrayList attrs = (ArrayList) $1;
+               attrs.Add ($3);
+
+               $$ = attrs;
+         }
+       ;
+
+attribute
+       : attribute_name opt_attribute_arguments
+         {
+               $$ = new DictionaryEntry ($1, $2);
+         }
+       ;
+
+attribute_name
+       : type_name  { /* reserved attribute name or identifier: 17.4 */ }
+       ;
+
+opt_attribute_arguments
+       : /* empty */   { $$ = null; }
+       | OPEN_PARENS attribute_arguments CLOSE_PARENS
+         {
+               $$ = $2;
+         }
+       ;
+
+attribute_arguments
+       : expression
+         {
+               ArrayList args = new ArrayList ();
+               args.Add ($1);
+               
+               $$ = args;
+         }
+       | attribute_arguments COMMA expression
+         {
+               ArrayList args = (ArrayList) $1;
+               args.Add ($3);
+
+               $$ = args;
+         }
+       ;
+
+
+class_body
+       :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
+       ;
+
+opt_class_member_declarations
+       : /* empty */
+       | class_member_declarations
+       ;
+
+class_member_declarations
+       : class_member_declaration
+       | class_member_declarations 
+         class_member_declaration
+       ;
+
+class_member_declaration
+       : constant_declaration                  // done
+       | field_declaration                     // done
+       | method_declaration                    // done
+       | property_declaration                  // done
+       | event_declaration                     // done
+       | indexer_declaration                   // done
+       | operator_declaration                  // done
+       | constructor_declaration               // done
+       | destructor_declaration                // done
+       | type_declaration
+       ;
+
+struct_declaration
+       : opt_attributes
+         opt_modifiers
+         STRUCT IDENTIFIER
+         { 
+               Struct new_struct;
+               string full_struct_name = MakeName ((string) $4);
+
+               new_struct = new Struct (rc, 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);
+         }
+         opt_struct_interfaces
+         struct_body
+         opt_semicolon
+         {
+               Struct new_struct = (Struct) current_container;
+
+               current_container = current_container.Parent;
+               CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
+               $$ = new_struct;
+         }
+       ;
+
+opt_struct_interfaces
+       : /* empty */
+       | struct_interfaces
+       ;
+
+struct_interfaces
+       : struct_interface
+       | struct_interfaces struct_interface
+       ; 
+
+struct_interface
+       : COLON type_list
+       ;
+
+struct_body
+       : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
+       ;
+
+opt_struct_member_declarations
+       : /* empty */
+       | struct_member_declarations
+       ;
+
+struct_member_declarations
+       : struct_member_declaration
+       | struct_member_declarations struct_member_declaration
+       ;
+
+struct_member_declaration
+       : constant_declaration
+       | field_declaration
+       | method_declaration
+       | property_declaration
+       | event_declaration
+       | indexer_declaration
+       | operator_declaration
+       | constructor_declaration
+       | type_declaration
+       ;
+
+constant_declaration
+       : opt_attributes 
+         opt_modifiers
+         CONST
+         type
+         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);
+
+                       CheckDef (current_container.AddConstant (c), c.Name);
+               }
+         }
+       ;
+
+constant_declarators
+       : constant_declarator 
+         {
+               ArrayList constants = new ArrayList ();
+               constants.Add ($1);
+               $$ = constants;
+         }
+       | constant_declarators COMMA constant_declarator
+         {
+               ArrayList constants = (ArrayList) $1;
+
+               constants.Add ($3);
+         }
+       ;
+
+constant_declarator
+       : IDENTIFIER ASSIGN constant_expression
+         {
+               $$ = new DictionaryEntry ($1, $3);
+         }
+       ;
+
+field_declaration
+       : opt_attributes
+         opt_modifiers
+         type 
+         variable_declarators
+         SEMICOLON
+       { 
+               string type = (string) $3;
+               int mod = (int) $2;
+
+               foreach (VariableDeclaration var in (ArrayList) $4){
+                       Field field = new Field (type, mod, var.identifier, 
+                                                var.expression_or_array_initializer, (Attributes) $1);
+
+                       CheckDef (current_container.AddField (field), field.Name);
+               }
+       }
+
+       ;
+
+variable_declarators
+       : variable_declarator 
+         {
+               ArrayList decl = new ArrayList ();
+               decl.Add ($1);
+               $$ = decl;
+         }
+       | variable_declarators COMMA variable_declarator
+         {
+               ArrayList decls = (ArrayList) $1;
+               decls.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+variable_declarator
+       : IDENTIFIER ASSIGN variable_initializer
+         {
+               $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
+         }
+       | IDENTIFIER
+         {
+               $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
+         }
+       ;
+
+variable_initializer
+       : expression
+         {
+               $$ = $1;
+         }
+       | array_initializer
+       {
+               $$ = $1;
+       }
+       ;
+
+method_declaration
+       : method_header
+         method_body
+         {
+               Method method = (Method) $1;
+               Block b = (Block) $2;
+               
+               if (b == null){
+                       if ((method.ModFlags & (Modifiers.EXTERN | Modifiers.ABSTRACT)) == 0){
+                               Report.Error (
+                                       501, lexer.Location, "`" + 
+                                       current_container.Name + "." + method.Name + "'" +
+                                       "must declare a body because it is not marked abstract or extern");
+                       }
+               }
+
+               method.Block = (Block) $2;
+               CheckDef (current_container.AddMethod (method), method.Name);
+
+               current_local_parameters = null;
+         }
+       ;
+
+method_header
+       : opt_attributes
+         opt_modifiers
+         type
+         member_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               Method method = new Method ((string) $3, (int) $2, (string) $4, 
+                                           (Parameters) $6, (Attributes) $1, lexer.Location);
+
+               current_local_parameters = (Parameters) $6;
+
+               $$ = method;
+         }
+       | opt_attributes
+         opt_modifiers
+         VOID
+         member_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               Method method = new Method ("System.Void", (int) $2, (string) $4, 
+                                           (Parameters) $6, (Attributes) $1, lexer.Location);
+
+               current_local_parameters = (Parameters) $6;
+               $$ = method;
+         }
+       ;
+
+method_body
+       : block
+       | SEMICOLON             { $$ = null; }
+       ;
+
+opt_formal_parameter_list
+       : /* empty */                   { $$ = new Parameters (null, null); }
+       | formal_parameter_list
+       ;
+
+formal_parameter_list
+       : fixed_parameters              
+         { 
+               ArrayList pars_list = (ArrayList) $1;
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars, null); 
+         } 
+       | fixed_parameters COMMA parameter_array
+         {
+               ArrayList pars_list = (ArrayList) $1;
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars, (Parameter) $3); 
+         }
+       | parameter_array 
+         {
+               $$ = new Parameters (null, (Parameter) $1);
+         }
+       ;
+
+fixed_parameters
+       : fixed_parameter       
+         {
+               ArrayList pars = new ArrayList ();
+
+               pars.Add ($1);
+               $$ = pars;
+         }
+       | fixed_parameters COMMA fixed_parameter
+         {
+               ArrayList pars = (ArrayList) $1;
+
+               pars.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+fixed_parameter
+       : opt_attributes
+         opt_parameter_modifier
+         type
+         IDENTIFIER
+         {
+               $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
+         }
+       ;
+
+opt_parameter_modifier
+       : /* empty */           { $$ = Parameter.Modifier.NONE; }
+       | parameter_modifier
+       ;
+
+parameter_modifier
+       : REF                   { $$ = Parameter.Modifier.REF; }
+       | OUT                   { $$ = Parameter.Modifier.OUT; }
+       ;
+
+parameter_array
+       : opt_attributes PARAMS type IDENTIFIER
+         { 
+               $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
+               note ("type must be a single-dimension array type"); 
+         }
+       ;
+
+member_name 
+       : IDENTIFIER { $$ = $1.ToString (); }
+       | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
+       ;
+
+property_declaration
+       : opt_attributes
+         opt_modifiers
+         type member_name
+         OPEN_BRACE 
+         {
+               Parameter implicit_value_parameter;
+               implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE, null);
+
+               lexer.properties = true;
+               
+               implicit_value_parameters = new Parameter [1];
+               implicit_value_parameters [0] = implicit_value_parameter;
+         }
+         accessor_declarations 
+         {
+               lexer.properties = false;
+         }
+         CLOSE_BRACE
+         { 
+               Property prop;
+               DictionaryEntry pair = (DictionaryEntry) $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;
+
+               prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block, (Attributes) $1);
+               
+               CheckDef (current_container.AddProperty (prop), prop.Name);
+               implicit_value_parameters = null;
+         }
+       ;
+
+accessor_declarations
+       : get_accessor_declaration opt_set_accessor_declaration
+         { 
+               $$ = new DictionaryEntry ($1, $2);
+         }
+       | set_accessor_declaration opt_get_accessor_declaration
+         {
+               $$ = new DictionaryEntry ($2, $1);
+         }
+       ;
+
+opt_get_accessor_declaration
+       : /* empty */                   { $$ = null; }
+       | get_accessor_declaration
+       ;
+
+opt_set_accessor_declaration
+       : /* empty */                   { $$ = null; }
+       | set_accessor_declaration
+       ;
+
+get_accessor_declaration
+       : opt_attributes GET
+         {
+               // 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);
+
+               
+         }
+          accessor_body
+         {
+               $$ = $4;
+               current_local_parameters = null;
+         }
+       ;
+
+set_accessor_declaration
+       : opt_attributes SET 
+         {
+                 if (parsing_indexer == false)  
+                         current_local_parameters = new Parameters (implicit_value_parameters, null);
+         }
+         accessor_body
+         {
+               $$ = $4;
+               current_local_parameters = null;
+         }
+       ;
+
+accessor_body
+       : block 
+       | SEMICOLON             { $$ = new Block (null); }
+       ;
+
+interface_declaration
+       : opt_attributes
+         opt_modifiers
+         INTERFACE IDENTIFIER
+         {
+               Interface new_interface;
+               string full_interface_name = MakeName ((string) $4);
+
+               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);
+         }
+         opt_interface_base
+         interface_body
+         { 
+               Interface new_interface = (Interface) current_interface;
+
+               if ($6 != null)
+                       new_interface.Bases = (ArrayList) $6;
+
+               current_interface = null;
+               CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
+         }
+       ;
+
+opt_interface_base
+       : /* empty */                     { $$ = null; }
+       | interface_base
+       ;
+
+interface_base
+       : COLON interface_type_list       { $$ = $2; }
+       ;
+
+interface_type_list
+       : interface_type
+         {
+               ArrayList interfaces = new ArrayList ();
+
+               interfaces.Add ($1);
+               $$ = interfaces;
+         }
+       | interface_type_list COMMA interface_type
+         {
+               ArrayList interfaces = (ArrayList) $1;
+               interfaces.Add ($3);
+               $$ = interfaces;
+         }
+       ;
+
+interface_body
+       : OPEN_BRACE
+         opt_interface_member_declarations
+         CLOSE_BRACE
+       ;
+
+opt_interface_member_declarations
+       : /* empty */
+       | interface_member_declarations
+       ;
+
+interface_member_declarations
+       : interface_member_declaration
+       | interface_member_declarations interface_member_declaration
+       ;
+
+interface_member_declaration
+       : interface_method_declaration          
+         { 
+               InterfaceMethod m = (InterfaceMethod) $1;
+
+               CheckDef (current_interface.AddMethod (m), m.Name);
+         }
+       | interface_property_declaration        
+         { 
+               InterfaceProperty p = (InterfaceProperty) $1;
+
+               CheckDef (current_interface.AddProperty (p), p.Name);
+          }
+       | interface_event_declaration 
+          { 
+               InterfaceEvent e = (InterfaceEvent) $1;
+
+               CheckDef (current_interface.AddEvent (e), e.Name);
+         }
+       | interface_indexer_declaration
+         { 
+               InterfaceIndexer i = (InterfaceIndexer) $1;
+
+               CheckDef (current_interface.AddIndexer (i), "indexer");
+         }
+       ;
+
+opt_new
+       : /* empty */   { $$ = false; }
+       | NEW           { $$ = true; }
+       ;
+
+interface_method_declaration
+       : opt_attributes opt_new type IDENTIFIER 
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         SEMICOLON
+         {
+               $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
+         }
+       | 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);
+         }
+       ;
+
+interface_property_declaration
+       : opt_attributes
+         opt_new
+         type IDENTIFIER 
+         OPEN_BRACE 
+         { lexer.properties = true; }
+         interface_accesors 
+         { lexer.properties = false; }
+         CLOSE_BRACE
+         {
+               int gs = (int) $7;
+
+               $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2, 
+                                           (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1);
+         }
+       ;
+
+interface_accesors
+       : opt_attributes GET SEMICOLON          { $$ = 1; }
+       | opt_attributes SET SEMICOLON          { $$ = 2; }
+       | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON 
+         { $$ = 3; }
+       | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
+         { $$ = 3; }
+       ;
+
+interface_event_declaration
+       : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
+         {
+               $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
+         }
+       ;
+
+interface_indexer_declaration 
+       : opt_attributes opt_new type THIS 
+         OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+         OPEN_BRACE 
+         { lexer.properties = true; }
+         interface_accesors 
+         { lexer.properties = false; }
+         CLOSE_BRACE
+         {
+               int a_flags = (int) $10;
+
+               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);
+         }
+       ;
+
+operator_declaration
+       : opt_attributes opt_modifiers operator_declarator block
+         {
+               OperatorDeclaration decl = (OperatorDeclaration) $3;
+               
+               Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
+                                           decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
+
+               // Note again, checking is done in semantic analysis
+               current_container.AddOperator (op);
+         }
+       ;
+
+operator_declarator
+       : type OPERATOR overloadable_operator 
+         OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+       {
+               CheckUnaryOperator ((Operator.OpType) $3);
+
+               $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
+                                             null, null, lexer.Location);
+       }
+       | type OPERATOR overloadable_operator
+         OPEN_PARENS 
+               type IDENTIFIER COMMA
+               type IDENTIFIER 
+         CLOSE_PARENS
+        {
+              CheckBinaryOperator ((Operator.OpType) $3);
+              
+              $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
+                                            (string) $8, (string) $9, lexer.Location);
+        }
+       | conversion_operator_declarator
+       ;
+
+overloadable_operator
+// Unary operators:
+       : BANG   { $$ = Operator.OpType.Negate; }
+        | TILDE  { $$ = Operator.OpType.BitComplement; }  
+        | OP_INC { $$ = Operator.OpType.Increment; }
+        | OP_DEC { $$ = Operator.OpType.Decrement; }
+        | TRUE   { $$ = Operator.OpType.True; }
+        | FALSE  { $$ = Operator.OpType.False; }
+// Unary and binary:
+        | PLUS { $$ = Operator.OpType.Addition; }
+        | MINUS { $$ = Operator.OpType.Subtraction; }
+// Binary:
+        | STAR { $$ = Operator.OpType.Multiply; }
+        | DIV {  $$ = Operator.OpType.Division; }
+        | PERCENT { $$ = Operator.OpType.Modulus; }
+        | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
+        | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
+        | CARRET { $$ = Operator.OpType.ExclusiveOr; }
+        | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
+        | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
+        | OP_EQ { $$ = Operator.OpType.Equality; }
+        | OP_NE { $$ = Operator.OpType.Inequality; }
+        | OP_GT { $$ = Operator.OpType.GreaterThan; }
+        | OP_LT { $$ = Operator.OpType.LessThan; }
+        | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
+        | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
+       ;
+
+conversion_operator_declarator
+       : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
+                                             null, null, lexer.Location);
+         }
+       | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
+                                             null, null, lexer.Location);
+         }
+       ;
+
+constructor_declaration
+       : opt_attributes
+         opt_modifiers
+         constructor_declarator
+         block
+         { 
+               Constructor c = (Constructor) $3;
+               c.Block = (Block) $4;
+               c.ModFlags = (int) $2;
+
+               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");
+                       }
+
+                       if (c.Initializer != null){
+                               Location l = lexer.Location;
+                               Report.Error (514, l, "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");
+                       }
+               } 
+               
+               CheckDef (current_container.AddConstructor (c), c.Name);
+
+               current_local_parameters = null;
+         }
+       ;
+
+constructor_declarator
+       : IDENTIFIER 
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         opt_constructor_initializer
+         {
+               Location l = lexer.Location;
+
+               $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $5, l);
+       
+               current_local_parameters = (Parameters) $3;
+         }
+       ;
+
+opt_constructor_initializer
+       : /* empty */                   { $$ = null; }
+       | constructor_initializer
+       ;
+
+constructor_initializer
+       : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
+         }
+       | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
+         }
+       ;
+
+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);
+                 
+               d.Block = (Block) $6;
+               CheckDef (current_container.AddMethod (d), d.Name);
+         }
+       ;
+
+event_declaration
+       : opt_attributes
+         opt_modifiers
+         EVENT type variable_declarators SEMICOLON
+         {
+               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);
+
+                       CheckDef (current_container.AddEvent (e), e.Name);
+                                      
+               }
+         }
+       | opt_attributes
+         opt_modifiers
+         EVENT type member_name 
+         OPEN_BRACE event_accessor_declarations CLOSE_BRACE
+       {
+               DictionaryEntry pair = (DictionaryEntry) $7;
+               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;
+               
+               Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);
+               
+               CheckDef (current_container.AddEvent (e), e.Name);
+       }
+       ;
+
+event_accessor_declarations
+       : add_accessor_declaration remove_accessor_declaration
+       {
+               $$ = new DictionaryEntry ($1, $2);
+       }
+       | remove_accessor_declaration add_accessor_declaration
+       {
+               $$ = new DictionaryEntry ($2, $1);
+       }       
+       ;
+
+add_accessor_declaration
+       : opt_attributes ADD block
+         {
+               $$ = $3;
+         }
+       ;
+
+remove_accessor_declaration
+       : opt_attributes REMOVE block
+       {
+               $$ = $3;
+       }
+       ;
+
+indexer_declaration
+       : opt_attributes opt_modifiers indexer_declarator 
+         OPEN_BRACE 
+         {
+               IndexerDeclaration decl = (IndexerDeclaration) $3;
+                 
+               lexer.properties = true;
+               parsing_indexer  = true;
+               
+               current_local_parameters = decl.param_list;
+         }
+          accessor_declarations 
+         {
+                 lexer.properties = false;
+                 parsing_indexer  = false;
+         }
+         CLOSE_BRACE
+         { 
+               // The signature is computed from the signature of the indexer.  Look
+               // at section 3.6 on the spec
+
+               Indexer indexer;
+               IndexerDeclaration decl = (IndexerDeclaration) $3;
+               DictionaryEntry pair = (DictionaryEntry) $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;
+
+               indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
+                                      get_block, set_block, (Attributes) $1);
+
+               // Note that there is no equivalent of CheckDef for this case
+               // We shall handle this in semantic analysis
+               
+               current_container.AddIndexer (indexer);
+               
+               current_local_parameters = null;
+         }
+       ;
+
+indexer_declarator
+       : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+         {
+               $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
+         }
+       | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+         {
+               $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
+         }
+       ;
+
+enum_declaration
+       : opt_attributes
+         opt_modifiers
+         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);
+
+               foreach (VariableDeclaration ev in (ArrayList) $6){
+                       CheckDef (e.AddEnumMember (ev.identifier, 
+                                                  (Expression) ev.expression_or_array_initializer),
+                                 ev.identifier);
+               }
+
+               CheckDef (current_container.AddEnum (e), name);
+         }
+       ;
+
+opt_enum_base
+       : /* empty */                   { $$ = "System.Int32"; }
+       | COLON integral_type           { $$ = $2;   }
+       ;
+
+enum_body
+       : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
+         {
+               $$ = $2;
+         }
+       ;
+
+opt_enum_member_declarations
+       : /* empty */                   { $$ = new ArrayList (); }
+       | enum_member_declarations opt_comma { $$ = $1; }
+       ;
+
+enum_member_declarations
+       : enum_member_declaration 
+         {
+               ArrayList l = new ArrayList ();
+
+               l.Add ($1);
+               $$ = l;
+         }
+       | enum_member_declarations COMMA enum_member_declaration
+         {
+               ArrayList l = (ArrayList) $1;
+
+               l.Add ($3);
+
+               $$ = l;
+         }
+       ;
+
+enum_member_declaration
+       : opt_attributes IDENTIFIER 
+         {
+               $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
+         }
+       | opt_attributes IDENTIFIER ASSIGN expression
+         { 
+               $$ = new VariableDeclaration ((string) $2, $4, lexer.Location);
+         }
+       ;
+
+delegate_declaration
+       : opt_attributes
+         opt_modifiers
+         DELEGATE type   
+         IDENTIFIER OPEN_PARENS 
+         formal_parameter_list
+         CLOSE_PARENS 
+         SEMICOLON
+         {
+               Delegate del = new Delegate ((string) $4, (int) $2, (string) $5, (Parameters) $7, 
+                                            (Attributes) $1, lexer.Location);
+
+               CheckDef (current_container.AddDelegate (del), del.Name);
+         }     
+       | opt_attributes
+         opt_modifiers
+         DELEGATE VOID   
+         IDENTIFIER OPEN_PARENS 
+         formal_parameter_list
+         CLOSE_PARENS 
+         SEMICOLON
+         {
+               Delegate del = new Delegate (null, (int) $2, (string) $5, (Parameters) $7, 
+                                            (Attributes) $1, lexer.Location);
+
+               CheckDef (current_container.AddDelegate (del), del.Name);
+         }
+       ;
+
+type_name
+       : namespace_or_type_name
+       ;
+
+namespace_or_type_name
+       : qualified_identifier
+       ;
+
+/* 
+ * Before you think of adding a return_type, notice that we have been
+ * using two rules in the places where it matters (one rule using type
+ * and another identical one that uses VOID as the return type).  This
+ * gets rid of a shift/reduce couple
+ */
+type
+       : type_name {   /* class_type */
+               /* 
+                  This does interfaces, delegates, struct_types, class_types, 
+                  parent classes, and more! 4.2 
+                */
+               $$ = $1; 
+         }
+       | builtin_types
+       | array_type
+       ;
+
+type_list
+       : type
+         {
+               ArrayList types = new ArrayList ();
+
+               types.Add ($1);
+               $$ = types;
+         }
+       | type_list COMMA type
+         {
+               ArrayList types = (ArrayList) $1;
+
+               types.Add ($3);
+               $$ = types;
+         }
+       ;
+
+/*
+ * replaces all the productions for isolating the various
+ * simple types, but we need this to reuse it easily in local_variable_type
+ */
+builtin_types
+       : OBJECT        { $$ = "System.Object"; }
+       | STRING        { $$ = "System.String"; }
+       | BOOL          { $$ = "System.Boolean"; }
+       | DECIMAL       { $$ = "System.Decimal"; }
+       | FLOAT         { $$ = "System.Single"; }
+       | DOUBLE        { $$ = "System.Double"; }
+       | integral_type
+       ;
+
+integral_type
+       : SBYTE         { $$ = "System.SByte"; }
+       | BYTE          { $$ = "System.Byte"; }
+       | SHORT         { $$ = "System.Int16"; }
+       | USHORT        { $$ = "System.UInt16"; }
+       | INT           { $$ = "System.Int32"; }
+       | UINT          { $$ = "System.UInt32"; }
+       | LONG          { $$ = "System.Int64"; }
+       | ULONG         { $$ = "System.UInt64"; }
+       | CHAR          { $$ = "System.Char"; }
+       ;
+
+interface_type
+       : type_name
+       ;
+
+array_type
+       : type rank_specifiers
+         {
+                 $$ = (string) $1 + (string) $2;
+         }
+       ;
+
+//
+// Expressions, section 7.5
+//
+primary_expression
+       : literal
+         {
+               // 7.5.1: Literals
+         }
+       | qualified_identifier
+         {
+               string name = (string) $1;
+
+               $$ = null;
+               $$ = QualifiedIdentifier (name, lexer.Location);
+         }
+       | parenthesized_expression
+       | member_access
+       | invocation_expression
+       | element_access
+       | this_access
+       | base_access
+       | post_increment_expression
+       | post_decrement_expression
+       | new_expression
+       | typeof_expression
+       | sizeof_expression
+       | checked_expression
+       | unchecked_expression
+       ;
+
+literal
+       : boolean_literal
+       | integer_literal
+       | real_literal
+       | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
+       | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
+       | NULL                  { $$ = new NullLiteral (); }
+       ;
+
+real_literal
+       : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
+       | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
+       | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
+       ;
+
+integer_literal
+       : LITERAL_INTEGER       { 
+               object v = lexer.Value;
+
+               // 
+               // FIXME: Possible optimization would be to 
+               // compute the *Literal objects directly in the scanner
+               //
+               if (v is int)
+                       $$ = new IntLiteral ((Int32) v); 
+               else if (v is uint)
+                       $$ = new UIntLiteral ((UInt32) v);
+               else if (v is long)
+                       $$ = new LongLiteral ((Int64) v);
+               else if (v is ulong)
+                       $$ = new ULongLiteral ((UInt64) v);
+               else
+                       Console.WriteLine ("OOPS.  Unexpected result from scanner");
+         }
+       ;
+
+boolean_literal
+       : TRUE                  { $$ = new BoolLiteral (true); }
+       | FALSE                 { $$ = new BoolLiteral (false); }
+       ;
+
+parenthesized_expression
+       : OPEN_PARENS expression CLOSE_PARENS
+         { $$ = $2; }
+       ;
+
+member_access
+       : primary_expression DOT IDENTIFIER
+         {
+               $$ = new MemberAccess ((Expression) $1, (string) $3);
+         }
+       | predefined_type DOT IDENTIFIER
+         {
+               $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
+         }
+       ;
+
+predefined_type
+       : builtin_types
+       ;
+
+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);
+               
+         }
+       ; 
+
+opt_argument_list
+       : /* empty */           { $$ = null; }
+       | argument_list
+       ;
+
+argument_list
+       : argument              
+         { 
+               ArrayList list = new ArrayList ();
+               list.Add ($1);
+               $$ = list;
+         }
+       | argument_list COMMA argument
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+argument
+       : expression
+         {
+               $$ = new Argument ((Expression) $1, Argument.AType.Expression);
+         }
+       | REF variable_reference 
+         { 
+               $$ = new Argument ((Expression) $2, Argument.AType.Ref);
+         }
+       | OUT variable_reference 
+         { 
+               $$ = new Argument ((Expression) $2, Argument.AType.Out);
+         }
+       ;
+
+variable_reference
+       : expression { note ("section 5.4"); $$ = $1; }
+       ;
+
+element_access
+       : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
+         {
+               $$ = new ElementAccess ((Expression) $1, (ArrayList) $3);
+         }
+       ;
+
+expression_list
+       : expression
+         {
+               ArrayList list = new ArrayList ();
+               list.Add ($1);
+               $$ = list;
+         }
+       | expression_list COMMA expression
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+this_access
+       : THIS
+         {
+               $$ = new This ();
+         }
+       ;
+
+base_access
+       : BASE DOT IDENTIFIER
+         {
+               $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);
+         }
+       | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
+         {
+               $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);
+         }
+       ;
+
+post_increment_expression
+       : primary_expression OP_INC
+         {
+               $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1, lexer.Location);
+         }
+       ;
+
+post_decrement_expression
+       : primary_expression OP_DEC
+         {
+               $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1, lexer.Location);
+         }
+       ;
+
+new_expression
+       : object_or_delegate_creation_expression
+       | array_creation_expression
+       ;
+
+object_or_delegate_creation_expression
+       : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
+         }
+       ;
+
+array_creation_expression
+       : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
+         opt_rank_specifier
+         opt_array_initializer
+         {
+               $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
+         }
+       ;
+
+opt_rank_specifier
+       : /* empty */
+         {
+                 $$ = "";
+         }
+       | rank_specifiers
+         {
+                       $$ = $1;
+         }
+       ;
+
+rank_specifiers
+       : rank_specifier
+         {
+                 $$ = $1;
+         }
+       | rank_specifier rank_specifiers
+         {
+                 $$ = (string) $1 + (string) $2;
+         }             
+        ;
+
+rank_specifier
+       : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
+         {
+               $$ = "[" + (string) $2 + "]";
+         }
+       ;
+
+opt_dim_separators
+       : /* empty */
+         {
+               $$ = "";
+         }
+       | dim_separators
+         {
+                 $$ = $1;
+         }               
+       ;
+
+dim_separators
+       : COMMA
+         {
+               $$ = ",";
+         }
+       | dim_separators COMMA
+         {
+               $$ =(string) $1 + ",";
+         }
+       ;
+
+opt_array_initializer
+       : /* empty */
+         {
+               $$ = null;
+         }
+        | array_initializer
+         {
+               $$ = $1;
+         }
+       ;
+
+array_initializer
+       : OPEN_BRACE CLOSE_BRACE
+         {
+               ArrayList list = new ArrayList ();
+               $$ = list;
+         }
+       | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
+       {
+               $$ = (ArrayList) $2;
+       }
+       ;
+
+variable_initializer_list
+       : variable_initializer
+       {
+               ArrayList list = new ArrayList ();
+               list.Add ($1);
+               $$ = list;
+       }
+       | variable_initializer_list COMMA variable_initializer
+       {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+       }
+       ;
+
+typeof_expression
+       : TYPEOF OPEN_PARENS type CLOSE_PARENS
+         {
+               $$ = new TypeOf ((string) $3);
+         }
+       ;
+
+sizeof_expression
+       : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
+               $$ = new SizeOf ((string) $3);
+
+               note ("Verify type is unmanaged"); 
+               note ("if (5.8) builtin, yield constant expression");
+         }
+       ;
+
+checked_expression
+       : CHECKED OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = new CheckedExpr ((Expression) $3);
+         }
+       ;
+
+unchecked_expression
+       : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = new UnCheckedExpr ((Expression) $3);
+         }
+       ;
+
+unary_expression
+       : primary_expression
+       | PLUS unary_expression         { 
+               $$ = new Unary (Unary.Operator.Addition, (Expression) $2, lexer.Location);
+         } 
+       | MINUS unary_expression 
+         { 
+               $$ = new Unary (Unary.Operator.Subtraction, (Expression) $2, lexer.Location);
+         }
+       | BANG unary_expression 
+         {
+               $$ = new Unary (Unary.Operator.Negate, (Expression) $2, lexer.Location);
+         }
+       | TILDE unary_expression
+         {
+               $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2, lexer.Location);
+         }
+       | STAR unary_expression
+         {
+               $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
+         }
+       | BITWISE_AND 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 
+         {
+               $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
+         }
+       ;
+
+pre_decrement_expression
+       : OP_DEC 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);
+         }
+       | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
+         {
+               $$ = new Cast ((string) $2, (Expression) $4);
+         }
+       ;
+
+multiplicative_expression
+       : unary_expression
+       | multiplicative_expression STAR unary_expression
+         {
+               $$ = new Binary (Binary.Operator.Multiply, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | multiplicative_expression DIV unary_expression
+         {
+               $$ = new Binary (Binary.Operator.Division, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | multiplicative_expression PERCENT unary_expression 
+         {
+               $$ = new Binary (Binary.Operator.Modulus, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+additive_expression
+       : multiplicative_expression
+       | additive_expression PLUS multiplicative_expression 
+         {
+               $$ = new Binary (Binary.Operator.Addition, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | additive_expression MINUS multiplicative_expression
+         {
+               $$ = new Binary (Binary.Operator.Subtraction, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+shift_expression
+       : additive_expression
+       | shift_expression OP_SHIFT_LEFT additive_expression
+         {
+               $$ = new Binary (Binary.Operator.LeftShift, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | shift_expression OP_SHIFT_RIGHT additive_expression
+         {
+               $$ = new Binary (Binary.Operator.RightShift, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ; 
+
+relational_expression
+       : shift_expression
+       | relational_expression OP_LT shift_expression
+         {
+               $$ = new Binary (Binary.Operator.LessThan, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_GT shift_expression
+         {
+               $$ = new Binary (Binary.Operator.GreaterThan, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_LE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.LessThanOrEqual, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_GE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression IS type
+         {
+               $$ = new Probe (Probe.Operator.Is, 
+                                (Expression) $1, (string) $3);
+         }
+       | relational_expression AS type
+         {
+               $$ = new Probe (Probe.Operator.As, 
+                                (Expression) $1, (string) $3);
+         }
+       ;
+
+equality_expression
+       : relational_expression
+       | equality_expression OP_EQ relational_expression
+         {
+               $$ = new Binary (Binary.Operator.Equality, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | equality_expression OP_NE relational_expression
+         {
+               $$ = new Binary (Binary.Operator.Inequality, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ; 
+
+and_expression
+       : equality_expression
+       | and_expression BITWISE_AND equality_expression
+         {
+               $$ = new Binary (Binary.Operator.BitwiseAnd, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+exclusive_or_expression
+       : and_expression
+       | exclusive_or_expression CARRET and_expression
+         {
+               $$ = new Binary (Binary.Operator.ExclusiveOr, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+inclusive_or_expression
+       : exclusive_or_expression
+       | inclusive_or_expression BITWISE_OR exclusive_or_expression
+         {
+               $$ = new Binary (Binary.Operator.BitwiseOr, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+conditional_and_expression
+       : inclusive_or_expression
+       | conditional_and_expression OP_AND inclusive_or_expression
+         {
+               $$ = new Binary (Binary.Operator.LogicalAnd, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+conditional_or_expression
+       : conditional_and_expression
+       | conditional_or_expression OP_OR conditional_and_expression
+         {
+               $$ = new Binary (Binary.Operator.LogicalOr, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+conditional_expression
+       : conditional_or_expression
+       | conditional_or_expression INTERR expression COLON expression 
+         {
+               $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
+         }
+       ;
+
+assignment_expression
+       : unary_expression ASSIGN expression
+         {
+               $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       | 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);
+         }
+       ;
+
+expression
+       : conditional_expression
+       | assignment_expression
+       ;
+
+constant_expression
+       : expression
+       ;
+
+boolean_expression
+       : expression    { CheckBoolean ((Expression) $1); $$ = $1; } 
+       ;
+
+//
+// 10 classes
+//
+class_declaration
+       : opt_attributes
+         opt_modifiers
+         CLASS IDENTIFIER
+         {
+               Class new_class;
+               string full_class_name = MakeName ((string) $4);
+
+               new_class = new Class (rc, current_container, full_class_name, (int) $2, 
+                                      (Attributes) $1, lexer.Location);
+               current_container = new_class;
+               current_container.Namespace = current_namespace;
+               tree.RecordClass (full_class_name, new_class);
+         }
+         opt_class_base
+         class_body 
+         opt_semicolon 
+         {
+               Class new_class = (Class) current_container;
+
+               if ($6 != null)
+                       new_class.Bases = (ArrayList) $6;
+
+               current_container = current_container.Parent;
+               CheckDef (current_container.AddClass (new_class), new_class.Name);
+
+               $$ = new_class;
+         }
+       ;       
+
+opt_modifiers
+       : /* empty */           { $$ = (int) 0; }
+       | modifiers
+       ;
+
+modifiers
+       : modifier
+       | modifiers modifier
+         { 
+               int m1 = (int) $1;
+               int m2 = (int) $2;
+
+               if ((m1 & m2) != 0) {
+                       Location l = lexer.Location;
+                       Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
+               }
+               $$ = (int) (m1 | m2);
+         }
+        ;
+
+modifier
+       : NEW                   { $$ = Modifiers.NEW; }
+       | PUBLIC                { $$ = Modifiers.PUBLIC; }
+       | PROTECTED             { $$ = Modifiers.PROTECTED; }
+       | INTERNAL              { $$ = Modifiers.INTERNAL; }
+       | PRIVATE               { $$ = Modifiers.PRIVATE; }
+       | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
+       | SEALED                { $$ = Modifiers.SEALED; }
+       | STATIC                { $$ = Modifiers.STATIC; }
+       | READONLY              { $$ = Modifiers.READONLY; }
+       | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
+       | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
+       | EXTERN                { $$ = Modifiers.EXTERN; }
+       ;
+
+opt_class_base
+       : /* empty */           { $$ = null; }
+       | class_base            { $$ = $1;   }
+       ;
+
+class_base
+       : COLON type_list { $$ = $2; }
+       ;
+
+//
+// Statements (8.2)
+//
+
+//
+// A block is "contained" on the following places:
+//     method_body
+//     property_declaration as part of the accessor body (get/set)
+//      operator_declaration
+//     constructor_declaration
+//     destructor_declaration
+//     event_declaration as part of add_accessor_declaration or remove_accessor_declaration
+//      
+block
+       : OPEN_BRACE 
+         {
+               current_block = new Block (current_block);
+         } 
+         opt_statement_list CLOSE_BRACE 
+         { 
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ;
+
+opt_statement_list
+       : /* empty */
+       | statement_list 
+       ;
+
+statement_list
+       : statement
+       | statement_list statement
+       ;
+
+statement
+       : declaration_statement
+         {
+               if ((Block) $1 != current_block){
+                       current_block.AddStatement ((Statement) $1);
+                       current_block = (Block) $1;
+               }
+         }
+       | embedded_statement
+         {
+               current_block.AddStatement ((Statement) $1);
+         }
+       | labeled_statement 
+         {
+               current_block.AddStatement ((Statement) $1);
+         }
+       ;
+
+embedded_statement
+       : block
+       | empty_statement
+        | expression_statement
+       | selection_statement
+       | iteration_statement
+       | jump_statement                  
+       | try_statement
+       | checked_statement
+       | unchecked_statement
+       | lock_statement
+       | using_statement
+       ;
+
+empty_statement
+       : SEMICOLON
+         {
+                 $$ = new EmptyStatement ();
+         }
+       ;
+
+labeled_statement
+       : IDENTIFIER COLON statement
+         {
+               string lab = (String) $1;
+               Block block;
+
+               block = new Block (current_block, lab);
+               block.AddStatement ((Statement) $3);
+               $$ = block;
+
+               if (!current_block.AddLabel (lab, block)){
+                       Location l = lexer.Location;
+                       Report.Error (140, l, "The label '" + lab + "' is a duplicate");
+                       $$ = $3;
+               }       
+         }
+       ;
+
+declaration_statement
+       : local_variable_declaration SEMICOLON          // done
+       | local_constant_declaration SEMICOLON          // finishme
+       ;
+
+/* 
+ * The following is from Rhys' grammar:
+ * > Types in local variable declarations must be recognized as 
+ * > expressions to prevent reduce/reduce errors in the grammar.
+ * > The expressions are converted into types during semantic analysis.
+ */
+local_variable_type
+       : primary_expression type_suffixes
+         { 
+               // FIXME: Do something smart here regarding the composition of the type.
+
+               // Ok, the above "primary_expression" is there to get rid of
+               // both reduce/reduce and shift/reduces in the grammar, it should
+               // really just be "type_name".  If you use type_name, a reduce/reduce
+               // 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 {
+                       Location l = lexer.Location;
+                       Report.Error (-1, l, "Invalid Type definition");
+                       $$ = "System.Object";
+               }
+         }
+       | builtin_types type_suffixes
+         {
+               $$ = (string) $1 + (string) $2;
+         }
+        ;
+
+// 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";
+//       }
+//     ;
+
+type_suffixes
+       : /* empty */
+         {
+               $$ = "";
+         }
+       | type_suffix_list
+       ;
+
+type_suffix_list 
+       : type_suffix
+       | type_suffix_list type_suffix
+         {
+               $$ = (string) $1 + (string) $2;
+         }
+       ;
+
+type_suffix
+       : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
+         {
+               $$ = "[" + (string) $2 + "]";
+         }
+       ;
+
+local_variable_declaration
+       : local_variable_type variable_declarators
+         {
+               $$ = declare_local_variables ((string) $1, (ArrayList) $2);
+         }
+       ;
+
+local_constant_declaration
+       : CONST type constant_declarator
+               // finishme     
+       ;
+
+expression_statement
+       : statement_expression SEMICOLON
+         {
+               $$ = $1;
+         }
+       ;
+
+       //
+       // We have to do the wrapping here and not in the case above,
+       // 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); }
+       ;
+
+object_creation_expression
+       : object_or_delegate_creation_expression
+         { note ("complain if this is a delegate maybe?"); } 
+       ;
+
+selection_statement
+       : if_statement
+       | switch_statement
+       ; 
+
+if_statement
+       : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
+         embedded_statement
+         { 
+               $$ = new If ((Expression) $3, (Statement) $5);
+         }
+       | IF OPEN_PARENS boolean_expression CLOSE_PARENS
+         embedded_statement ELSE embedded_statement
+         {
+               $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
+         }
+       ;
+
+switch_statement
+       : SWITCH OPEN_PARENS expression CLOSE_PARENS 
+         switch_block
+         {
+               $$ = new Switch ((Expression) $3, (ArrayList) $5);
+         }
+       ;
+
+switch_block
+       : OPEN_BRACE
+         opt_switch_sections
+         CLOSE_BRACE
+         {
+               $$ = $2;
+         }
+       ;
+
+opt_switch_sections
+       : /* empty */           { $$ = new ArrayList (); }
+       | switch_sections
+       ;
+
+switch_sections
+       : switch_section 
+         {
+               ArrayList sections = new ArrayList ();
+
+               sections.Add ($1);
+               $$ = sections;
+         }
+       | switch_sections switch_section
+         {
+               ArrayList sections = (ArrayList) $1;
+
+               sections.Add ($2);
+               $$ = sections;
+         }
+       ;
+
+switch_section
+       : switch_labels
+         {
+               current_block = new Block (current_block);
+         }
+         statement_list 
+         {
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = new SwitchSection ((ArrayList) $1, current_block);
+               current_block = current_block.Parent;
+         }
+       ;
+
+switch_labels
+       : switch_label 
+         {
+               ArrayList labels = new ArrayList ();
+
+               labels.Add ($1);
+               $$ = labels;
+         }
+       | switch_labels switch_label 
+         {
+               ArrayList labels = (ArrayList) ($1);
+               labels.Add ($2);
+
+               $$ = labels;
+         }
+       ;
+
+switch_label
+       : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2); }
+       | DEFAULT COLON                         { $$ = new SwitchLabel (null); }
+       ;
+
+iteration_statement
+       : while_statement
+       | do_statement
+       | for_statement
+       | foreach_statement
+       ;
+
+while_statement
+       : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
+       {
+               $$ = new While ((Expression) $3, (Statement) $5);
+       }
+       ;
+
+do_statement
+       : DO embedded_statement 
+         WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
+         {
+               $$ = new Do ((Statement) $2, (Expression) $5);
+         }
+       ;
+
+for_statement
+       : FOR OPEN_PARENS 
+         opt_for_initializer SEMICOLON
+         opt_for_condition SEMICOLON
+         opt_for_iterator CLOSE_PARENS 
+         embedded_statement
+         {
+               $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
+         }
+       ;
+
+opt_for_initializer
+       : /* empty */           { $$ = new EmptyStatement (); }
+       | for_initializer       
+       ;
+
+for_initializer
+       : local_variable_declaration
+       | statement_expression_list
+       ;
+
+opt_for_condition
+       : /* empty */           { $$ = new BoolLiteral (true); }
+       | boolean_expression
+       ;
+
+opt_for_iterator
+       : /* empty */           { $$ = new EmptyStatement (); }
+       | for_iterator
+       ;
+
+for_iterator
+       : statement_expression_list
+       ;
+
+statement_expression_list
+       : statement_expression  
+         {
+               Block b = new Block (null, true);
+
+               b.AddStatement ((Statement) $1);
+               $$ = b;
+         }
+       | statement_expression_list COMMA statement_expression
+         {
+               Block b = (Block) $1;
+
+               b.AddStatement ((Statement) $3);
+               $$ = $1;
+         }
+       ;
+
+foreach_statement
+       : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS 
+         embedded_statement
+         {
+               string temp_id = current_block.MakeInternalID ();
+               ExpressionStatement assign_e;
+               Expression ma;
+               Statement getcurrent;
+               Block foreach_block, child_block;
+               Location l = lexer.Location;
+
+               foreach_block = new Block (current_block, true);
+
+               foreach_block.AddVariable ("System.IEnumerator", temp_id, l);
+               foreach_block.AddVariable ((string) $3, (string) $4, l);
+               assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id), 
+                                      new Invocation (
+                                               new MemberAccess ((Expression) $6, "GetEnumerator"), 
+                                               null, lexer.Location), lexer.Location);
+               current_block.AddStatement (new StatementExpression (assign_e));
+               ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");
+               child_block = new Block (current_block);
+
+               getcurrent = new StatementExpression (
+                       new Assign (
+                               new LocalVariableReference (foreach_block, (string) $4),
+                               new Cast (
+                                       (string) $3, 
+                                       new MemberAccess (
+                               new LocalVariableReference (foreach_block, temp_id), "Current")), 
+                               lexer.Location));
+
+               child_block.AddStatement (getcurrent);
+               child_block.AddStatement ((Statement) $8);
+               foreach_block.AddStatement (new While (ma, (Statement) child_block));
+
+               $$ = foreach_block;
+         }
+       ;
+
+jump_statement
+       : break_statement
+       | continue_statement
+       | goto_statement
+       | return_statement
+       | throw_statement
+       ;
+
+break_statement
+       : BREAK SEMICOLON
+         {
+               $$ = new Break ();
+         }
+       ;
+
+continue_statement
+       : CONTINUE SEMICOLON
+         {
+               $$ = new Continue ();
+         }
+       ;
+
+goto_statement
+       : GOTO IDENTIFIER SEMICOLON 
+         {
+               $$ = new Goto ((string) $2);
+         }
+       | GOTO CASE constant_expression SEMICOLON
+       | GOTO DEFAULT SEMICOLON 
+       ; 
+
+return_statement
+       : RETURN opt_expression SEMICOLON
+         {
+               $$ = new Return ((Expression) $2);
+         }
+       ;
+
+throw_statement
+       : THROW opt_expression SEMICOLON
+         {
+               $$ = new Throw ((Expression) $2);
+         }
+       ;
+
+opt_expression
+       : /* empty */
+       | expression
+       ;
+
+try_statement
+       : TRY block catch_clauses 
+       {
+               Catch g = null;
+               ArrayList s = new ArrayList ();
+               
+               foreach (Catch cc in (ArrayList) $3) {
+                       if (cc.Type == null)
+                               g = cc;
+                       else
+                               s.Add (cc);
+               }
+
+               // Now s contains the list of specific catch clauses
+               // and g contains the general one.
+               
+               $$ = new Try ((Block) $2, s, g, null);
+       }
+       | TRY block opt_catch_clauses FINALLY block
+         {
+               Catch g = null;
+               ArrayList s = new ArrayList ();
+               
+               foreach (Catch cc in (ArrayList) $3) {
+                       if (cc.Type == null)
+                               g = cc;
+                       else
+                               s.Add (cc);
+               }
+
+               $$ = new Try ((Block) $2, s, g, (Block) $5);
+         }
+       ;
+
+opt_catch_clauses
+       : /* empty */  { $$ = null; }
+        | catch_clauses
+       ;
+
+catch_clauses
+       : catch_clause 
+         {
+               ArrayList l = new ArrayList ();
+
+               l.Add ($1);
+               $$ = l;
+         }
+       | catch_clauses catch_clause
+         {
+               ArrayList l = (ArrayList) $1;
+
+               l.Add ($2);
+               $$ = l;
+         }
+       ;
+
+opt_identifier
+       : /* empty */   { $$ = null; }
+       | IDENTIFIER
+       ;
+
+catch_clause 
+       : CATCH opt_catch_args block
+       {
+               string type = null;
+               string id = null;
+               
+               if ($2 != null) {
+                       DictionaryEntry cc = (DictionaryEntry) $2;
+                       type = (string) cc.Key;
+                       id   = (string) cc.Value;
+               }
+
+               $$ = new Catch (type, id, (Block) $3);
+       }
+        ;
+
+opt_catch_args
+       : /* empty */ { $$ = null; }
+        | catch_args
+       ;         
+
+catch_args 
+        : OPEN_PARENS type opt_identifier CLOSE_PARENS 
+        {
+               $$ = new DictionaryEntry ($2, $3);
+       }
+        ;
+
+checked_statement
+       : CHECKED block
+         {
+               $$ = new Checked ((Block) $2);
+         }
+       ;
+
+unchecked_statement
+       : UNCHECKED block
+         {
+               $$ = new Unchecked ((Block) $2);
+         }
+       ;
+
+lock_statement
+       : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
+         {
+               $$ = new Lock ((Expression) $3, (Statement) $5);
+         }
+       ;
+
+using_statement
+       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
+         // finishme
+       ; 
+
+resource_acquisition
+       : local_variable_declaration
+         expression
+         // finishme
+       ;
+
+%%
+
+// <summary>
+//   A class used to pass around variable declarations and constants
+// </summary>
+public class VariableDeclaration {
+       public string identifier;
+       public object expression_or_array_initializer;
+       public Location Location;
+
+       public VariableDeclaration (string id, object eoai, Location l){
+               this.identifier = id;
+               this.expression_or_array_initializer = eoai;
+               this.Location = l;
+       }
+}
+
+// <summary>
+//   A class used to hold info about an indexer declarator
+// </summary>
+
+public class IndexerDeclaration {
+       public string type;
+       public string interface_type;
+       public Parameters param_list;
+
+       public IndexerDeclaration (string type, string interface_type, Parameters param_list)
+       {
+               this.type = type;
+               this.interface_type = interface_type;
+               this.param_list = param_list;
+       }
+}
+
+// <summary>
+//  A class used to hold info about an operator declarator
+// </summary>
+
+public class OperatorDeclaration {
+       public Operator.OpType optype;
+       public string ret_type;
+       public string arg1type;
+       public string arg1name;
+       public string arg2type;
+       public string arg2name;
+       public Location location;
+
+       public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
+                                   string arg2type, string arg2name, Location location)
+       {
+               optype = op;
+               this.ret_type = ret_type;
+               this.arg1type = arg1type;
+               this.arg1name = arg1name;
+               this.arg2type = arg2type;
+               this.arg2name = arg2name;
+               this.location = location;
+       }
+
+}
+
+// <summary>
+//   Given the @class_name name, it creates a fully qualified name
+//   based on the containing declaration space
+// </summary>
+string 
+MakeName (string class_name)
+{
+       string ns = current_namespace.Name;
+       string container_name = current_container.Name;
+
+       if (container_name == ""){
+               if (ns != "")
+                       return ns + "." + class_name;
+               else
+                       return class_name;
+       } else
+               return container_name + "." + class_name;
+}
+
+// <summary>
+//   Used to report back to the user the result of a declaration
+//   in the current declaration space
+// </summary>
+void 
+CheckDef (DeclSpace.AdditionResult result, string name)
+{
+       if (result == DeclSpace.AdditionResult.Success)
+               return;
+
+       Location l = lexer.Location;
+       
+       switch (result){
+       case DeclSpace.AdditionResult.NameExists:
+               Report.Error (102, l, "The namespace `" + 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:
+               Report.Error (542, l, "Member names cannot be the same as their enclosing type");
+               break;
+               
+       case DeclSpace.AdditionResult.NotAConstructor:
+               Report.Error (1520, l, "Class, struct, or interface method must have a return type");
+               break;
+       }
+}
+
+void 
+CheckDef (bool result, string name)
+{
+       if (result)
+               return;
+       CheckDef (DeclSpace.AdditionResult.NameExists, name);
+}
+
+object 
+SimpleLookup (string name)
+{
+       //
+       // 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;
+               Parameter par = current_local_parameters.GetParameterByName (name, out idx);
+               if (par != null)
+                       return new ParameterReference (current_local_parameters, idx, name);
+       }
+
+       return null;
+}
+
+// 
+// Assumes that the name contains a `.' and tries to perform a simple lookup
+// and shape the result to be a MemberAccess on a Local/Parameter
+//
+object CompositeLookup (string name)
+{
+       int pos = name.IndexOf (".");
+       string left = name.Substring (0, pos);
+       object o;
+
+       o = SimpleLookup (left);
+       if (o != null){
+               string right = name.Substring (pos + 1);
+               return new MemberAccess ((Expression) o, right);
+       }
+
+       return null;
+}
+
+object QualifiedIdentifier (string name, Location l)
+{
+       object o;
+
+       if (name.IndexOf ('.') == -1)
+               o = SimpleLookup (name);
+       else 
+               o = CompositeLookup (name);
+
+       if (o == null)
+               o = new SimpleName (name, l);
+
+       return o;
+}
+
+Block declare_local_variables (string type, ArrayList variable_declarators)
+{
+       Block implicit_block;
+       ArrayList inits = null;
+
+       //
+       // We use the `Used' property to check whether statements
+       // have been added to the current block.  If so, we need
+       // to create another block to contain the new declaration
+       // otherwise, as an optimization, we use the same block to
+       // add the declaration.
+       //
+       // FIXME: A further optimization is to check if the statements
+       // that were added were added as part of the initialization
+       // below.  In which case, no other statements have been executed
+       // and we might be able to reduce the number of blocks for
+       // situations like this:
+       //
+       // int j = 1;  int k = j + 1;
+       //
+       if (current_block.Used)
+               implicit_block = new Block (current_block, true);
+       else
+               implicit_block = new Block (current_block, true);
+
+       foreach (VariableDeclaration decl in variable_declarators){
+               if (implicit_block.AddVariable (type, decl.identifier, decl.Location)){
+                       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 +
+                                        "' is already defined in this scope");
+               }
+       }
+
+       if (inits == null)
+               return implicit_block;
+
+       foreach (VariableDeclaration decl in inits){
+               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));
+               } else {
+                       Console.WriteLine ("Not handling Array initializers yet");
+               }
+       }
+                       
+       return implicit_block;
+}
+
+void CheckConstant (Expression expr)
+{
+       // finishme
+}
+
+void CheckBoolean (Expression expr)
+{
+       // finishme
+}
+
+void CheckAttributeTarget (string a)
+{
+       switch (a) {
+
+       case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
+               return;
+               
+       default :
+               Location l = lexer.Location;
+               Report.Error (658, l, "Invalid attribute target");
+               break;
+       }
+
+}
+
+void CheckUnaryOperator (Operator.OpType op)
+{
+       switch (op) {
+               
+       case Operator.OpType.Negate: 
+       case Operator.OpType.BitComplement: 
+       case Operator.OpType.Increment:
+       case Operator.OpType.Decrement:
+       case Operator.OpType.True: 
+       case Operator.OpType.False: 
+       case Operator.OpType.Addition: 
+       case Operator.OpType.Subtraction:
+               
+               break;
+               
+       default :
+               Location l = lexer.Location;
+               Report.Error (1019, l, "Overloadable unary operator expected"); 
+               break;
+               
+       }
+}
+
+void CheckBinaryOperator (Operator.OpType op)
+{
+       switch (op) {
+               
+       case Operator.OpType.Addition: 
+       case Operator.OpType.Subtraction: 
+       case Operator.OpType.Multiply:
+       case Operator.OpType.Division:
+       case Operator.OpType.Modulus: 
+       case Operator.OpType.BitwiseAnd: 
+       case Operator.OpType.BitwiseOr:
+       case Operator.OpType.ExclusiveOr: 
+       case Operator.OpType.LeftShift: 
+       case Operator.OpType.RightShift:
+       case Operator.OpType.Equality: 
+       case Operator.OpType.Inequality:
+       case Operator.OpType.GreaterThan: 
+       case Operator.OpType.LessThan: 
+       case Operator.OpType.GreaterThanOrEqual:
+       case Operator.OpType.LessThanOrEqual:
+               break;
+               
+       default :
+               Location l = lexer.Location;
+               Report.Error (1020, l, "Overloadable binary operator expected");
+               break;
+       }
+       
+}
+
+void output (string s)
+{
+       Console.WriteLine (s);
+}
+
+void note (string s)
+{
+       // Used to put annotations
+}
+
+Tokenizer lexer;
+
+public Tokenizer Lexer {
+       get {
+               return lexer;
+       }
+}                 
+
+public CSharpParser(RootContext rc, string name, System.IO.Stream input) 
+{
+       current_namespace = new Namespace (null, "");
+       this.rc   = rc;
+       this.tree = rc.Tree;
+       this.name = name;
+       this.input = input;
+       current_container = tree.Types;
+       current_container.Namespace = current_namespace;
+
+       lexer = new Tokenizer (input, name);
+}
+
+public override int parse ()
+{
+       StringBuilder value = new StringBuilder ();
+
+       global_errors = 0;
+       try {
+               if (yacc_verbose_flag)
+                       yyparse (lexer, new yydebug.yyDebugSimple ());
+               else
+                       yyparse (lexer);
+       } catch (Exception e){
+               // Console.WriteLine ("Fatal error: " + name);
+               // Console.WriteLine (lexer.location);
+
+               Console.WriteLine (lexer.location + "  : Parsing error");
+               Console.WriteLine (e);
+               global_errors++;
+       }
+       
+       return global_errors;
+}
+
+
+/* end end end */
+}