2004-06-09 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
1 %{
2 //
3 // cs-parser.jay: The Parser for the C# compiler
4 //
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 //          Ravi Pratap     (ravi@ximian.com)
7 //
8 // Licensed under the terms of the GNU GPL
9 //
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
11 //
12 // TODO:
13 //   (1) Figure out why error productions dont work.  `type-declaration' is a
14 //       great spot to put an `error' because you can reproduce it with this input:
15 //       "public X { }"
16 //
17 // Possible optimization:
18 //   Run memory profiler with parsing only, and consider dropping 
19 //   arraylists where not needed.   Some pieces can use linked lists.
20 //
21 using System.Text;
22 using System.IO;
23 using System;
24
25 namespace Mono.CSharp
26 {
27         using System.Collections;
28         using Mono.Languages;
29
30         /// <summary>
31         ///    The C# Parser
32         /// </summary>
33         public class CSharpParser : GenericParser {
34                 NamespaceEntry  current_namespace;
35                 TypeContainer   current_container;
36         
37                 IIteratorContainer iterator_container;
38
39                 /// <summary>
40                 ///   Current block is used to add statements as we find
41                 ///   them.  
42                 /// </summary>
43                 Block      current_block;
44
45                 /// <summary>
46                 ///   If true, creates a toplevel block in the block production
47                 ///   This is flagged by the delegate creation
48                 /// </summary>
49                 bool       create_toplevel_block;
50         
51                 /// <summary>
52                 /// <summary>
53                 ///   Current interface is used by the various declaration
54                 ///   productions in the interface declaration to "add"
55                 ///   the interfaces as we find them.
56                 /// </summary>
57                 Interface  current_interface;
58
59                 /// <summary>
60                 ///   This is used by the unary_expression code to resolve
61                 ///   a name against a parameter.  
62                 /// </summary>
63                 Parameters current_local_parameters;
64
65                 /// <summary>
66                 ///   Using during property parsing to describe the implicit
67                 ///   value parameter that is passed to the "set" and "get"accesor
68                 ///   methods (properties and indexers).
69                 /// </summary>
70                 Expression implicit_value_parameter_type;
71                 Parameters indexer_parameters;
72
73                 /// <summary>
74                 ///   Used to determine if we are parsing the get/set pair
75                 ///   of an indexer or a property
76                 /// </summmary>
77                 bool  parsing_indexer;
78
79                 ///
80                 /// An out-of-band stack.
81                 ///
82                 Stack oob_stack;
83
84                 ///
85                 /// Switch stack.
86                 ///
87                 Stack switch_stack;
88
89                 ///
90                 /// The current file.
91                 ///
92                 SourceFile file;
93                 
94                 
95                 /// Current attribute target
96                 string current_attr_target;
97                 
98                 /// assembly and module attribute definition is enabled
99                 bool global_attrs_enabled = true;
100 %}
101
102 %token EOF
103 %token NONE   /* This token is never returned by our lexer */
104 %token ERROR            // This is used not by the parser, but by the tokenizer.
105                         // do not remove.
106
107 /*
108  *These are the C# keywords
109  */
110 %token FIRST_KEYWORD
111 %token ABSTRACT 
112 %token AS
113 %token ADD
114 %token ASSEMBLY
115 %token BASE     
116 %token BOOL     
117 %token BREAK    
118 %token BYTE     
119 %token CASE     
120 %token CATCH    
121 %token CHAR     
122 %token CHECKED  
123 %token CLASS    
124 %token CONST    
125 %token CONTINUE 
126 %token DECIMAL  
127 %token DEFAULT  
128 %token DELEGATE 
129 %token DO       
130 %token DOUBLE   
131 %token ELSE     
132 %token ENUM     
133 %token EVENT    
134 %token EXPLICIT 
135 %token EXTERN   
136 %token FALSE    
137 %token FINALLY  
138 %token FIXED    
139 %token FLOAT    
140 %token FOR      
141 %token FOREACH  
142 %token GOTO     
143 %token IF       
144 %token IMPLICIT 
145 %token IN       
146 %token INT      
147 %token INTERFACE
148 %token INTERNAL 
149 %token IS       
150 %token LOCK     
151 %token LONG     
152 %token NAMESPACE
153 %token NEW      
154 %token NULL     
155 %token OBJECT   
156 %token OPERATOR 
157 %token OUT      
158 %token OVERRIDE 
159 %token PARAMS   
160 %token PRIVATE  
161 %token PROTECTED
162 %token PUBLIC   
163 %token READONLY 
164 %token REF      
165 %token RETURN   
166 %token REMOVE
167 %token SBYTE    
168 %token SEALED   
169 %token SHORT    
170 %token SIZEOF   
171 %token STACKALLOC
172 %token STATIC   
173 %token STRING   
174 %token STRUCT   
175 %token SWITCH   
176 %token THIS     
177 %token THROW    
178 %token TRUE     
179 %token TRY      
180 %token TYPEOF   
181 %token UINT     
182 %token ULONG    
183 %token UNCHECKED
184 %token UNSAFE   
185 %token USHORT   
186 %token USING    
187 %token VIRTUAL  
188 %token VOID     
189 %token VOLATILE
190 %token WHILE    
191 %token ARGLIST
192
193 /* C# keywords which are not really keywords */
194 %token GET           "get"
195 %token SET           "set"
196
197 %left LAST_KEYWORD
198
199 /* C# single character operators/punctuation. */
200 %token OPEN_BRACE    "{"
201 %token CLOSE_BRACE   "}"
202 %token OPEN_BRACKET  "["
203 %token CLOSE_BRACKET "]"
204 %token OPEN_PARENS   "("
205 %token CLOSE_PARENS  ")"
206 %token DOT           "."
207 %token COMMA         ","
208 %token COLON         ":"
209 %token SEMICOLON     ";"
210 %token TILDE         "~"
211
212 %token PLUS           "+"
213 %token MINUS          "-"
214 %token BANG           "!"
215 %token ASSIGN         "="
216 %token OP_LT          "<"
217 %token OP_GT          ">"
218 %token BITWISE_AND    "&"
219 %token BITWISE_OR     "|"
220 %token STAR           "*"
221 %token PERCENT        "%"
222 %token DIV            "/"
223 %token CARRET         "^"
224 %token INTERR         "?"
225
226 /* C# multi-character operators. */
227 %token OP_INC                 "++"
228 %token OP_DEC                 "--"
229 %token OP_SHIFT_LEFT          "<<"
230 %token OP_SHIFT_RIGHT         ">>"
231 %token OP_LE                  "<="
232 %token OP_GE                  ">="
233 %token OP_EQ                  "=="
234 %token OP_NE                  "!="
235 %token OP_AND                 "&&"
236 %token OP_OR                  "||"
237 %token OP_MULT_ASSIGN         "*="
238 %token OP_DIV_ASSIGN          "/="
239 %token OP_MOD_ASSIGN          "%="
240 %token OP_ADD_ASSIGN          "+="
241 %token OP_SUB_ASSIGN          "-="
242 %token OP_SHIFT_LEFT_ASSIGN   "<<="
243 %token OP_SHIFT_RIGHT_ASSIGN  ">>="
244 %token OP_AND_ASSIGN          "&="
245 %token OP_XOR_ASSIGN          "^="
246 %token OP_OR_ASSIGN           "|="
247 %token OP_PTR                 "->"
248
249 /* Numbers */
250 %token LITERAL_INTEGER           "int literal"
251 %token LITERAL_FLOAT             "float literal"
252 %token LITERAL_DOUBLE            "double literal"
253 %token LITERAL_DECIMAL           "decimal literal"
254 %token LITERAL_CHARACTER         "character literal"
255 %token LITERAL_STRING            "string literal"
256
257 %token IDENTIFIER
258 %token CLOSE_PARENS_CAST
259 %token CLOSE_PARENS_NO_CAST
260 %token CLOSE_PARENS_OPEN_PARENS
261 %token CLOSE_PARENS_MINUS
262
263 /* Add precedence rules to solve dangling else s/r conflict */
264 %nonassoc LOWPREC
265 %nonassoc IF
266 %nonassoc ELSE
267 %right ASSIGN
268 %left OP_OR
269 %left OP_AND
270 %left BITWISE_OR
271 %left BITWISE_AND
272 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
273 %left PLUS MINUS
274 %left STAR DIV PERCENT
275 %right BANG CARRET UMINUS
276 %nonassoc OP_INC OP_DEC
277 %left OPEN_PARENS
278 %left OPEN_BRACKET OPEN_BRACE
279 %left DOT
280 %nonassoc HIGHPREC
281
282 %start compilation_unit
283 %%
284
285 compilation_unit
286         : outer_declarations opt_EOF
287         | outer_declarations global_attributes opt_EOF
288         | global_attributes opt_EOF
289         | opt_EOF /* allow empty files */
290         ;
291         
292 opt_EOF
293         : /* empty */
294         | EOF
295         ;
296
297 outer_declarations
298         : outer_declaration
299         | outer_declarations outer_declaration
300         ;
301  
302 outer_declaration
303         : using_directive
304         | namespace_member_declaration
305         ;
306   
307 using_directives
308         : using_directive 
309         | using_directives using_directive
310         ;
311
312 using_directive
313         : using_alias_directive
314         | using_namespace_directive
315         ;
316
317 using_alias_directive
318         : USING IDENTIFIER ASSIGN 
319           namespace_or_type_name SEMICOLON
320           {
321                   current_namespace.UsingAlias ((string) $2, (Expression) $4, lexer.Location);
322           }
323         | USING error {
324                 CheckIdentifierToken (yyToken);
325           }
326         ;
327
328 using_namespace_directive
329         : USING namespace_name SEMICOLON 
330           {
331                 current_namespace.Using ((string) $2, lexer.Location);
332           }
333         ;
334
335 //
336 // Strictly speaking, namespaces don't have attributes but
337 // we parse global attributes along with namespace declarations and then
338 // detach them
339 // 
340 namespace_declaration
341         : opt_attributes NAMESPACE namespace_or_type_name
342         {
343                 if ($1 != null) {
344                         Report.Error(1518, Lexer.Location, "Attributes cannot be applied to namespaces."
345                                         + " Expected class, delegate, enum, interface, or struct");
346                 }
347
348                 current_namespace = RootContext.Tree.RecordNamespace (current_namespace, file, $3.ToString (), lexer.Location);
349         } 
350           namespace_body opt_semicolon
351           { 
352                 current_namespace = current_namespace.Parent;
353           }
354         ;
355
356 opt_semicolon
357         : /* empty */
358         | SEMICOLON
359         ;
360
361 opt_comma
362         : /* empty */
363         | COMMA
364         ;
365
366 namespace_name
367         : namespace_or_type_name { $$ = ($1).ToString (); } 
368         ;
369
370 namespace_body
371         : OPEN_BRACE
372           opt_using_directives
373           opt_namespace_member_declarations
374           CLOSE_BRACE
375           {
376           }
377         ;
378
379 opt_using_directives
380         : /* empty */
381         | using_directives
382         ;
383
384 opt_namespace_member_declarations
385         : /* empty */
386         | namespace_member_declarations
387         ;
388
389 namespace_member_declarations
390         : namespace_member_declaration
391         | namespace_member_declarations namespace_member_declaration
392         ;
393
394 namespace_member_declaration
395         : type_declaration
396           {
397                 string name = "";
398                 int mod_flags;
399
400                 if ($1 is Class){
401                         Class c = (Class) $1;
402                         mod_flags = c.ModFlags;
403                         name = c.Name;
404                 } else if ($1 is Struct){
405                         Struct s = (Struct) $1;
406                         mod_flags = s.ModFlags;
407                         name = s.Name;
408                 } else
409                         break;
410
411                 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
412                         Report.Error (
413                                 1527, lexer.Location, 
414                                 "Namespace elements cant be explicitly " +
415                                 "declared private or protected in `" + name + "'");
416                 }
417                 current_namespace.DeclarationFound = true;
418           }
419         | namespace_declaration {
420                 current_namespace.DeclarationFound = true;
421           }
422
423         | field_declaration {
424                 Report.Error (116, lexer.Location, "A namespace can only contain types and namespace declarations");
425           }
426         | method_declaration {
427                 Report.Error (116, lexer.Location, "A namespace can only contain types and namespace declarations");
428           }
429         ;
430
431 type_declaration
432         : class_declaration             
433         | struct_declaration            
434         | interface_declaration         
435         | enum_declaration              
436         | delegate_declaration
437 //
438 // Enable this when we have handled all errors, because this acts as a generic fallback
439 //
440 //      | error {
441 //              Console.WriteLine ("Token=" + yyToken);
442 //              Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
443 //        }
444         ;
445
446 //
447 // Attributes 17.2
448 //
449
450 global_attributes
451         : attribute_sections
452 {
453         if ($1 != null)
454                 CodeGen.Assembly.AddAttributes (((Attributes)$1).Attrs);
455
456         $$ = $1;
457 }
458
459 opt_attributes
460         : /* empty */ 
461           {
462                 global_attrs_enabled = false;
463                 $$ = null;
464       }
465         | attribute_sections
466           { 
467                 global_attrs_enabled = false;
468                 $$ = $1;
469           }
470     ;
471  
472
473 attribute_sections
474         : attribute_section
475       {
476                 ArrayList sect = (ArrayList) $1;
477
478                 if (global_attrs_enabled) {
479                         if (current_attr_target == "module") {
480                                 CodeGen.Module.AddAttributes (sect);
481                                 $$ = null;
482                         } else if (current_attr_target == "assembly") {
483                                 CodeGen.Assembly.AddAttributes (sect);
484                                 $$ = null;
485                         } else {
486                                 $$ = new Attributes (sect);
487                         }
488                 } else {
489                         $$ = new Attributes (sect);
490                 }               
491                 current_attr_target = null;
492       }
493         | attribute_sections attribute_section
494           {
495                 Attributes attrs = $1 as Attributes;
496                 ArrayList sect = (ArrayList) $2;
497
498                 if (global_attrs_enabled) {
499                         if (current_attr_target == "module") {
500                                 CodeGen.Module.AddAttributes (sect);
501                                 $$ = null;
502                         } else if (current_attr_target == "assembly") {
503                                 CodeGen.Assembly.AddAttributes (sect);
504                                 $$ = null;
505                         } else {
506                                 if (attrs == null)
507                                         attrs = new Attributes (sect);
508                                 else
509                                         attrs.AddAttributes (sect);                     
510                         }
511                 } else {
512                         if (attrs == null)
513                                 attrs = new Attributes (sect);
514                         else
515                                 attrs.AddAttributes (sect);
516                 }               
517                 $$ = attrs;
518                 current_attr_target = null;
519           }
520         ;
521
522 attribute_section
523         : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
524           {
525                 $$ = $3;
526           }
527         | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
528           {
529                 $$ = $2;
530           }
531         ;
532  
533 attribute_target_specifier
534         : attribute_target COLON
535           {
536                 current_attr_target = (string)$1;
537                 $$ = $1;
538           }
539         ;
540
541 attribute_target
542         : IDENTIFIER
543           {
544                 CheckAttributeTarget ((string) $1);
545                 $$ = $1;
546           }
547         | EVENT  { $$ = "event"; }        
548         | RETURN { $$ = "return"; }
549         ;
550
551 attribute_list
552         : attribute
553           {
554                 ArrayList attrs = new ArrayList (4);
555                 attrs.Add ($1);
556
557                 $$ = attrs;
558                
559           }
560         | attribute_list COMMA attribute
561           {
562                 ArrayList attrs = (ArrayList) $1;
563                 attrs.Add ($3);
564
565                 $$ = attrs;
566           }
567         ;
568
569 attribute
570         : attribute_name
571           {
572                 $$ = lexer.Location;
573           }
574           opt_attribute_arguments
575           {
576                 if (current_attr_target == "assembly" || current_attr_target == "module")
577                         $$ = new GlobalAttribute (current_container, current_attr_target, (string) ($1).ToString (), (ArrayList) $3, (Location) $2);
578                 else
579                         $$ = new Attribute (current_attr_target, (string) ($1).ToString (), (ArrayList) $3, (Location) $2);
580           }
581         ;
582
583 attribute_name
584         : type_name  { /* reserved attribute name or identifier: 17.4 */ }
585         ;
586
587 opt_attribute_arguments
588         : /* empty */   { $$ = null; }
589         | OPEN_PARENS attribute_arguments CLOSE_PARENS
590           {
591                 $$ = $2;
592           }
593         ;
594
595
596 attribute_arguments
597         : opt_positional_argument_list
598           {
599                 if ($1 == null)
600                         $$ = null;
601                 else {
602                         ArrayList args = new ArrayList (4);
603                         args.Add ($1);
604                 
605                         $$ = args;
606                 }
607           }
608         | positional_argument_list COMMA named_argument_list
609           {
610                 ArrayList args = new ArrayList (4);
611                 args.Add ($1);
612                 args.Add ($3);
613
614                 $$ = args;
615           }
616         | named_argument_list
617           {
618                 ArrayList args = new ArrayList (4);
619                 args.Add (null);
620                 args.Add ($1);
621                 
622                 $$ = args;
623           }
624         ;
625
626
627 opt_positional_argument_list
628         : /* empty */           { $$ = null; } 
629         | positional_argument_list
630         ;
631
632 positional_argument_list
633         : expression
634           {
635                 ArrayList args = new ArrayList (4);
636                 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
637
638                 $$ = args;
639           }
640         | positional_argument_list COMMA expression
641          {
642                 ArrayList args = (ArrayList) $1;
643                 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
644
645                 $$ = args;
646          }
647         ;
648
649 named_argument_list
650         : named_argument
651           {
652                 ArrayList args = new ArrayList (4);
653                 args.Add ($1);
654
655                 $$ = args;
656           }
657         | named_argument_list COMMA named_argument
658           {       
659                 ArrayList args = (ArrayList) $1;
660                 args.Add ($3);
661
662                 $$ = args;
663           }
664         ;
665
666 named_argument
667         : IDENTIFIER ASSIGN expression
668           {
669                 $$ = new DictionaryEntry (
670                         (string) $1, 
671                         new Argument ((Expression) $3, Argument.AType.Expression));
672           }
673         ;
674
675                   
676 class_body
677         :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
678         ;
679
680 opt_class_member_declarations
681         : /* empty */
682         | class_member_declarations
683         ;
684
685 class_member_declarations
686         : class_member_declaration
687         | class_member_declarations 
688           class_member_declaration
689         ;
690
691 class_member_declaration
692         : constant_declaration                  // done
693         | field_declaration                     // done
694         | method_declaration                    // done
695         | property_declaration                  // done
696         | event_declaration                     // done
697         | indexer_declaration                   // done
698         | operator_declaration                  // done
699         | constructor_declaration               // done
700         | destructor_declaration                // done
701         | type_declaration
702         ;
703
704 struct_declaration
705         : opt_attributes
706           opt_modifiers
707           STRUCT IDENTIFIER
708           { 
709                 Struct new_struct;
710                 string full_struct_name = MakeName ((string) $4);
711
712                 new_struct = new Struct (current_namespace, current_container, full_struct_name,
713                                          (int) $2, (Attributes) $1, lexer.Location);
714                 current_container = new_struct;
715                 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
716           }
717           opt_class_base
718           struct_body
719           opt_semicolon
720           {
721                 Struct new_struct = (Struct) current_container;
722
723                 if ($6 != null)
724                         new_struct.Bases = (ArrayList) $6;
725
726                 current_container = current_container.Parent;
727                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
728                 $$ = new_struct;
729           }
730         | opt_attributes opt_modifiers STRUCT error {
731                 CheckIdentifierToken (yyToken);
732           }
733         ;
734
735 struct_body
736         : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
737         ;
738
739 opt_struct_member_declarations
740         : /* empty */
741         | struct_member_declarations
742         ;
743
744 struct_member_declarations
745         : struct_member_declaration
746         | struct_member_declarations struct_member_declaration
747         ;
748
749 struct_member_declaration
750         : constant_declaration
751         | field_declaration
752         | method_declaration
753         | property_declaration
754         | event_declaration
755         | indexer_declaration
756         | operator_declaration
757         | constructor_declaration
758         | type_declaration
759
760         /*
761          * This is only included so we can flag error 575: 
762          * destructors only allowed on class types
763          */
764         | destructor_declaration 
765         ;
766
767 constant_declaration
768         : opt_attributes 
769           opt_modifiers
770           CONST
771           type
772           constant_declarators
773           SEMICOLON
774           {
775                 foreach (VariableDeclaration constant in (ArrayList) $5){
776                         Location l = constant.Location;
777
778                         Const c = new Const (
779                                 (Expression) $4, (string) constant.identifier, 
780                                 (Expression) constant.expression_or_array_initializer, (int) $2, 
781                                 (Attributes) $1, l);
782
783                         CheckDef (current_container.AddConstant (c), c.Name, l);
784                 }
785           }
786         ;
787
788 constant_declarators
789         : constant_declarator 
790           {
791                 ArrayList constants = new ArrayList (4);
792                 constants.Add ($1);
793                 $$ = constants;
794           }
795         | constant_declarators COMMA constant_declarator
796           {
797                 ArrayList constants = (ArrayList) $1;
798
799                 constants.Add ($3);
800           }
801         ;
802
803 constant_declarator
804         : IDENTIFIER ASSIGN constant_expression
805           {
806                 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
807           }
808         ;
809
810 field_declaration
811         : opt_attributes
812           opt_modifiers
813           type 
814           variable_declarators
815           SEMICOLON
816           { 
817                 Expression type = (Expression) $3;
818                 int mod = (int) $2;
819
820                 foreach (VariableDeclaration var in (ArrayList) $4){
821                         Location l = var.Location;
822
823                         Field field = new Field (type, mod, var.identifier, 
824                                                  var.expression_or_array_initializer, 
825                                                  (Attributes) $1, l);
826
827                         CheckDef (current_container.AddField (field), field.Name, l);
828                 }
829           }
830         | opt_attributes
831           opt_modifiers
832           VOID  
833           variable_declarators
834           SEMICOLON {
835                 Report.Error (670, lexer.Location, "void type is not allowed for fields");
836           }
837         ;
838
839 variable_declarators
840         : variable_declarator 
841           {
842                 ArrayList decl = new ArrayList (4);
843                 decl.Add ($1);
844                 $$ = decl;
845           }
846         | variable_declarators COMMA variable_declarator
847           {
848                 ArrayList decls = (ArrayList) $1;
849                 decls.Add ($3);
850                 $$ = $1;
851           }
852         ;
853
854 variable_declarator
855         : IDENTIFIER ASSIGN variable_initializer
856           {
857                 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
858           }
859         | IDENTIFIER
860           {
861                 $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
862           }
863         ;
864
865 variable_initializer
866         : expression
867           {
868                 $$ = $1;
869           }
870         | array_initializer
871           {
872                 $$ = $1;
873           }
874         | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
875           {
876                 $$ = new StackAlloc ((Expression) $2, (Expression) $4, lexer.Location);
877           }
878         ;
879
880 method_declaration
881         : method_header {
882                 iterator_container = (IIteratorContainer) $1;
883           }
884           method_body
885           {
886                 Method method = (Method) $1;
887                 Block b = (Block) $3;
888                 const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
889
890                 if (b == null){
891                         if ((method.ModFlags & extern_abstract) == 0){
892                                 Report.Error (
893                                         501, lexer.Location,  current_container.MakeName (method.Name) +
894                                         "must declare a body because it is not marked abstract or extern");
895                         }
896                 } else {
897                         if ((method.ModFlags & Modifiers.EXTERN) != 0){
898                                 Report.Error (
899                                         179, lexer.Location, current_container.MakeName (method.Name) +
900                                         " is declared extern, but has a body");
901                         }
902                 }
903
904                 method.Block = (Block) $3;
905                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
906
907                 current_local_parameters = null;
908                 iterator_container = null;
909           }
910         ;
911
912 opt_error_modifier
913         : /* empty */
914         | modifiers 
915           {
916                 int m = (int) $1;
917                 int i = 1;
918
919                 while (m != 0){
920                         if ((i & m) != 0){
921                                 Report.Error (
922                                         1585, lexer.Location, "Member modifier `" + 
923                                         Modifiers.Name (i) + "' must precede member type and name");
924                         }
925                         m &= ~i;
926                         i = i << 1;
927                 }
928           }
929         ;
930
931 method_header
932         : opt_attributes
933           opt_modifiers
934           type
935           member_name
936           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
937           {
938                 Method method = new Method (current_container, (Expression) $3, (int) $2,
939                                             false, (string) $4,  (Parameters) $6,
940                                             (Attributes) $1, lexer.Location);
941
942                 current_local_parameters = (Parameters) $6;
943
944                 $$ = method;
945           }
946         | opt_attributes
947           opt_modifiers
948           VOID
949           member_name
950           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
951           {
952                 Method method = new Method (current_container, TypeManager.system_void_expr,
953                                             (int) $2, false, (string) $4, (Parameters) $6,
954                                             (Attributes) $1, lexer.Location);
955
956                 current_local_parameters = (Parameters) $6;
957                 $$ = method;
958           }
959         | opt_attributes
960           opt_modifiers
961           type 
962           modifiers member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
963           {
964                 Report.Error (1585, lexer.Location, 
965                         String.Format ("Modifier {0} should appear before type", 
966                                 Modifiers.Name ((int) $4)));
967                 Method method = new Method (current_container, TypeManager.system_void_expr,
968                                             0, false, (string) $5, (Parameters) $7,
969                                             (Attributes) $1, lexer.Location);
970
971                 current_local_parameters = (Parameters) $7;
972                 $$ = method;
973           }
974         ;
975
976 method_body
977         : block
978         | SEMICOLON             { $$ = null; }
979         ;
980
981 opt_formal_parameter_list
982         : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
983         | formal_parameter_list
984         ;
985
986 formal_parameter_list
987         : fixed_parameters              
988           { 
989                 ArrayList pars_list = (ArrayList) $1;
990
991                 Parameter [] pars = new Parameter [pars_list.Count];
992                 pars_list.CopyTo (pars);
993
994                 $$ = new Parameters (pars, null, lexer.Location); 
995           } 
996         | fixed_parameters COMMA parameter_array
997           {
998                 ArrayList pars_list = (ArrayList) $1;
999
1000                 Parameter [] pars = new Parameter [pars_list.Count];
1001                 pars_list.CopyTo (pars);
1002
1003                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1004           }
1005         | fixed_parameters COMMA ARGLIST
1006           {
1007                 ArrayList pars_list = (ArrayList) $1;
1008
1009                 Parameter [] pars = new Parameter [pars_list.Count];
1010                 pars_list.CopyTo (pars);
1011
1012                 $$ = new Parameters (pars, true, lexer.Location);
1013           }
1014         | parameter_array 
1015           {
1016                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1017           }
1018         | ARGLIST
1019           {
1020                 $$ = new Parameters (null, true, lexer.Location);
1021           }
1022         ;
1023
1024 fixed_parameters
1025         : fixed_parameter       
1026           {
1027                 ArrayList pars = new ArrayList (4);
1028
1029                 pars.Add ($1);
1030                 $$ = pars;
1031           }
1032         | fixed_parameters COMMA fixed_parameter
1033           {
1034                 ArrayList pars = (ArrayList) $1;
1035
1036                 pars.Add ($3);
1037                 $$ = $1;
1038           }
1039         ;
1040
1041 fixed_parameter
1042         : opt_attributes
1043           opt_parameter_modifier
1044           type
1045           IDENTIFIER
1046           {
1047                 $$ = new Parameter ((Expression) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
1048           }
1049         | opt_attributes
1050           opt_parameter_modifier
1051           type
1052           error {
1053                 CheckIdentifierToken (yyToken);
1054                 $$ = null;
1055           }
1056         ;
1057
1058 opt_parameter_modifier
1059         : /* empty */           { $$ = Parameter.Modifier.NONE; }
1060         | parameter_modifier
1061         ;
1062
1063 parameter_modifier
1064         : REF                   { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1065         | OUT                   { $$ = Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; }
1066         ;
1067
1068 parameter_array
1069         : opt_attributes PARAMS type IDENTIFIER
1070           { 
1071                 $$ = new Parameter ((Expression) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
1072                 note ("type must be a single-dimension array type"); 
1073           }
1074         | opt_attributes PARAMS type error {
1075                 CheckIdentifierToken (yyToken);
1076                 $$ = null;
1077           }
1078         ;
1079
1080 member_name 
1081         : namespace_or_type_name { $$ = ($1).ToString (); } 
1082         ;
1083
1084 property_declaration
1085         : opt_attributes
1086           opt_modifiers
1087           type member_name
1088           OPEN_BRACE 
1089           {
1090                 implicit_value_parameter_type = (Expression) $3;
1091
1092                 lexer.PropertyParsing = true;
1093
1094                 $$ = lexer.Location;
1095
1096                 iterator_container = SimpleIteratorContainer.GetSimple ();
1097           }
1098           accessor_declarations 
1099           {
1100                 lexer.PropertyParsing = false;
1101           }
1102           CLOSE_BRACE
1103           { 
1104                 Property prop;
1105                 Pair pair = (Pair) $7;
1106                 Accessor get_block = (Accessor) pair.First;
1107                 Accessor set_block = (Accessor) pair.Second;
1108
1109                 Location loc = (Location) $6;
1110                 prop = new Property (current_container, (Expression) $3, (int) $2, false,
1111                                      (string) $4, (Attributes) $1, get_block, set_block, loc);
1112                 if (SimpleIteratorContainer.Simple.Yields)
1113                         prop.SetYields ();
1114                 
1115                 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1116                 implicit_value_parameter_type = null;
1117                 iterator_container = null;
1118           }
1119         ;
1120
1121 accessor_declarations
1122         : get_accessor_declaration opt_set_accessor_declaration
1123           { 
1124                 $$ = new Pair ($1, $2);
1125           }
1126         | set_accessor_declaration opt_get_accessor_declaration
1127           {
1128                 $$ = new Pair ($2, $1);
1129           }
1130         ;
1131
1132 opt_get_accessor_declaration
1133         : /* empty */                   { $$ = null; }
1134         | get_accessor_declaration
1135         ;
1136
1137 opt_set_accessor_declaration
1138         : /* empty */                   { $$ = null; }
1139         | set_accessor_declaration
1140         ;
1141
1142 get_accessor_declaration
1143         : opt_attributes GET
1144           {
1145                 // If this is not the case, then current_local_parameters has already
1146                 // been set in indexer_declaration
1147                 if (parsing_indexer == false)
1148                         current_local_parameters = null;
1149                 else 
1150                         current_local_parameters = indexer_parameters;
1151                 lexer.PropertyParsing = false;
1152           }
1153           accessor_body
1154           {
1155                 $$ = new Accessor ((Block) $4, (Attributes) $1);
1156                 current_local_parameters = null;
1157                 lexer.PropertyParsing = true;
1158           }
1159         ;
1160
1161 set_accessor_declaration
1162         : opt_attributes SET 
1163           {
1164                 Parameter [] args;
1165                 Parameter implicit_value_parameter = new Parameter (
1166                         implicit_value_parameter_type, "value", 
1167                         Parameter.Modifier.NONE, null);
1168
1169                 if (parsing_indexer == false) {
1170                         args  = new Parameter [1];
1171                         args [0] = implicit_value_parameter;
1172                         current_local_parameters = new Parameters (args, null, lexer.Location);
1173                 } else {
1174                         Parameter [] fpars = indexer_parameters.FixedParameters;
1175
1176                         if (fpars != null){
1177                                 int count = fpars.Length;
1178
1179                                 args = new Parameter [count + 1];
1180                                 fpars.CopyTo (args, 0);
1181                                 args [count] = implicit_value_parameter;
1182                         } else 
1183                                 args = null;
1184                         current_local_parameters = new Parameters (
1185                                 args, indexer_parameters.ArrayParameter, lexer.Location);
1186                 }
1187                 
1188                 lexer.PropertyParsing = false;
1189           }
1190           accessor_body
1191           {
1192                 $$ = new Accessor ((Block) $4, (Attributes) $1);
1193                 current_local_parameters = null;
1194                 lexer.PropertyParsing = true;
1195           }
1196         ;
1197
1198 accessor_body
1199         : block 
1200         | SEMICOLON             { $$ = null; }
1201         ;
1202
1203 interface_declaration
1204         : opt_attributes
1205           opt_modifiers
1206           INTERFACE IDENTIFIER
1207           {
1208                 Interface new_interface;
1209                 string full_interface_name = MakeName ((string) $4);
1210
1211                 new_interface = new Interface (current_namespace, current_container, full_interface_name,
1212                                                (int) $2, (Attributes) $1, lexer.Location);
1213                 if (current_interface != null) {
1214                         Location l = lexer.Location;
1215                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
1216                 }
1217                 current_interface = new_interface;
1218                 current_container = new_interface;
1219                 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1220           }
1221           opt_class_base
1222           interface_body opt_semicolon
1223           { 
1224                 Interface new_interface = (Interface) current_interface;
1225
1226                 if ($6 != null)
1227                         new_interface.Bases = (ArrayList) $6;
1228
1229                 current_interface = null;
1230                 current_container = current_container.Parent;
1231                 CheckDef (current_container.AddInterface (new_interface), 
1232                           new_interface.Name, new_interface.Location);
1233           }
1234         | opt_attributes opt_modifiers INTERFACE error {
1235                 CheckIdentifierToken (yyToken);
1236           }
1237         ;
1238
1239 interface_body
1240         : OPEN_BRACE
1241           opt_interface_member_declarations
1242           CLOSE_BRACE
1243         ;
1244
1245 opt_interface_member_declarations
1246         : /* empty */
1247         | interface_member_declarations
1248         ;
1249
1250 interface_member_declarations
1251         : interface_member_declaration
1252         | interface_member_declarations interface_member_declaration
1253         ;
1254
1255 interface_member_declaration
1256         : interface_method_declaration          
1257           { 
1258                 Method m = (Method) $1;
1259
1260                 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1261           }
1262         | interface_property_declaration        
1263           { 
1264                 Property p = (Property) $1;
1265
1266                 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1267           }
1268         | interface_event_declaration 
1269           { 
1270                 if ($1 != null){
1271                         Event e = (Event) $1;
1272                         CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1273                 }
1274           }
1275         | interface_indexer_declaration
1276           { 
1277                 Indexer i = (Indexer) $1;
1278
1279                 current_interface.AddIndexer (i);
1280           }
1281         ;
1282
1283 opt_new
1284         : opt_modifiers 
1285           {
1286                 int val = (int) $1;
1287                 val = Modifiers.Check (Modifiers.NEW | Modifiers.UNSAFE, val, 0, lexer.Location);
1288                 $$ = val;
1289           }
1290         ;
1291
1292 interface_method_declaration
1293         : opt_attributes opt_new type IDENTIFIER 
1294           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1295           SEMICOLON
1296           {
1297                 $$ = new Method (current_container, (Expression) $3, (int) $2, true,
1298                                  (string) $4, (Parameters) $6, (Attributes) $1,
1299                                  lexer.Location);
1300           }
1301         | opt_attributes opt_new VOID IDENTIFIER 
1302           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1303           SEMICOLON
1304           {
1305                 $$ = new Method (current_container, TypeManager.system_void_expr, (int) $2,
1306                                  true, (string) $4, (Parameters) $6,  (Attributes) $1,
1307                                  lexer.Location);
1308           }
1309         ;
1310
1311 interface_property_declaration
1312         : opt_attributes
1313           opt_new
1314           type IDENTIFIER 
1315           OPEN_BRACE 
1316           { lexer.PropertyParsing = true; }
1317           interface_accessors 
1318           { lexer.PropertyParsing = false; }
1319           CLOSE_BRACE
1320           {
1321                 InterfaceAccessorInfo pinfo = (InterfaceAccessorInfo) $7;
1322
1323                 $$ = new Property (current_container, (Expression) $3, (int) $2, true,
1324                                    (string) $4, (Attributes) $1, pinfo.Get, pinfo.Set,
1325                                    lexer.Location);
1326           }
1327         | opt_attributes
1328           opt_new
1329           type error {
1330                 CheckIdentifierToken (yyToken);
1331                 $$ = null;
1332           }
1333         ;
1334
1335 interface_accessors
1336         : opt_attributes GET SEMICOLON          { $$ = new InterfaceAccessorInfo (true, false, (Attributes) $1, null); }
1337         | opt_attributes SET SEMICOLON          { $$ = new InterfaceAccessorInfo (false, true, null, (Attributes) $1); }
1338         | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON 
1339           { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $1, (Attributes) $3); }
1340         | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
1341           { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $3, (Attributes) $1); }
1342         ;
1343
1344 interface_event_declaration
1345         : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
1346           {
1347                 $$ = new EventField (current_container, (Expression) $4, (int) $2, true, (string) $5, null,
1348                                 (Attributes) $1, lexer.Location);
1349           }
1350         | opt_attributes opt_new EVENT type error {
1351                 CheckIdentifierToken (yyToken);
1352                 $$ = null;
1353           }
1354         | opt_attributes opt_new EVENT type IDENTIFIER ASSIGN  {
1355                 Report.Error (68, lexer.Location, "Event declarations on interfaces can not be initialized.");
1356                 $$ = null;
1357           }
1358         | opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE event_accessor_declarations CLOSE_BRACE {
1359                 Report.Error (69, lexer.Location, "Event accessors not valid on interfaces");
1360                 $$ = null;
1361           }
1362         ;
1363
1364 interface_indexer_declaration 
1365         : opt_attributes opt_new type THIS 
1366           OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1367           OPEN_BRACE 
1368           { lexer.PropertyParsing = true; }
1369           interface_accessors 
1370           { lexer.PropertyParsing = false; }
1371           CLOSE_BRACE
1372           {
1373                 InterfaceAccessorInfo info = (InterfaceAccessorInfo) $10;
1374
1375                 $$ = new Indexer (current_container, (Expression) $3, null, (int) $2, true,
1376                                   (Parameters) $6, (Attributes) $1, info.Get, info.Set,
1377                                   lexer.Location);
1378           }
1379         ;
1380
1381 operator_declaration
1382         : opt_attributes opt_modifiers operator_declarator 
1383           {
1384                 iterator_container = SimpleIteratorContainer.GetSimple ();
1385           }
1386           operator_body
1387           {
1388                 OperatorDeclaration decl = (OperatorDeclaration) $3;
1389                 
1390                 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
1391                                             decl.arg2type, decl.arg2name, (Block) $5, (Attributes) $1, decl.location);
1392
1393                 if (SimpleIteratorContainer.Simple.Yields)
1394                         op.SetYields ();
1395
1396                 // Note again, checking is done in semantic analysis
1397                 current_container.AddOperator (op);
1398
1399                 current_local_parameters = null;
1400                 iterator_container = null;
1401           }
1402         ;
1403
1404 operator_body 
1405         : block
1406         | SEMICOLON { $$ = null; }
1407         ; 
1408 operator_declarator
1409         : type OPERATOR overloadable_operator 
1410           OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1411         {
1412                 Operator.OpType op = (Operator.OpType) $3;
1413                 CheckUnaryOperator (op);
1414
1415                 if (op == Operator.OpType.Addition)
1416                         op = Operator.OpType.UnaryPlus;
1417
1418                 if (op == Operator.OpType.Subtraction)
1419                         op = Operator.OpType.UnaryNegation;
1420
1421                 Parameter [] pars = new Parameter [1];
1422
1423                 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1424
1425                 current_local_parameters = new Parameters (pars, null, lexer.Location);
1426
1427                 $$ = new OperatorDeclaration (op, (Expression) $1, (Expression) $5, (string) $6,
1428                                               null, null, lexer.Location);
1429         }
1430         | type OPERATOR overloadable_operator
1431           OPEN_PARENS 
1432                 type IDENTIFIER COMMA
1433                 type IDENTIFIER 
1434           CLOSE_PARENS
1435         {
1436                CheckBinaryOperator ((Operator.OpType) $3);
1437
1438                Parameter [] pars = new Parameter [2];
1439
1440                pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1441                pars [1] = new Parameter ((Expression) $8, (string) $9, Parameter.Modifier.NONE, null);
1442
1443                current_local_parameters = new Parameters (pars, null, lexer.Location);
1444                
1445                $$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1, 
1446                                              (Expression) $5, (string) $6,
1447                                              (Expression) $8, (string) $9, lexer.Location);
1448         }
1449         | conversion_operator_declarator
1450         ;
1451
1452 overloadable_operator
1453 // Unary operators:
1454         : BANG   { $$ = Operator.OpType.LogicalNot; }
1455         | TILDE  { $$ = Operator.OpType.OnesComplement; }  
1456         | OP_INC { $$ = Operator.OpType.Increment; }
1457         | OP_DEC { $$ = Operator.OpType.Decrement; }
1458         | TRUE   { $$ = Operator.OpType.True; }
1459         | FALSE  { $$ = Operator.OpType.False; }
1460 // Unary and binary:
1461         | PLUS { $$ = Operator.OpType.Addition; }
1462         | MINUS { $$ = Operator.OpType.Subtraction; }
1463 // Binary:
1464         | STAR { $$ = Operator.OpType.Multiply; }
1465         | DIV {  $$ = Operator.OpType.Division; }
1466         | PERCENT { $$ = Operator.OpType.Modulus; }
1467         | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
1468         | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
1469         | CARRET { $$ = Operator.OpType.ExclusiveOr; }
1470         | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
1471         | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
1472         | OP_EQ { $$ = Operator.OpType.Equality; }
1473         | OP_NE { $$ = Operator.OpType.Inequality; }
1474         | OP_GT { $$ = Operator.OpType.GreaterThan; }
1475         | OP_LT { $$ = Operator.OpType.LessThan; }
1476         | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
1477         | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
1478         ;
1479
1480 conversion_operator_declarator
1481         : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1482           {
1483                 Parameter [] pars = new Parameter [1];
1484
1485                 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1486
1487                 current_local_parameters = new Parameters (pars, null, lexer.Location);  
1488                   
1489                 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $5, (string) $6,
1490                                               null, null, lexer.Location);
1491           }
1492         | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1493           {
1494                 Parameter [] pars = new Parameter [1];
1495
1496                 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1497
1498                 current_local_parameters = new Parameters (pars, null, lexer.Location);  
1499                   
1500                 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (Expression) $3, (Expression) $5, (string) $6,
1501                                               null, null, lexer.Location);
1502           }
1503         | IMPLICIT error 
1504           {
1505                 syntax_error (lexer.Location, "'operator' expected");
1506           }
1507         | EXPLICIT error 
1508           {
1509                 syntax_error (lexer.Location, "'operator' expected");
1510           }
1511         ;
1512
1513 constructor_declaration
1514         : opt_attributes
1515           opt_modifiers
1516           constructor_declarator
1517           constructor_body
1518           { 
1519                 Constructor c = (Constructor) $3;
1520                 c.Block = (Block) $4;
1521                 c.OptAttributes = (Attributes) $1;
1522                 c.ModFlags = (int) $2;
1523         
1524                 if (c.Name == current_container.Basename){
1525                         if ((c.ModFlags & Modifiers.STATIC) != 0){
1526                                 if ((c.ModFlags & Modifiers.Accessibility) != 0){
1527                                         Report.Error (
1528                                                 515, c.Location, String.Format (
1529                                                 "`{0}.{1}': static constructor can not have access modifiers",
1530                                                 c.Name, current_container.Name));
1531                                 }
1532         
1533                                 c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);   
1534         
1535                                 if (c.Initializer != null){
1536                                         Report.Error (
1537                                                 514, c.Location, 
1538                                                 "Static constructors can not have an explicit this or base " +
1539                                                 "constructor invocations");
1540                                 }
1541         
1542                                 if (!c.Parameters.Empty){
1543                                         Report.Error (
1544                                                 132, c.Location, "Static constructors should not have parameters");
1545                                 }
1546                         } else {
1547                                 c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
1548                         }
1549                 } else {
1550                         // We let another layer check the validity of the constructor.
1551                         Console.WriteLine ("{0} and {1}", c.Name, current_container.Basename);
1552                 }
1553
1554                 CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
1555
1556                 current_local_parameters = null;
1557           }
1558         ;
1559
1560 constructor_declarator
1561         : IDENTIFIER 
1562           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
1563           {
1564                 oob_stack.Push (lexer.Location);
1565
1566                 current_local_parameters = (Parameters) $3;
1567           }
1568           opt_constructor_initializer
1569           {
1570                 Location l = (Location) oob_stack.Pop ();
1571                 $$ = new Constructor (current_container, (string) $1, 0, (Parameters) $3,
1572                                       (ConstructorInitializer) $6, l);
1573           }
1574         ;
1575
1576 constructor_body
1577         : block
1578         | SEMICOLON             { $$ = null; }
1579         ;
1580
1581 opt_constructor_initializer
1582         : /* empty */                   { $$ = null; }
1583         | constructor_initializer
1584         ;
1585
1586 constructor_initializer
1587         : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1588           {
1589                 $$ = new ConstructorBaseInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
1590           }
1591         | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1592           {
1593                 $$ = new ConstructorThisInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
1594           }
1595         | COLON error {
1596                 Report.Error (1018, lexer.Location, "Keyword this or base expected");
1597                 $$ = null;
1598           }
1599         ;
1600
1601 opt_finalizer
1602         : /* EMPTY */           { $$ = 0; }
1603         | UNSAFE                { $$ = Modifiers.UNSAFE; }
1604         | EXTERN                { $$ = Modifiers.EXTERN; }
1605         ;
1606         
1607 destructor_declaration
1608         : opt_attributes opt_finalizer TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1609           {
1610                 if ((string) $4 != current_container.Basename){
1611                         Report.Error (574, lexer.Location, "Name of destructor must match name of class");
1612                 } else if (!(current_container is Class)){
1613                         Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
1614                 } else {
1615                         Location l = lexer.Location;
1616
1617                         int m = (int) $2;
1618                         if (!RootContext.StdLib && current_container.Name == "System.Object")
1619                                 m |= Modifiers.PROTECTED | Modifiers.VIRTUAL;
1620                         else
1621                                 m |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
1622                         
1623                         if ((m & Modifiers.UNSAFE) != 0){
1624                                 if (!RootContext.Unsafe){
1625                                         Report.Error (227, l,
1626                                               "Unsafe code requires the -unsafe command " +
1627                                               "line option to be specified");
1628                                 }
1629                         }
1630                         
1631                         Method d = new Destructor (
1632                                 current_container, TypeManager.system_void_expr, m, "Finalize", 
1633                                 new Parameters (null, null, l), (Attributes) $1, l);
1634                   
1635                         d.Block = (Block) $7;
1636                         CheckDef (current_container.AddMethod (d), d.Name, d.Location);
1637                 }
1638           }
1639         ;
1640
1641 event_declaration
1642         : opt_attributes
1643           opt_modifiers
1644           EVENT type variable_declarators SEMICOLON
1645           {
1646                 foreach (VariableDeclaration var in (ArrayList) $5) {
1647
1648                         Event e = new EventField (current_container, (Expression) $4, (int) $2, false, var.identifier,
1649                                              var.expression_or_array_initializer,
1650                                              (Attributes) $1, lexer.Location);
1651
1652                         CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1653                                        
1654                 }
1655           }
1656         | opt_attributes
1657           opt_modifiers
1658           EVENT type member_name
1659           OPEN_BRACE
1660           {
1661                 implicit_value_parameter_type = (Expression) $4;  
1662                 lexer.EventParsing = true;
1663                 oob_stack.Push (lexer.Location);
1664           }
1665           event_accessor_declarations
1666           {
1667                 lexer.EventParsing = false;  
1668           }
1669           CLOSE_BRACE
1670           {
1671                 Location loc = (Location) oob_stack.Pop ();
1672
1673                 if ($8 == null){
1674                         Report.Error (65, lexer.Location, "Event must have both add and remove accesors");
1675                         $$ = null;
1676                 } else {
1677                         Pair pair = (Pair) $8;
1678                         
1679                         Event e = new EventProperty (current_container, (Expression) $4, (int) $2, false, (string) $5,
1680                                              null, (Attributes) $1, (Accessor) pair.First, (Accessor) pair.Second,
1681                                              loc);
1682                         
1683                         CheckDef (current_container.AddEvent (e), e.Name, loc);
1684                         implicit_value_parameter_type = null;
1685                 }
1686           }
1687         | opt_attributes opt_modifiers EVENT type member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS block {
1688                 string mn = (string) $5;
1689
1690                 if (mn.IndexOf ('.') != -1)
1691                         Report.Error (71, lexer.Location, "Explicit implementation of events requires property syntax");
1692                 else 
1693                         Report.Error (71, lexer.Location, "Event declaration should use property syntax");
1694           }
1695         ;
1696
1697 event_accessor_declarations
1698         : add_accessor_declaration remove_accessor_declaration
1699         {
1700                 $$ = new Pair ($1, $2);
1701         }
1702         | remove_accessor_declaration add_accessor_declaration
1703         {
1704                 $$ = new Pair ($2, $1);
1705         }       
1706         | add_accessor_declaration  { $$ = null; } 
1707         | remove_accessor_declaration { $$ = null; } 
1708         ;
1709
1710 add_accessor_declaration
1711         : opt_attributes ADD
1712           {
1713                 Parameter [] args = new Parameter [1];
1714                 Parameter implicit_value_parameter = new Parameter (
1715                         implicit_value_parameter_type, "value", 
1716                         Parameter.Modifier.NONE, null);
1717
1718                 args [0] = implicit_value_parameter;
1719                 
1720                 current_local_parameters = new Parameters (args, null, lexer.Location);  
1721                 lexer.EventParsing = false;
1722           }
1723           block
1724           {
1725                 $$ = new Accessor ((Block) $4, (Attributes) $1);
1726                 lexer.EventParsing = true;
1727           }
1728         | opt_attributes ADD error {
1729                 Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
1730                 $$ = null;
1731           }
1732         ;
1733
1734 remove_accessor_declaration
1735         : opt_attributes REMOVE
1736           {
1737                 Parameter [] args = new Parameter [1];
1738                 Parameter implicit_value_parameter = new Parameter (
1739                         implicit_value_parameter_type, "value", 
1740                         Parameter.Modifier.NONE, null);
1741
1742                 args [0] = implicit_value_parameter;
1743                 
1744                 current_local_parameters = new Parameters (args, null, lexer.Location);  
1745                 lexer.EventParsing = false;
1746           }
1747           block
1748           {
1749                 $$ = new Accessor ((Block) $4, (Attributes) $1);
1750                 lexer.EventParsing = true;
1751           }
1752         | opt_attributes REMOVE error {
1753                 Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
1754                 $$ = null;
1755           }
1756         ;
1757
1758 indexer_declaration
1759         : opt_attributes opt_modifiers indexer_declarator 
1760           OPEN_BRACE 
1761           {
1762                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1763
1764                 implicit_value_parameter_type = decl.type;
1765                 
1766                 lexer.PropertyParsing = true;
1767                 parsing_indexer  = true;
1768                 
1769                 indexer_parameters = decl.param_list;
1770                 oob_stack.Push (lexer.Location);
1771           }
1772           accessor_declarations 
1773           {
1774                   lexer.PropertyParsing = false;
1775                   parsing_indexer  = false;
1776           }
1777           CLOSE_BRACE
1778           { 
1779                 // The signature is computed from the signature of the indexer.  Look
1780                 // at section 3.6 on the spec
1781                 Location loc = (Location) oob_stack.Pop ();
1782                 Indexer indexer;
1783                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1784                 Pair pair = (Pair) $6;
1785                 Accessor get_block = (Accessor) pair.First;
1786                 Accessor set_block = (Accessor) pair.Second;
1787
1788                 indexer = new Indexer (current_container, decl.type, decl.interface_type,
1789                                        (int) $2, false, decl.param_list, (Attributes) $1,
1790                                        get_block, set_block, loc);
1791
1792                 // Note that there is no equivalent of CheckDef for this case
1793                 // We shall handle this in semantic analysis
1794                 
1795                 current_container.AddIndexer (indexer);
1796                 
1797                 current_local_parameters = null;
1798                 implicit_value_parameter_type = null;
1799                 indexer_parameters = null;
1800           }
1801         ;
1802
1803 indexer_declarator
1804         : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1805           {
1806                 Parameters pars = (Parameters) $4;
1807
1808                 if (pars.FixedParameters == null && pars.ArrayParameter == null){
1809                         Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1810                 }
1811
1812                 $$ = new IndexerDeclaration ((Expression) $1, null, pars);
1813           }
1814         | type namespace_or_type_name DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1815           {
1816                 Parameters pars = (Parameters) $6;
1817
1818                 if (pars.FixedParameters == null && pars.ArrayParameter == null){
1819                         Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1820                 }
1821                 $$ = new IndexerDeclaration ((Expression) $1, $2.ToString (), pars);
1822           }
1823         ;
1824
1825 enum_declaration
1826         : opt_attributes
1827           opt_modifiers
1828           ENUM IDENTIFIER 
1829           opt_enum_base
1830           enum_body
1831           opt_semicolon
1832           { 
1833                 Location enum_location = lexer.Location;
1834
1835                 string full_name = MakeName ((string) $4);
1836                 Enum e = new Enum (current_namespace, current_container, (Expression) $5, (int) $2,
1837                                    full_name, (Attributes) $1, enum_location);
1838                 
1839                 foreach (VariableDeclaration ev in (ArrayList) $6) {
1840                         Location loc = (Location) ev.Location;
1841
1842                         CheckDef (e.AddEnumMember (ev.identifier, 
1843                                                    (Expression) ev.expression_or_array_initializer,
1844                                                    loc, ev.OptAttributes),
1845                                   ev.identifier, loc);
1846                 }
1847
1848                 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1849                 RootContext.Tree.RecordDecl (full_name, e);
1850
1851           }
1852         ;
1853
1854 opt_enum_base
1855         : /* empty */           { $$ = TypeManager.system_int32_expr; }
1856         | COLON type            { $$ = $2;   }
1857         ;
1858
1859 enum_body
1860         : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1861           {
1862                 $$ = $2;
1863           }
1864         ;
1865
1866 opt_enum_member_declarations
1867         : /* empty */                   { $$ = new ArrayList (4); }
1868         | enum_member_declarations opt_comma { $$ = $1; }
1869         ;
1870
1871 enum_member_declarations
1872         : enum_member_declaration 
1873           {
1874                 ArrayList l = new ArrayList (4);
1875
1876                 l.Add ($1);
1877                 $$ = l;
1878           }
1879         | enum_member_declarations COMMA enum_member_declaration
1880           {
1881                 ArrayList l = (ArrayList) $1;
1882
1883                 l.Add ($3);
1884
1885                 $$ = l;
1886           }
1887         ;
1888
1889 enum_member_declaration
1890         : opt_attributes IDENTIFIER 
1891           {
1892                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1893           }
1894         | opt_attributes IDENTIFIER
1895           {
1896                   $$ = lexer.Location;
1897           }
1898           ASSIGN expression
1899           { 
1900                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1901           }
1902         ;
1903
1904 delegate_declaration
1905         : opt_attributes
1906           opt_modifiers
1907           DELEGATE type   
1908           IDENTIFIER OPEN_PARENS 
1909           opt_formal_parameter_list
1910           CLOSE_PARENS 
1911           SEMICOLON
1912           {
1913                 Location l = lexer.Location;
1914                 Delegate del = new Delegate (current_namespace, current_container, (Expression) $4,
1915                                              (int) $2, MakeName ((string) $5), (Parameters) $7, 
1916                                              (Attributes) $1, l);
1917                   
1918                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1919           }     
1920         | opt_attributes
1921           opt_modifiers
1922           DELEGATE VOID   
1923           IDENTIFIER OPEN_PARENS 
1924           opt_formal_parameter_list
1925           CLOSE_PARENS 
1926           SEMICOLON
1927           {
1928                 Location l = lexer.Location;
1929                 Delegate del = new Delegate (
1930                         current_namespace, current_container,
1931                         TypeManager.system_void_expr, (int) $2, MakeName ((string) $5), 
1932                         (Parameters) $7, (Attributes) $1, l);
1933
1934                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1935           }
1936         ;
1937
1938 type_name
1939         : namespace_or_type_name
1940         ;
1941
1942 namespace_or_type_name
1943         : IDENTIFIER { $$ = new SimpleName ((string) $1, lexer.Location);}
1944         | namespace_or_type_name DOT IDENTIFIER { 
1945                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1946           }
1947         ;
1948
1949 /* 
1950  * Before you think of adding a return_type, notice that we have been
1951  * using two rules in the places where it matters (one rule using type
1952  * and another identical one that uses VOID as the return type).  This
1953  * gets rid of a shift/reduce couple
1954  */
1955 type
1956         : type_name {   /* class_type */
1957                 /* 
1958                    This does interfaces, delegates, struct_types, class_types, 
1959                    parent classes, and more! 4.2 
1960                  */
1961           }
1962         | builtin_types
1963         | array_type
1964         | pointer_type    
1965         ;
1966
1967
1968 pointer_type
1969         : type STAR
1970           {
1971                 //
1972                 // Note that here only unmanaged types are allowed but we
1973                 // can't perform checks during this phase - we do it during
1974                 // semantic analysis.
1975                 //
1976                 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1977           }
1978         | VOID STAR
1979           {
1980                 $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);
1981           }
1982         ;
1983
1984 non_expression_type
1985         : builtin_types 
1986         | non_expression_type rank_specifier
1987           {
1988                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1989           }
1990         | non_expression_type STAR
1991           {
1992                 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1993           }
1994         | expression rank_specifiers 
1995           {
1996                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1997           }
1998         | expression STAR 
1999           {
2000                 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
2001           }
2002         
2003         //
2004         // We need this because the parser will happily go and reduce IDENTIFIER STAR
2005         // through this different path
2006         //
2007         | multiplicative_expression STAR 
2008           {
2009                 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
2010           }
2011         ;
2012
2013 type_list
2014         : type
2015           {
2016                 ArrayList types = new ArrayList (4);
2017
2018                 types.Add ($1);
2019                 $$ = types;
2020           }
2021         | type_list COMMA type
2022           {
2023                 ArrayList types = (ArrayList) $1;
2024
2025                 types.Add ($3);
2026                 $$ = types;
2027           }
2028         ;
2029
2030 /*
2031  * replaces all the productions for isolating the various
2032  * simple types, but we need this to reuse it easily in local_variable_type
2033  */
2034 builtin_types
2035         : OBJECT        { $$ = TypeManager.system_object_expr; }
2036         | STRING        { $$ = TypeManager.system_string_expr; }
2037         | BOOL          { $$ = TypeManager.system_boolean_expr; }
2038         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
2039         | FLOAT         { $$ = TypeManager.system_single_expr; }
2040         | DOUBLE        { $$ = TypeManager.system_double_expr; }
2041         | integral_type
2042         ;
2043
2044 integral_type
2045         : SBYTE         { $$ = TypeManager.system_sbyte_expr; }
2046         | BYTE          { $$ = TypeManager.system_byte_expr; }
2047         | SHORT         { $$ = TypeManager.system_int16_expr; }
2048         | USHORT        { $$ = TypeManager.system_uint16_expr; }
2049         | INT           { $$ = TypeManager.system_int32_expr; }
2050         | UINT          { $$ = TypeManager.system_uint32_expr; }
2051         | LONG          { $$ = TypeManager.system_int64_expr; }
2052         | ULONG         { $$ = TypeManager.system_uint64_expr; }
2053         | CHAR          { $$ = TypeManager.system_char_expr; }
2054         | VOID          { $$ = TypeManager.system_void_expr; }
2055         ;
2056
2057 interface_type
2058         : type_name
2059         ;
2060
2061 array_type
2062         : type rank_specifiers
2063           {
2064                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2065           }
2066         ;
2067
2068 //
2069 // Expressions, section 7.5
2070 //
2071 primary_expression
2072         : literal
2073           {
2074                 // 7.5.1: Literals
2075           }
2076  
2077         | IDENTIFIER { $$ = new SimpleName ((string) $1, lexer.Location); }
2078         | parenthesized_expression
2079         | member_access
2080         | invocation_expression
2081         | element_access
2082         | this_access
2083         | base_access
2084         | post_increment_expression
2085         | post_decrement_expression
2086         | new_expression
2087         | typeof_expression
2088         | sizeof_expression
2089         | checked_expression
2090         | unchecked_expression
2091         | pointer_member_access
2092         | anonymous_method_expression
2093         ;
2094
2095 literal
2096         : boolean_literal
2097         | integer_literal
2098         | real_literal
2099         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
2100         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
2101         | NULL                  { $$ = NullLiteral.Null; }
2102         ;
2103
2104 real_literal
2105         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
2106         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
2107         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
2108         ;
2109
2110 integer_literal
2111         : LITERAL_INTEGER       { 
2112                 object v = lexer.Value;
2113
2114                 if (v is int){
2115                         int i = (int) v;
2116
2117                         if (i == 0)
2118                                 $$ = IntLiteral.Zero;
2119                         else if (i == 1)
2120                                 $$ = IntLiteral.One;
2121                         else
2122                                 $$ = new IntLiteral (i);
2123                 } else if (v is uint)
2124                         $$ = new UIntLiteral ((UInt32) v);
2125                 else if (v is long)
2126                         $$ = new LongLiteral ((Int64) v);
2127                 else if (v is ulong)
2128                         $$ = new ULongLiteral ((UInt64) v);
2129                 else
2130                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
2131           }
2132         ;
2133
2134 boolean_literal
2135         : TRUE                  { $$ = new BoolLiteral (true); }
2136         | FALSE                 { $$ = new BoolLiteral (false); }
2137         ;
2138
2139 parenthesized_expression_0
2140         : OPEN_PARENS expression CLOSE_PARENS
2141           {
2142                 $$ = $2;
2143                 lexer.Deambiguate_CloseParens ();
2144                 // After this, the next token returned is one of
2145                 // CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST, CLOSE_PARENS_OPEN_PARENS
2146                 // or CLOSE_PARENS_MINUS.
2147           }
2148         ;
2149
2150 parenthesized_expression
2151         : parenthesized_expression_0 CLOSE_PARENS_NO_CAST
2152           {
2153                 $$ = $1;
2154           }
2155         | parenthesized_expression_0 CLOSE_PARENS_MINUS
2156           {
2157                 // If a parenthesized expression is followed by a minus, we need to wrap
2158                 // the expression inside a ParenthesizedExpression for the CS0075 check
2159                 // in Binary.DoResolve().
2160                 $$ = new ParenthesizedExpression ((Expression) $1, lexer.Location);
2161           }
2162         ;;
2163
2164 member_access
2165         : primary_expression DOT IDENTIFIER
2166           {
2167                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2168           }
2169         | predefined_type DOT IDENTIFIER
2170           {
2171                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2172           }
2173         ;
2174
2175 predefined_type
2176         : builtin_types
2177         ;
2178
2179 invocation_expression
2180         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2181           {
2182                 if ($1 == null) {
2183                         Location l = lexer.Location;
2184                         Report.Error (1, l, "Parse error");
2185                 }
2186                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2187           }
2188         | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS CLOSE_PARENS
2189           {
2190                 $$ = new Invocation ((Expression) $1, new ArrayList (), lexer.Location);
2191           }
2192         | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS primary_expression
2193           {
2194                 $$ = new InvocationOrCast ((Expression) $1, (Expression) $3, lexer.Location);
2195           }
2196         ;
2197
2198 opt_argument_list
2199         : /* empty */           { $$ = null; }
2200         | argument_list
2201         ;
2202
2203 argument_list
2204         : argument
2205           { 
2206                 ArrayList list = new ArrayList (4);
2207                 list.Add ($1);
2208                 $$ = list;
2209           }
2210         | argument_list COMMA argument
2211           {
2212                 ArrayList list = (ArrayList) $1;
2213                 list.Add ($3);
2214                 $$ = list;
2215           }
2216         | argument_list error {
2217                 CheckToken (1026, yyToken, ", or ) expected");
2218           }
2219         ;
2220
2221 argument
2222         : expression
2223           {
2224                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2225           }
2226         | REF variable_reference 
2227           { 
2228                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2229           }
2230         | OUT variable_reference 
2231           { 
2232                 $$ = new Argument ((Expression) $2, Argument.AType.Out);
2233           }
2234         | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS
2235           {
2236                 ArrayList list = (ArrayList) $3;
2237                 Argument[] args = new Argument [list.Count];
2238                 list.CopyTo (args, 0);
2239
2240                 Expression expr = new Arglist (args, lexer.Location);
2241                 $$ = new Argument (expr, Argument.AType.Expression);
2242           }
2243         | ARGLIST
2244           {
2245                 $$ = new Argument (new ArglistAccess (lexer.Location), Argument.AType.ArgList);
2246           }
2247         ;
2248
2249 variable_reference
2250         : expression { note ("section 5.4"); $$ = $1; }
2251         ;
2252
2253 element_access
2254         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
2255           {
2256                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2257           }
2258         | primary_expression rank_specifiers
2259           {
2260                 // So the super-trick is that primary_expression
2261                 // can only be either a SimpleName or a MemberAccess. 
2262                 // The MemberAccess case arises when you have a fully qualified type-name like :
2263                 // Foo.Bar.Blah i;
2264                 // SimpleName is when you have
2265                 // Blah i;
2266                   
2267                 Expression expr = (Expression) $1;  
2268                 if (expr is ComposedCast){
2269                         $$ = new ComposedCast (expr, (string) $2, lexer.Location);
2270                 } else if (!(expr is SimpleName || expr is MemberAccess)){
2271                         Error_ExpectingTypeName (lexer.Location, expr);
2272                         $$ = TypeManager.system_object_expr;
2273                 } else {
2274                         //
2275                         // So we extract the string corresponding to the SimpleName
2276                         // or MemberAccess
2277                         // 
2278                         $$ = new ComposedCast (expr, (string) $2, lexer.Location);
2279                 }
2280           }
2281         ;
2282
2283 expression_list
2284         : expression
2285           {
2286                 ArrayList list = new ArrayList (4);
2287                 list.Add ($1);
2288                 $$ = list;
2289           }
2290         | expression_list COMMA expression
2291           {
2292                 ArrayList list = (ArrayList) $1;
2293                 list.Add ($3);
2294                 $$ = list;
2295           }
2296         ;
2297
2298 this_access
2299         : THIS
2300           {
2301                 $$ = new This (current_block, lexer.Location);
2302           }
2303         ;
2304
2305 base_access
2306         : BASE DOT IDENTIFIER
2307           {
2308                 $$ = new BaseAccess ((string) $3, lexer.Location);
2309           }
2310         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
2311           {
2312                 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
2313           }
2314         | BASE error {
2315                 Report.Error (175, "Use of keyword `base' is not valid in this context");
2316                 $$ = null;
2317           }
2318         ;
2319
2320 post_increment_expression
2321         : primary_expression OP_INC
2322           {
2323                 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2324                                        (Expression) $1, lexer.Location);
2325           }
2326         ;
2327
2328 post_decrement_expression
2329         : primary_expression OP_DEC
2330           {
2331                 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
2332                                        (Expression) $1, lexer.Location);
2333           }
2334         ;
2335
2336 new_expression
2337         : object_or_delegate_creation_expression
2338         | array_creation_expression
2339         ;
2340
2341 object_or_delegate_creation_expression
2342         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2343           {
2344                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2345           }
2346         ;
2347
2348 array_creation_expression
2349         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
2350           opt_rank_specifier
2351           opt_array_initializer
2352           {
2353                 $$ = new ArrayCreation ((Expression) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
2354           }
2355         | NEW type rank_specifiers array_initializer
2356           {
2357                 $$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, lexer.Location);
2358           }
2359         | NEW type error 
2360           {
2361                 Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
2362           }
2363         ;
2364
2365 opt_rank_specifier
2366         : /* empty */
2367           {
2368                   $$ = "";
2369           }
2370         | rank_specifiers
2371           {
2372                         $$ = $1;
2373           }
2374         ;
2375
2376 rank_specifiers
2377         : rank_specifier opt_rank_specifier
2378           {
2379                   $$ = (string) $2 + (string) $1;
2380           }
2381         ;
2382
2383 rank_specifier
2384         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2385           {
2386                 $$ = "[" + (string) $2 + "]";
2387           }
2388         ;
2389
2390 opt_dim_separators
2391         : /* empty */
2392           {
2393                 $$ = "";
2394           }
2395         | dim_separators
2396           {
2397                   $$ = $1;
2398           }               
2399         ;
2400
2401 dim_separators
2402         : COMMA
2403           {
2404                 $$ = ",";
2405           }
2406         | dim_separators COMMA
2407           {
2408                 $$ = (string) $1 + ",";
2409           }
2410         ;
2411
2412 opt_array_initializer
2413         : /* empty */
2414           {
2415                 $$ = null;
2416           }
2417         | array_initializer
2418           {
2419                 $$ = $1;
2420           }
2421         ;
2422
2423 array_initializer
2424         : OPEN_BRACE CLOSE_BRACE
2425           {
2426                 ArrayList list = new ArrayList (4);
2427                 $$ = list;
2428           }
2429         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
2430           {
2431                 $$ = (ArrayList) $2;
2432           }
2433         ;
2434
2435 variable_initializer_list
2436         : variable_initializer
2437           {
2438                 ArrayList list = new ArrayList (4);
2439                 list.Add ($1);
2440                 $$ = list;
2441           }
2442         | variable_initializer_list COMMA variable_initializer
2443           {
2444                 ArrayList list = (ArrayList) $1;
2445                 list.Add ($3);
2446                 $$ = list;
2447           }
2448         ;
2449
2450 typeof_expression
2451         : TYPEOF OPEN_PARENS VOID CLOSE_PARENS
2452           {
2453                 $$ = new TypeOfVoid (lexer.Location);
2454           }
2455         | TYPEOF OPEN_PARENS type CLOSE_PARENS
2456           {
2457                 $$ = new TypeOf ((Expression) $3, lexer.Location);
2458           }
2459         ;
2460
2461 sizeof_expression
2462         : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
2463                 $$ = new SizeOf ((Expression) $3, lexer.Location);
2464           }
2465         ;
2466
2467 checked_expression
2468         : CHECKED OPEN_PARENS expression CLOSE_PARENS
2469           {
2470                 $$ = new CheckedExpr ((Expression) $3, lexer.Location);
2471           }
2472         ;
2473
2474 unchecked_expression
2475         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2476           {
2477                 $$ = new UnCheckedExpr ((Expression) $3, lexer.Location);
2478           }
2479         ;
2480
2481 pointer_member_access 
2482         : primary_expression OP_PTR IDENTIFIER
2483           {
2484                 Expression deref;
2485
2486                 deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lexer.Location);
2487                 $$ = new MemberAccess (deref, (string) $3, lexer.Location);
2488           }
2489         ;
2490
2491 anonymous_method_expression
2492         : DELEGATE opt_anonymous_method_signature {
2493                 oob_stack.Push (current_local_parameters);
2494                 current_local_parameters = (Parameters)$2;
2495                 create_toplevel_block = true;
2496           } block {
2497                 if (true){
2498                         Report.Error (-213, lexer.Location, "Anonymous methods are not supported in this branch");
2499                         $$ = null;
2500                 } else {
2501                         create_toplevel_block = false;
2502                         if (!RootContext.V2){
2503                                 Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
2504                                 $$ = null;
2505                         } else 
2506                                 $$ = new AnonymousMethod ((Parameters) $2, (Block) $4, lexer.Location);
2507                         current_local_parameters = (Parameters) oob_stack.Pop ();
2508                 }
2509           }
2510         ;
2511
2512 opt_anonymous_method_signature
2513         : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
2514         | anonymous_method_signature
2515         ;
2516
2517 anonymous_method_signature
2518         : OPEN_PARENS opt_anonymous_method_parameter_list CLOSE_PARENS 
2519           {
2520                 if ($2 == null)
2521                         $$ = Parameters.EmptyReadOnlyParameters;
2522                 else {
2523                         ArrayList par_list = (ArrayList) $2;
2524                         Parameter [] pars = new Parameter [par_list.Count];
2525                         par_list.CopyTo (pars);
2526                         $$ = new Parameters (pars, null, lexer.Location);
2527                 }
2528           }
2529         ;
2530
2531 opt_anonymous_method_parameter_list
2532         : /* empty */   { $$ = null; } 
2533         | anonymous_method_parameter_list  { $$ = $1; }
2534         ;
2535
2536 anonymous_method_parameter_list
2537         : anonymous_method_parameter 
2538           {
2539                 ArrayList a = new ArrayList (4);
2540                 a.Add ($1);
2541                 $$ = a;
2542           }
2543         | anonymous_method_parameter_list COMMA anonymous_method_parameter 
2544           {
2545                 ArrayList a = (ArrayList) $1;
2546                 a.Add ($3);
2547                 $$ = a;
2548           }
2549         ; 
2550
2551 anonymous_method_parameter
2552         : opt_parameter_modifier type IDENTIFIER {
2553                 $$ = new Parameter ((Expression) $2, (string) $2, (Parameter.Modifier) $1, null);
2554           }
2555         ;
2556
2557 unary_expression
2558         : primary_expression
2559         | BANG prefixed_unary_expression
2560           {
2561                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2562           }
2563         | TILDE prefixed_unary_expression
2564           {
2565                 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2566           }
2567         | cast_expression
2568         ;
2569
2570 cast_list
2571         : parenthesized_expression_0 CLOSE_PARENS_CAST unary_expression
2572           {
2573                 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2574           }
2575         | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
2576           {
2577                 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2578           }     
2579         ;
2580
2581 cast_expression
2582         : cast_list
2583         | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2584           {
2585                 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2586           }
2587         ;
2588
2589         //
2590         // The idea to split this out is from Rhys' grammar
2591         // to solve the problem with casts.
2592         //
2593 prefixed_unary_expression
2594         : unary_expression
2595         | PLUS prefixed_unary_expression
2596           { 
2597                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2598           } 
2599         | MINUS prefixed_unary_expression 
2600           { 
2601                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2602           }
2603         | OP_INC prefixed_unary_expression 
2604           {
2605                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2606                                        (Expression) $2, lexer.Location);
2607           }
2608         | OP_DEC prefixed_unary_expression 
2609           {
2610                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2611                                        (Expression) $2, lexer.Location);
2612           }
2613         | STAR prefixed_unary_expression
2614           {
2615                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2616           }
2617         | BITWISE_AND prefixed_unary_expression
2618           {
2619                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2620           }
2621         ;
2622
2623 pre_increment_expression
2624         : OP_INC prefixed_unary_expression 
2625           {
2626                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2627                                        (Expression) $2, lexer.Location);
2628           }
2629         ;
2630
2631 pre_decrement_expression
2632         : OP_DEC prefixed_unary_expression 
2633           {
2634                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2635                                        (Expression) $2, lexer.Location);
2636           }
2637         ;
2638
2639 multiplicative_expression
2640         : prefixed_unary_expression
2641         | multiplicative_expression STAR prefixed_unary_expression
2642           {
2643                 $$ = new Binary (Binary.Operator.Multiply, 
2644                                  (Expression) $1, (Expression) $3, lexer.Location);
2645           }
2646         | multiplicative_expression DIV prefixed_unary_expression
2647           {
2648                 $$ = new Binary (Binary.Operator.Division, 
2649                                  (Expression) $1, (Expression) $3, lexer.Location);
2650           }
2651         | multiplicative_expression PERCENT prefixed_unary_expression 
2652           {
2653                 $$ = new Binary (Binary.Operator.Modulus, 
2654                                  (Expression) $1, (Expression) $3, lexer.Location);
2655           }
2656         ;
2657
2658 additive_expression
2659         : multiplicative_expression
2660         | additive_expression PLUS multiplicative_expression 
2661           {
2662                 $$ = new Binary (Binary.Operator.Addition, 
2663                                  (Expression) $1, (Expression) $3, lexer.Location);
2664           }
2665         | additive_expression MINUS multiplicative_expression
2666           {
2667                 $$ = new Binary (Binary.Operator.Subtraction, 
2668                                  (Expression) $1, (Expression) $3, lexer.Location);
2669           }
2670         ;
2671
2672 shift_expression
2673         : additive_expression
2674         | shift_expression OP_SHIFT_LEFT additive_expression
2675           {
2676                 $$ = new Binary (Binary.Operator.LeftShift, 
2677                                  (Expression) $1, (Expression) $3, lexer.Location);
2678           }
2679         | shift_expression OP_SHIFT_RIGHT additive_expression
2680           {
2681                 $$ = new Binary (Binary.Operator.RightShift, 
2682                                  (Expression) $1, (Expression) $3, lexer.Location);
2683           }
2684         ; 
2685
2686 relational_expression
2687         : shift_expression
2688         | relational_expression OP_LT shift_expression
2689           {
2690                 $$ = new Binary (Binary.Operator.LessThan, 
2691                                  (Expression) $1, (Expression) $3, lexer.Location);
2692           }
2693         | relational_expression OP_GT shift_expression
2694           {
2695                 $$ = new Binary (Binary.Operator.GreaterThan, 
2696                                  (Expression) $1, (Expression) $3, lexer.Location);
2697           }
2698         | relational_expression OP_LE shift_expression
2699           {
2700                 $$ = new Binary (Binary.Operator.LessThanOrEqual, 
2701                                  (Expression) $1, (Expression) $3, lexer.Location);
2702           }
2703         | relational_expression OP_GE shift_expression
2704           {
2705                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
2706                                  (Expression) $1, (Expression) $3, lexer.Location);
2707           }
2708         | relational_expression IS type
2709           {
2710                 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2711           }
2712         | relational_expression AS type
2713           {
2714                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2715           }
2716         ;
2717
2718 equality_expression
2719         : relational_expression
2720         | equality_expression OP_EQ relational_expression
2721           {
2722                 $$ = new Binary (Binary.Operator.Equality, 
2723                                  (Expression) $1, (Expression) $3, lexer.Location);
2724           }
2725         | equality_expression OP_NE relational_expression
2726           {
2727                 $$ = new Binary (Binary.Operator.Inequality, 
2728                                  (Expression) $1, (Expression) $3, lexer.Location);
2729           }
2730         ; 
2731
2732 and_expression
2733         : equality_expression
2734         | and_expression BITWISE_AND equality_expression
2735           {
2736                 $$ = new Binary (Binary.Operator.BitwiseAnd, 
2737                                  (Expression) $1, (Expression) $3, lexer.Location);
2738           }
2739         ;
2740
2741 exclusive_or_expression
2742         : and_expression
2743         | exclusive_or_expression CARRET and_expression
2744           {
2745                 $$ = new Binary (Binary.Operator.ExclusiveOr, 
2746                                  (Expression) $1, (Expression) $3, lexer.Location);
2747           }
2748         ;
2749
2750 inclusive_or_expression
2751         : exclusive_or_expression
2752         | inclusive_or_expression BITWISE_OR exclusive_or_expression
2753           {
2754                 $$ = new Binary (Binary.Operator.BitwiseOr, 
2755                                  (Expression) $1, (Expression) $3, lexer.Location);
2756           }
2757         ;
2758
2759 conditional_and_expression
2760         : inclusive_or_expression
2761         | conditional_and_expression OP_AND inclusive_or_expression
2762           {
2763                 $$ = new Binary (Binary.Operator.LogicalAnd, 
2764                                  (Expression) $1, (Expression) $3, lexer.Location);
2765           }
2766         ;
2767
2768 conditional_or_expression
2769         : conditional_and_expression
2770         | conditional_or_expression OP_OR conditional_and_expression
2771           {
2772                 $$ = new Binary (Binary.Operator.LogicalOr, 
2773                                  (Expression) $1, (Expression) $3, lexer.Location);
2774           }
2775         ;
2776
2777 conditional_expression
2778         : conditional_or_expression
2779         | conditional_or_expression INTERR expression COLON expression 
2780           {
2781                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2782           }
2783         ;
2784
2785 assignment_expression
2786         : prefixed_unary_expression ASSIGN expression
2787           {
2788                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2789           }
2790         | prefixed_unary_expression OP_MULT_ASSIGN expression
2791           {
2792                 Location l = lexer.Location;
2793
2794                 $$ = new CompoundAssign (
2795                         Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
2796           }
2797         | prefixed_unary_expression OP_DIV_ASSIGN expression
2798           {
2799                 Location l = lexer.Location;
2800
2801                 $$ = new CompoundAssign (
2802                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
2803           }
2804         | prefixed_unary_expression OP_MOD_ASSIGN expression
2805           {
2806                 Location l = lexer.Location;
2807
2808                 $$ = new CompoundAssign (
2809                         Binary.Operator.Modulus, (Expression) $1, (Expression) $3, l);
2810           }
2811         | prefixed_unary_expression OP_ADD_ASSIGN expression
2812           {
2813                 Location l = lexer.Location;
2814
2815                 $$ = new CompoundAssign (
2816                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
2817           }
2818         | prefixed_unary_expression OP_SUB_ASSIGN expression
2819           {
2820                 Location l = lexer.Location;
2821
2822                 $$ = new CompoundAssign (
2823                         Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
2824           }
2825         | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2826           {
2827                 Location l = lexer.Location;
2828
2829                 $$ = new CompoundAssign (
2830                         Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, l);
2831           }
2832         | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2833           {
2834                 Location l = lexer.Location;
2835
2836                 $$ = new CompoundAssign (
2837                         Binary.Operator.RightShift, (Expression) $1, (Expression) $3, l);
2838           }
2839         | prefixed_unary_expression OP_AND_ASSIGN expression
2840           {
2841                 Location l = lexer.Location;
2842
2843                 $$ = new CompoundAssign (
2844                         Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3, l);
2845           }
2846         | prefixed_unary_expression OP_OR_ASSIGN expression
2847           {
2848                 Location l = lexer.Location;
2849
2850                 $$ = new CompoundAssign (
2851                         Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3, l);
2852           }
2853         | prefixed_unary_expression OP_XOR_ASSIGN expression
2854           {
2855                 Location l = lexer.Location;
2856
2857                 $$ = new CompoundAssign (
2858                         Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, l);
2859           }
2860         ;
2861
2862 expression
2863         : conditional_expression
2864         | assignment_expression
2865         ;
2866
2867 constant_expression
2868         : expression
2869         ;
2870
2871 boolean_expression
2872         : expression
2873         ;
2874
2875 //
2876 // 10 classes
2877 //
2878 class_declaration
2879         : opt_attributes
2880           opt_modifiers
2881           CLASS IDENTIFIER
2882           {
2883                 Class new_class;
2884                 string name;
2885
2886                 name = MakeName ((string) $4);
2887
2888                 new_class = new Class (current_namespace, current_container, name, (int) $2, 
2889                                        (Attributes) $1, lexer.Location);
2890                 current_container = new_class;
2891                 RootContext.Tree.RecordDecl (name, new_class);
2892           }
2893           opt_class_base
2894           class_body 
2895           opt_semicolon 
2896           {
2897                 Class new_class = (Class) current_container;
2898
2899                 if ($6 != null) {
2900                         if (new_class.Name == "System.Object") {
2901                                 Report.Error (537, new_class.Location, "The class System.Object cannot have a base class or implement an interface.");
2902                         }
2903                         new_class.Bases = (ArrayList) $6;
2904                 }
2905
2906                 current_container = current_container.Parent;
2907                 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
2908
2909                 $$ = new_class;
2910           }
2911         ;       
2912
2913 opt_modifiers
2914         : /* empty */           { $$ = (int) 0; }
2915         | modifiers
2916         ;
2917
2918 modifiers
2919         : modifier
2920         | modifiers modifier
2921           { 
2922                 int m1 = (int) $1;
2923                 int m2 = (int) $2;
2924
2925                 if ((m1 & m2) != 0) {
2926                         Location l = lexer.Location;
2927                         Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2928                 }
2929                 $$ = (int) (m1 | m2);
2930           }
2931         ;
2932
2933 modifier
2934         : NEW                   { $$ = Modifiers.NEW; }
2935         | PUBLIC                { $$ = Modifiers.PUBLIC; }
2936         | PROTECTED             { $$ = Modifiers.PROTECTED; }
2937         | INTERNAL              { $$ = Modifiers.INTERNAL; }
2938         | PRIVATE               { $$ = Modifiers.PRIVATE; }
2939         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
2940         | SEALED                { $$ = Modifiers.SEALED; }
2941         | STATIC                { $$ = Modifiers.STATIC; }
2942         | READONLY              { $$ = Modifiers.READONLY; }
2943         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
2944         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
2945         | EXTERN                { $$ = Modifiers.EXTERN; }
2946         | VOLATILE              { $$ = Modifiers.VOLATILE; }
2947         | UNSAFE                { $$ = Modifiers.UNSAFE; }
2948         ;
2949
2950 opt_class_base
2951         : /* empty */           { $$ = null; }
2952         | class_base            { $$ = $1;   }
2953         ;
2954
2955 class_base
2956         : COLON type_list { $$ = $2; }
2957         ;
2958
2959 //
2960 // Statements (8.2)
2961 //
2962
2963 //
2964 // A block is "contained" on the following places:
2965 //      method_body
2966 //      property_declaration as part of the accessor body (get/set)
2967 //      operator_declaration
2968 //      constructor_declaration
2969 //      destructor_declaration
2970 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2971 //      
2972 block
2973         : OPEN_BRACE 
2974           {
2975                 if (current_block == null || create_toplevel_block){
2976                         current_block = new ToplevelBlock (current_local_parameters, lexer.Location);
2977                 } else {
2978                         current_block = new Block (current_block, current_local_parameters,
2979                                 lexer.Location, Location.Null);
2980                 }
2981           } 
2982           opt_statement_list CLOSE_BRACE 
2983           { 
2984                 while (current_block.Implicit)
2985                         current_block = current_block.Parent;
2986                 $$ = current_block;
2987                 current_block.SetEndLocation (lexer.Location);
2988                 current_block = current_block.Parent;
2989           }
2990         ;
2991
2992 opt_statement_list
2993         : /* empty */
2994         | statement_list 
2995         ;
2996
2997 statement_list
2998         : statement
2999         | statement_list statement
3000         ;
3001
3002 statement
3003         : declaration_statement
3004           {
3005                 if ($1 != null && (Block) $1 != current_block){
3006                         current_block.AddStatement ((Statement) $1);
3007                         current_block = (Block) $1;
3008                 }
3009           }
3010         | valid_declaration_statement
3011           {
3012                 current_block.AddStatement ((Statement) $1);
3013           }
3014         | labeled_statement
3015         ;
3016
3017 valid_declaration_statement
3018         : block
3019         | empty_statement
3020         | expression_statement
3021         | selection_statement
3022         | iteration_statement
3023         | jump_statement                  
3024         | try_statement
3025         | checked_statement
3026         | unchecked_statement
3027         | lock_statement
3028         | using_statement
3029         | unsafe_statement
3030         | fixed_statement
3031         ;
3032
3033 embedded_statement
3034         : valid_declaration_statement
3035         | declaration_statement
3036           {
3037                   Report.Error (1023, lexer.Location, "An embedded statement may not be a declaration.");
3038                   $$ = null;
3039           }
3040         | labeled_statement
3041           {
3042                   Report.Error (1023, lexer.Location, "An embedded statement may not be a labeled statement.");
3043                   $$ = null;
3044           }
3045         ;
3046
3047 empty_statement
3048         : SEMICOLON
3049           {
3050                   $$ = EmptyStatement.Value;
3051           }
3052         ;
3053
3054 labeled_statement
3055         : IDENTIFIER COLON 
3056           {
3057                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
3058
3059                 if (current_block.AddLabel ((string) $1, labeled, lexer.Location))
3060                         current_block.AddStatement (labeled);
3061           }
3062           statement
3063         ;
3064
3065 declaration_statement
3066         : local_variable_declaration SEMICOLON
3067           {
3068                 if ($1 != null){
3069                         DictionaryEntry de = (DictionaryEntry) $1;
3070
3071                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
3072                 }
3073           }
3074
3075         | local_constant_declaration SEMICOLON
3076           {
3077                 if ($1 != null){
3078                         DictionaryEntry de = (DictionaryEntry) $1;
3079
3080                         $$ = declare_local_constants ((Expression) de.Key, (ArrayList) de.Value);
3081                 }
3082           }
3083         ;
3084
3085 /* 
3086  * The following is from Rhys' grammar:
3087  * > Types in local variable declarations must be recognized as 
3088  * > expressions to prevent reduce/reduce errors in the grammar.
3089  * > The expressions are converted into types during semantic analysis.
3090  */
3091 local_variable_type
3092         : primary_expression opt_rank_specifier
3093           { 
3094                 // FIXME: Do something smart here regarding the composition of the type.
3095
3096                 // Ok, the above "primary_expression" is there to get rid of
3097                 // both reduce/reduce and shift/reduces in the grammar, it should
3098                 // really just be "type_name".  If you use type_name, a reduce/reduce
3099                 // creeps up.  If you use namespace_or_type_name (which is all we need
3100                 // really) two shift/reduces appear.
3101                 // 
3102
3103                 // So the super-trick is that primary_expression
3104                 // can only be either a SimpleName or a MemberAccess. 
3105                 // The MemberAccess case arises when you have a fully qualified type-name like :
3106                 // Foo.Bar.Blah i;
3107                 // SimpleName is when you have
3108                 // Blah i;
3109                   
3110                 Expression expr = (Expression) $1;  
3111                 if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
3112                         Error_ExpectingTypeName (lexer.Location, expr);
3113                         $$ = null;
3114                 } else {
3115                         //
3116                         // So we extract the string corresponding to the SimpleName
3117                         // or MemberAccess
3118                         // 
3119
3120                         if ((string) $2 == "")
3121                                 $$ = $1;
3122                         else
3123                                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3124                 }
3125           }
3126         | builtin_types opt_rank_specifier
3127           {
3128                 if ((string) $2 == "")
3129                         $$ = $1;
3130                 else
3131                         $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3132           }
3133         ;
3134
3135 local_variable_pointer_type
3136         : primary_expression STAR
3137           {
3138                 Expression expr = (Expression) $1;  
3139                 Location l = lexer.Location;
3140
3141                 if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
3142                         Error_ExpectingTypeName (l, expr);
3143
3144                         $$ = null;
3145                 } else 
3146                         $$ = new ComposedCast ((Expression) $1, "*", l);
3147           }
3148         | builtin_types STAR
3149           {
3150                 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);;
3151           }
3152         | VOID STAR
3153           {
3154                 $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);;
3155           }
3156         | local_variable_pointer_type STAR
3157           {
3158                 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
3159           }
3160         ;
3161
3162 local_variable_declaration
3163         : local_variable_type variable_declarators
3164           {
3165                 if ($1 != null)
3166                         $$ = new DictionaryEntry ($1, $2);
3167                 else
3168                         $$ = null;
3169           }
3170         | local_variable_pointer_type opt_rank_specifier variable_declarators
3171         {
3172                 if ($1 != null){
3173                         Expression t;
3174
3175                         if ((string) $2 == "")
3176                                 t = (Expression) $1;
3177                         else
3178                                 t = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3179                         $$ = new DictionaryEntry (t, $3);
3180                 } else 
3181                         $$ = null;
3182         }
3183         ;
3184
3185 local_constant_declaration
3186         : CONST local_variable_type constant_declarators
3187           {
3188                 if ($2 != null)
3189                         $$ = new DictionaryEntry ($2, $3);
3190                 else
3191                         $$ = null;
3192           }
3193         ;
3194
3195 expression_statement
3196         : statement_expression SEMICOLON
3197           {
3198                 $$ = $1;
3199           }
3200         ;
3201
3202         //
3203         // We have to do the wrapping here and not in the case above,
3204         // because statement_expression is used for example in for_statement
3205         //
3206 statement_expression
3207         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3208         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3209         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3210         | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3211         | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3212         | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3213         | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3214         | error {
3215                 Report.Error (1002, lexer.Location, "Expecting `;'");
3216                 $$ = null;
3217           }
3218         ;
3219
3220 object_creation_expression
3221         : object_or_delegate_creation_expression
3222           { note ("complain if this is a delegate maybe?"); } 
3223         ;
3224
3225 selection_statement
3226         : if_statement
3227         | switch_statement
3228         ; 
3229
3230 if_statement
3231         : if_statement_open if_statement_rest
3232           {
3233                 $$ = $2;
3234           }
3235         ;
3236
3237 if_statement_open
3238         : IF OPEN_PARENS 
3239           {
3240                 oob_stack.Push (lexer.Location);
3241           }
3242         ;
3243
3244 if_statement_rest
3245         : boolean_expression CLOSE_PARENS 
3246           embedded_statement
3247           { 
3248                 Location l = (Location) oob_stack.Pop ();
3249
3250                 $$ = new If ((Expression) $1, (Statement) $3, l);
3251
3252                 if (RootContext.WarningLevel >= 3){
3253                         if ($3 == EmptyStatement.Value)
3254                                 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3255                 }
3256
3257           }
3258         | boolean_expression CLOSE_PARENS
3259           embedded_statement ELSE embedded_statement
3260           {
3261                 Location l = (Location) oob_stack.Pop ();
3262
3263                 $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
3264           }
3265         ;
3266
3267 switch_statement
3268         : SWITCH OPEN_PARENS 
3269           { 
3270                 oob_stack.Push (lexer.Location);
3271                 switch_stack.Push (current_block);
3272           }
3273           expression CLOSE_PARENS 
3274           switch_block
3275           {
3276                 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
3277                 current_block = (Block) switch_stack.Pop ();
3278           }
3279         ;
3280
3281 switch_block
3282         : OPEN_BRACE
3283           opt_switch_sections
3284           CLOSE_BRACE
3285           {
3286                 $$ = $2;
3287           }
3288         ;
3289
3290 opt_switch_sections
3291         : /* empty */           
3292           {
3293                 Report.Error (1522, lexer.Location, "Empty switch block"); 
3294           }
3295         | switch_sections
3296         ;
3297
3298 switch_sections
3299         : switch_section 
3300           {
3301                 ArrayList sections = new ArrayList (4);
3302
3303                 sections.Add ($1);
3304                 $$ = sections;
3305           }
3306         | switch_sections switch_section
3307           {
3308                 ArrayList sections = (ArrayList) $1;
3309
3310                 sections.Add ($2);
3311                 $$ = sections;
3312           }
3313         ;
3314
3315 switch_section
3316         : switch_labels
3317           {
3318                 current_block = current_block.CreateSwitchBlock (lexer.Location);
3319           }
3320           statement_list 
3321           {
3322                 Block topmost = current_block;
3323
3324                 while (topmost.Implicit)
3325                         topmost = topmost.Parent;
3326                 $$ = new SwitchSection ((ArrayList) $1, topmost);
3327           }
3328         ;
3329
3330 switch_labels
3331         : switch_label 
3332           {
3333                 ArrayList labels = new ArrayList (4);
3334
3335                 labels.Add ($1);
3336                 $$ = labels;
3337           }
3338         | switch_labels switch_label 
3339           {
3340                 ArrayList labels = (ArrayList) ($1);
3341                 labels.Add ($2);
3342
3343                 $$ = labels;
3344           }
3345         ;
3346
3347 switch_label
3348         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
3349         | DEFAULT COLON                         { $$ = new SwitchLabel (null, lexer.Location); }
3350         | error {
3351                 Report.Error (
3352                         1523, lexer.Location, 
3353                         "The keyword case or default must precede code in switch block");
3354           }
3355         ;
3356
3357 iteration_statement
3358         : while_statement
3359         | do_statement
3360         | for_statement
3361         | foreach_statement
3362         ;
3363
3364 while_statement
3365         : WHILE OPEN_PARENS 
3366         {
3367                 oob_stack.Push (lexer.Location);
3368         }
3369         boolean_expression CLOSE_PARENS embedded_statement
3370         {
3371                 Location l = (Location) oob_stack.Pop ();
3372                 $$ = new While ((Expression) $4, (Statement) $6, l);
3373         
3374                 if (RootContext.WarningLevel >= 3){
3375                         if ($6 == EmptyStatement.Value)
3376                                 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3377                 }
3378         }
3379         ;
3380
3381 do_statement
3382         : DO embedded_statement 
3383           WHILE OPEN_PARENS {
3384                 oob_stack.Push (lexer.Location);
3385           }
3386           boolean_expression CLOSE_PARENS SEMICOLON
3387           {
3388                 Location l = (Location) oob_stack.Pop ();
3389
3390                 $$ = new Do ((Statement) $2, (Expression) $6, l);
3391           }
3392         ;
3393
3394 for_statement
3395         : FOR OPEN_PARENS 
3396           opt_for_initializer SEMICOLON
3397           {
3398                 Block assign_block = new Block (current_block);
3399                 current_block = assign_block;
3400
3401                 if ($3 is DictionaryEntry){
3402                         DictionaryEntry de = (DictionaryEntry) $3;
3403                         
3404                         Expression type = (Expression) de.Key;
3405                         ArrayList var_declarators = (ArrayList) de.Value;
3406
3407                         foreach (VariableDeclaration decl in var_declarators){
3408
3409                                 LocalInfo vi;
3410
3411                                 vi = current_block.AddVariable (
3412                                         type, decl.identifier, current_local_parameters, decl.Location);
3413                                 if (vi == null)
3414                                         continue;
3415
3416                                 Location l = lexer.Location;
3417                                 Expression expr;
3418                                 if (decl.expression_or_array_initializer is Expression){
3419                                         expr = (Expression) decl.expression_or_array_initializer;
3420                                 } else if (decl.expression_or_array_initializer == null) {
3421                                         expr = null;
3422                                 } else {
3423                                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3424                                         expr = new ArrayCreation (type, "", init, decl.Location);
3425                                 }
3426                                         
3427                                 LocalVariableReference var;
3428                                 var = new LocalVariableReference (assign_block, decl.identifier, l);
3429
3430                                 if (expr != null) {
3431                                         Assign a = new Assign (var, expr, decl.Location);
3432                                         
3433                                         assign_block.AddStatement (new StatementExpression (a, lexer.Location));
3434                                 }
3435                         }
3436                         
3437                         $3 = null;
3438                 } 
3439                 oob_stack.Push (lexer.Location);
3440           } 
3441           opt_for_condition SEMICOLON
3442           opt_for_iterator CLOSE_PARENS 
3443           embedded_statement
3444           {
3445                 Location l = (Location) oob_stack.Pop ();
3446
3447                 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
3448
3449                 if (RootContext.WarningLevel >= 3){
3450                         if ($10 == EmptyStatement.Value)
3451                                 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3452                 }
3453
3454                 current_block.AddStatement (f);
3455                 while (current_block.Implicit)
3456                         current_block = current_block.Parent;
3457                 $$ = current_block;
3458                 current_block = current_block.Parent;
3459           }
3460         ;
3461
3462 opt_for_initializer
3463         : /* empty */           { $$ = EmptyStatement.Value; }
3464         | for_initializer       
3465         ;
3466
3467 for_initializer
3468         : local_variable_declaration
3469         | statement_expression_list
3470         ;
3471
3472 opt_for_condition
3473         : /* empty */           { $$ = null; }
3474         | boolean_expression
3475         ;
3476
3477 opt_for_iterator
3478         : /* empty */           { $$ = EmptyStatement.Value; }
3479         | for_iterator
3480         ;
3481
3482 for_iterator
3483         : statement_expression_list
3484         ;
3485
3486 statement_expression_list
3487         : statement_expression  
3488           {
3489                 // CHANGE: was `null'
3490                 Block b = new Block (current_block, Block.Flags.Implicit);   
3491
3492                 b.AddStatement ((Statement) $1);
3493                 $$ = b;
3494           }
3495         | statement_expression_list COMMA statement_expression
3496           {
3497                 Block b = (Block) $1;
3498
3499                 b.AddStatement ((Statement) $3);
3500                 $$ = $1;
3501           }
3502         ;
3503
3504 foreach_statement
3505         : FOREACH OPEN_PARENS type IDENTIFIER IN 
3506           {
3507                 oob_stack.Push (lexer.Location);
3508           }
3509           expression CLOSE_PARENS 
3510           {
3511                 oob_stack.Push (current_block);
3512
3513                 Block foreach_block = new Block (current_block);
3514                 LocalVariableReference v = null;
3515                 Location l = lexer.Location;
3516                 LocalInfo vi;
3517
3518                 vi = foreach_block.AddVariable ((Expression) $3, (string) $4, current_local_parameters, l);
3519                 if (vi != null) {
3520                         vi.ReadOnly = true;
3521
3522                         // Get a writable reference to this read-only variable.
3523                         v = new LocalVariableReference (foreach_block, (string) $4, l, vi, false);
3524                 }
3525                 current_block = foreach_block;
3526
3527                 oob_stack.Push (v);
3528                 oob_stack.Push (current_block);
3529           } 
3530           embedded_statement 
3531           {
3532                 Block foreach_block = (Block) oob_stack.Pop ();
3533                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
3534                 Block prev_block = (Block) oob_stack.Pop ();
3535                 Location l = (Location) oob_stack.Pop ();
3536
3537                 current_block = prev_block;
3538
3539                 if (v != null) {
3540                         Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l);
3541                         foreach_block.AddStatement (f);
3542                 }
3543
3544                 $$ = foreach_block;
3545           }
3546         ;
3547
3548 jump_statement
3549         : break_statement
3550         | continue_statement
3551         | goto_statement
3552         | return_statement
3553         | throw_statement
3554         | yield_statement
3555         ;
3556
3557 break_statement
3558         : BREAK SEMICOLON
3559           {
3560                 $$ = new Break (lexer.Location);
3561           }
3562         ;
3563
3564 continue_statement
3565         : CONTINUE SEMICOLON
3566           {
3567                 $$ = new Continue (lexer.Location);
3568           }
3569         ;
3570
3571 goto_statement
3572         : GOTO IDENTIFIER SEMICOLON 
3573           {
3574                 $$ = new Goto (current_block, (string) $2, lexer.Location);
3575           }
3576         | GOTO CASE constant_expression SEMICOLON
3577           {
3578                 $$ = new GotoCase ((Expression) $3, lexer.Location);
3579           }
3580         | GOTO DEFAULT SEMICOLON 
3581           {
3582                 $$ = new GotoDefault (lexer.Location);
3583           }
3584         ; 
3585
3586 return_statement
3587         : RETURN opt_expression SEMICOLON
3588           {
3589                 $$ = new Return ((Expression) $2, lexer.Location);
3590           }
3591         ;
3592
3593 throw_statement
3594         : THROW opt_expression SEMICOLON
3595           {
3596                 $$ = new Throw ((Expression) $2, lexer.Location);
3597           }
3598         ;
3599
3600 yield_statement 
3601         : IDENTIFIER RETURN expression SEMICOLON
3602           {
3603                 string s = (string) $1;
3604                 if (s != "yield"){
3605                         Report.Error (1003, lexer.Location, "; expected");
3606                         $$ = null;
3607                 }
3608                 if (!RootContext.V2){
3609                         Report.Error (-222, lexer.Location, "yield statement only available in C# 2.0 mode");
3610                         $$ = null;
3611                 }
3612                 if (iterator_container == null){
3613                         Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
3614                         $$ = null;
3615                 } else {
3616                         iterator_container.SetYields ();
3617                         $$ = new Yield ((Expression) $3, lexer.Location); 
3618                 }
3619           }
3620         | IDENTIFIER BREAK SEMICOLON
3621           {
3622                 string s = (string) $1;
3623                 if (s != "yield"){
3624                         Report.Error (1003, lexer.Location, "; expected");
3625                         $$ = null;
3626                 }
3627                 if (!RootContext.V2){
3628                         Report.Error (-222, lexer.Location, "yield statement only available in C# 2.0 mode");
3629                         $$ = null;
3630                 }
3631                 if (iterator_container == null){
3632                         Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
3633                         $$ = null;
3634                 } else {
3635                         iterator_container.SetYields ();
3636                         $$ = new YieldBreak (lexer.Location);
3637                 }
3638           }
3639         ;
3640
3641 opt_expression
3642         : /* empty */
3643         | expression
3644         ;
3645
3646 try_statement
3647         : TRY block catch_clauses 
3648         {
3649                 Catch g = null;
3650                 ArrayList s = new ArrayList (4);
3651                 
3652                 foreach (Catch cc in (ArrayList) $3) {
3653                         if (cc.IsGeneral)
3654                                 g = cc;
3655                         else
3656                                 s.Add (cc);
3657                 }
3658
3659                 // Now s contains the list of specific catch clauses
3660                 // and g contains the general one.
3661                 
3662                 $$ = new Try ((Block) $2, s, g, null, lexer.Location);
3663         }
3664         | TRY block opt_catch_clauses FINALLY block
3665           {
3666                 Catch g = null;
3667                 ArrayList s = new ArrayList (4);
3668                 ArrayList catch_list = (ArrayList) $3;
3669
3670                 if (catch_list != null){
3671                         foreach (Catch cc in catch_list) {
3672                                 if (cc.IsGeneral)
3673                                         g = cc;
3674                                 else
3675                                         s.Add (cc);
3676                         }
3677                 }
3678
3679                 $$ = new Try ((Block) $2, s, g, (Block) $5, lexer.Location);
3680           }
3681         | TRY block error 
3682           {
3683                 Report.Error (1524, lexer.Location, "Expected catch or finally");
3684           }
3685         ;
3686
3687 opt_catch_clauses
3688         : /* empty */  { $$ = null; }
3689         | catch_clauses
3690         ;
3691
3692 catch_clauses
3693         : catch_clause 
3694           {
3695                 ArrayList l = new ArrayList (4);
3696
3697                 l.Add ($1);
3698                 $$ = l;
3699           }
3700         | catch_clauses catch_clause
3701           {
3702                 ArrayList l = (ArrayList) $1;
3703
3704                 l.Add ($2);
3705                 $$ = l;
3706           }
3707         ;
3708
3709 opt_identifier
3710         : /* empty */   { $$ = null; }
3711         | IDENTIFIER
3712         ;
3713
3714 catch_clause 
3715         : CATCH opt_catch_args 
3716         {
3717                 Expression type = null;
3718                 string id = null;
3719                 
3720                 if ($2 != null) {
3721                         DictionaryEntry cc = (DictionaryEntry) $2;
3722                         type = (Expression) cc.Key;
3723                         id   = (string) cc.Value;
3724
3725                         if (id != null){
3726                                 ArrayList one = new ArrayList (4);
3727                                 Location loc = lexer.Location;
3728
3729                                 one.Add (new VariableDeclaration (id, null, loc));
3730
3731                                 $1 = current_block;
3732                                 current_block = new Block (current_block);
3733                                 Block b = declare_local_variables (type, one, loc);
3734                                 current_block = b;
3735                         }
3736                 }
3737         } block {
3738                 Expression type = null;
3739                 string id = null;
3740
3741                 if ($2 != null){
3742                         DictionaryEntry cc = (DictionaryEntry) $2;
3743                         type = (Expression) cc.Key;
3744                         id   = (string) cc.Value;
3745
3746                         if ($1 != null){
3747                                 //
3748                                 // FIXME: I can change this for an assignment.
3749                                 //
3750                                 while (current_block != (Block) $1)
3751                                         current_block = current_block.Parent;
3752                         }
3753                 }
3754
3755
3756                 $$ = new Catch (type, id , (Block) $4, lexer.Location);
3757         }
3758         ;
3759
3760 opt_catch_args
3761         : /* empty */ { $$ = null; }
3762         | catch_args
3763         ;         
3764
3765 catch_args 
3766         : OPEN_PARENS type opt_identifier CLOSE_PARENS 
3767         {
3768                 $$ = new DictionaryEntry ($2, $3);
3769         }
3770         ;
3771
3772 checked_statement
3773         : CHECKED block
3774           {
3775                 $$ = new Checked ((Block) $2);
3776           }
3777         ;
3778
3779 unchecked_statement
3780         : UNCHECKED block
3781           {
3782                 $$ = new Unchecked ((Block) $2);
3783           }
3784         ;
3785
3786 unsafe_statement
3787         : UNSAFE 
3788         {
3789                 if (!RootContext.Unsafe){
3790                         Report.Error (227, lexer.Location, 
3791                                 "Unsafe code can only be used if --unsafe is used");
3792                 }
3793         } block {
3794                 $$ = new Unsafe ((Block) $3);
3795         }
3796         ;
3797
3798 fixed_statement
3799         : FIXED OPEN_PARENS 
3800           type fixed_pointer_declarators 
3801           CLOSE_PARENS 
3802           {
3803                 Block assign_block = new Block (current_block, Block.Flags.Implicit);
3804                 ArrayList list = (ArrayList) $4;
3805                 Expression type = (Expression) $3;
3806                 Location l = lexer.Location;
3807                 int top = list.Count;
3808
3809                 for (int i = 0; i < top; i++){
3810                         Pair p = (Pair) list [i];
3811                         LocalInfo v;
3812
3813                         v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
3814                         if (v == null)
3815                                 continue;
3816                         v.ReadOnly = true;
3817                         p.First = v;
3818                         list [i] = p;
3819                 }
3820                 current_block.AddStatement (assign_block);
3821                 current_block = assign_block;
3822                 oob_stack.Push (assign_block);
3823                 oob_stack.Push (l);
3824           }
3825           embedded_statement 
3826           {
3827                 Location l = (Location) oob_stack.Pop ();
3828                 oob_stack.Pop ();
3829
3830                 $$ = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
3831           }
3832         ;
3833
3834 fixed_pointer_declarators
3835         : fixed_pointer_declarator      { 
3836                 ArrayList declarators = new ArrayList (4); 
3837                 declarators.Add ($1);
3838                 $$ = declarators;
3839           }
3840         | fixed_pointer_declarators COMMA fixed_pointer_declarator
3841           {
3842                 ArrayList declarators = (ArrayList) $1;
3843                 declarators.Add ($3);
3844                 $$ = declarators;
3845           }
3846         ;
3847
3848 fixed_pointer_declarator
3849         : IDENTIFIER ASSIGN expression
3850           {     
3851                 $$ = new Pair ($1, $3);
3852           }
3853         ;
3854
3855 lock_statement
3856         : LOCK OPEN_PARENS expression CLOSE_PARENS 
3857           {
3858                 //
3859           } 
3860           embedded_statement
3861           {
3862                 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3863           }
3864         ;
3865
3866 using_statement
3867         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
3868           {
3869                 Block assign_block = new Block (current_block);
3870                 current_block = assign_block;
3871
3872                 oob_stack.Push (lexer.Location);
3873                 
3874                 if ($3 is DictionaryEntry){
3875                         DictionaryEntry de = (DictionaryEntry) $3;
3876                         Location l = lexer.Location;
3877
3878                         Expression type = (Expression) de.Key;
3879                         ArrayList var_declarators = (ArrayList) de.Value;
3880
3881                         ArrayList vars = new ArrayList (4);
3882
3883                         foreach (VariableDeclaration decl in var_declarators){
3884
3885                                 LocalInfo vi    = current_block.AddVariable (
3886                                         type, decl.identifier, 
3887                                         current_local_parameters, decl.Location);
3888                                 if (vi == null)
3889                                         continue;
3890                                 vi.ReadOnly = true;
3891
3892                                 Expression expr;
3893                                 if (decl.expression_or_array_initializer is Expression){
3894                                         expr = (Expression) decl.expression_or_array_initializer;
3895                                 } else {
3896                                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3897                                         
3898                                         expr = new ArrayCreation (type, "", init, decl.Location);
3899                                 }
3900
3901                                 LocalVariableReference var;
3902
3903                                 // Get a writable reference to this read-only variable.
3904                                 var = new LocalVariableReference (assign_block, decl.identifier, l, vi, false);
3905
3906                                 // This is so that it is not a warning on using variables
3907                                 vi.Used = true;
3908
3909                                 vars.Add (new DictionaryEntry (var, expr));                             
3910
3911                                 // Assign a = new Assign (var, expr, decl.Location);
3912                                 // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
3913                         }
3914                         $3 = new DictionaryEntry (type, vars);
3915                  }
3916           } 
3917           embedded_statement
3918           {
3919                 Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
3920                 current_block.AddStatement (u);
3921                 while (current_block.Implicit)
3922                         current_block = current_block.Parent;
3923                 $$ = current_block;
3924                 current_block = current_block.Parent;
3925           }
3926         ; 
3927
3928 resource_acquisition
3929         : local_variable_declaration
3930         | expression
3931         ;
3932
3933 %%
3934
3935 // <summary>
3936 //   A class used to pass around variable declarations and constants
3937 // </summary>
3938 public class VariableDeclaration {
3939         public string identifier;
3940         public object expression_or_array_initializer;
3941         public Location Location;
3942         public Attributes OptAttributes;
3943
3944         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs)
3945         {
3946                 this.identifier = id;
3947                 this.expression_or_array_initializer = eoai;
3948                 this.Location = l;
3949                 this.OptAttributes = opt_attrs;
3950         }
3951
3952         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3953         {
3954         }
3955 }
3956
3957 /// <summary>
3958 ///  Used to pass around interface property information
3959 /// </summary>
3960 public class InterfaceAccessorInfo {
3961
3962         public readonly Accessor Get, Set;
3963
3964         public InterfaceAccessorInfo (bool has_get, bool has_set,
3965                                       Attributes get_attrs, Attributes set_attrs)
3966         {
3967                 if (has_get)
3968                         Get = new Accessor (null, get_attrs);
3969                 if (has_set)
3970                         Set = new Accessor (null, set_attrs);
3971         }
3972 }
3973
3974
3975 // <summary>
3976 //   A class used to hold info about an indexer declarator
3977 // </summary>
3978 public class IndexerDeclaration {
3979         public Expression type;
3980         public string interface_type;
3981         public Parameters param_list;
3982
3983         public IndexerDeclaration (Expression type, string interface_type, Parameters param_list)
3984         {
3985                 this.type = type;
3986                 this.interface_type = interface_type;
3987                 this.param_list = param_list;
3988         }
3989 }
3990
3991 //
3992 // We use this when we do not have an object in advance that is an IIteratorContainer
3993 //
3994 public class SimpleIteratorContainer : IIteratorContainer {
3995         public bool Yields;
3996
3997         public static SimpleIteratorContainer Simple = new SimpleIteratorContainer ();
3998
3999         //
4000         // Reset and return
4001         //
4002         public static SimpleIteratorContainer GetSimple () { 
4003                 Simple.Yields = false;
4004                 return Simple;
4005         }
4006
4007         public void SetYields () { Yields = true; } 
4008 }
4009
4010 // <summary>
4011 //  A class used to hold info about an operator declarator
4012 // </summary>
4013 public class OperatorDeclaration {
4014         public Operator.OpType optype;
4015         public Expression ret_type, arg1type, arg2type;
4016         public string arg1name, arg2name;
4017         public Location location;
4018
4019         public OperatorDeclaration (Operator.OpType op, Expression ret_type, 
4020                                     Expression arg1type, string arg1name,
4021                                     Expression arg2type, string arg2name, Location location)
4022         {
4023                 optype = op;
4024                 this.ret_type = ret_type;
4025                 this.arg1type = arg1type;
4026                 this.arg1name = arg1name;
4027                 this.arg2type = arg2type;
4028                 this.arg2name = arg2name;
4029                 this.location = location;
4030         }
4031
4032 }
4033
4034 void Error_ExpectingTypeName (Location l, Expression expr)
4035 {
4036         if (expr is Invocation){
4037                 Report.Error (1002, l, "; expected");
4038         } else {
4039                 Report.Error (-1, l, "Invalid Type definition");
4040         }
4041 }
4042
4043 // <summary>
4044 //   Given the @class_name name, it creates a fully qualified name
4045 //   based on the containing declaration space
4046 // </summary>
4047 string 
4048 MakeName (string class_name)
4049 {
4050         string ns = current_namespace.FullName;
4051         string container_name = current_container.Name;
4052
4053         if (container_name == ""){
4054                 if (ns != "")
4055                         return ns + "." + class_name;
4056                 else
4057                         return class_name;
4058         } else
4059                 return container_name + "." + class_name;
4060 }
4061
4062 // <summary>
4063 //   Used to report back to the user the result of a declaration
4064 //   in the current declaration space
4065 // </summary>
4066 void 
4067 CheckDef (DeclSpace.AdditionResult result, string name, Location l)
4068 {
4069         if (result == DeclSpace.AdditionResult.Success)
4070                 return;
4071
4072         switch (result){
4073         case DeclSpace.AdditionResult.NameExists:
4074                 Report.Error (102, l, "The container `" + current_container.Name + 
4075                                  "' already contains a definition for `"+
4076                                  name + "'");
4077                 break;
4078
4079
4080                 //
4081                 // This is handled only for static Constructors, because
4082                 // in reality we handle these by the semantic analysis later
4083                 //
4084         case DeclSpace.AdditionResult.MethodExists:
4085                 Report.Error (
4086                         111, l, "Class `"+current_container.Name+
4087                         "' already defines a member called '" + 
4088                         name + "' with the same parameter types (more than one default constructor)");
4089                 break;
4090
4091         case DeclSpace.AdditionResult.EnclosingClash:
4092                 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
4093                 break;
4094                 
4095         case DeclSpace.AdditionResult.NotAConstructor:
4096                 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
4097                 break;
4098
4099         case DeclSpace.AdditionResult.Error:
4100                 // Error has already been reported.
4101                 break;
4102         }
4103 }
4104
4105 void 
4106 CheckDef (bool result, string name, Location l)
4107 {
4108         if (result)
4109                 return;
4110         CheckDef (DeclSpace.AdditionResult.NameExists, name, l);
4111 }
4112
4113 Block declare_local_variables (Expression type, ArrayList variable_declarators, Location loc)
4114 {
4115         Block implicit_block;
4116         ArrayList inits = null;
4117
4118         //
4119         // We use the `Used' property to check whether statements
4120         // have been added to the current block.  If so, we need
4121         // to create another block to contain the new declaration
4122         // otherwise, as an optimization, we use the same block to
4123         // add the declaration.
4124         //
4125         // FIXME: A further optimization is to check if the statements
4126         // that were added were added as part of the initialization
4127         // below.  In which case, no other statements have been executed
4128         // and we might be able to reduce the number of blocks for
4129         // situations like this:
4130         //
4131         // int j = 1;  int k = j + 1;
4132         //
4133         if (current_block.Used)
4134                 implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
4135         else
4136                 implicit_block = current_block;
4137
4138         foreach (VariableDeclaration decl in variable_declarators){
4139
4140                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
4141                         if (decl.expression_or_array_initializer != null){
4142                                 if (inits == null)
4143                                         inits = new ArrayList (4);
4144                                 inits.Add (decl);
4145                         }
4146                 }
4147         }
4148
4149         if (inits == null)
4150                 return implicit_block;
4151
4152         foreach (VariableDeclaration decl in inits){
4153                 Assign assign;
4154                 Expression expr;
4155                 
4156                 if (decl.expression_or_array_initializer is Expression){
4157                         expr = (Expression) decl.expression_or_array_initializer;
4158
4159                 } else {
4160                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
4161                         
4162                         expr = new ArrayCreation (type, "", init, decl.Location);
4163                 }
4164
4165                 LocalVariableReference var;
4166                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
4167
4168                 assign = new Assign (var, expr, decl.Location);
4169
4170                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
4171         }
4172         
4173         return implicit_block;
4174 }
4175
4176 Block declare_local_constants (Expression type, ArrayList declarators)
4177 {
4178         Block implicit_block;
4179
4180         if (current_block.Used)
4181                 implicit_block = new Block (current_block, Block.Flags.Implicit);
4182         else
4183                 implicit_block = current_block;
4184
4185         foreach (VariableDeclaration decl in declarators){
4186                 implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
4187                                                   current_local_parameters, decl.Location);
4188         }
4189         
4190         return implicit_block;
4191 }
4192
4193 void CheckAttributeTarget (string a)
4194 {
4195         switch (a) {
4196
4197         case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" :
4198                 return;
4199                 
4200         default :
4201                 Location l = lexer.Location;
4202                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
4203                 break;
4204         }
4205
4206 }
4207
4208 void CheckUnaryOperator (Operator.OpType op)
4209 {
4210         switch (op) {
4211                 
4212         case Operator.OpType.LogicalNot: 
4213         case Operator.OpType.OnesComplement: 
4214         case Operator.OpType.Increment:
4215         case Operator.OpType.Decrement:
4216         case Operator.OpType.True: 
4217         case Operator.OpType.False: 
4218         case Operator.OpType.Addition: 
4219         case Operator.OpType.Subtraction:
4220                 
4221                 break;
4222                 
4223         default :
4224                 Location l = lexer.Location;
4225                 Report.Error (1019, l, "Overloadable unary operator expected"); 
4226                 break;
4227                 
4228         }
4229 }
4230
4231 void CheckBinaryOperator (Operator.OpType op)
4232 {
4233         switch (op) {
4234                 
4235         case Operator.OpType.Addition: 
4236         case Operator.OpType.Subtraction: 
4237         case Operator.OpType.Multiply:
4238         case Operator.OpType.Division:
4239         case Operator.OpType.Modulus: 
4240         case Operator.OpType.BitwiseAnd: 
4241         case Operator.OpType.BitwiseOr:
4242         case Operator.OpType.ExclusiveOr: 
4243         case Operator.OpType.LeftShift: 
4244         case Operator.OpType.RightShift:
4245         case Operator.OpType.Equality: 
4246         case Operator.OpType.Inequality:
4247         case Operator.OpType.GreaterThan: 
4248         case Operator.OpType.LessThan: 
4249         case Operator.OpType.GreaterThanOrEqual:
4250         case Operator.OpType.LessThanOrEqual:
4251                 break;
4252                 
4253         default :
4254                 Location l = lexer.Location;
4255                 Report.Error (1020, l, "Overloadable binary operator expected");
4256                 break;
4257         }
4258         
4259 }
4260
4261 void syntax_error (Location l, string msg)
4262 {
4263         Report.Error (1003, l, "Syntax error, " + msg);
4264 }
4265
4266 void output (string s)
4267 {
4268         Console.WriteLine (s);
4269 }
4270
4271 void note (string s)
4272 {
4273         // Used to put annotations
4274 }
4275
4276 Tokenizer lexer;
4277
4278 public Tokenizer Lexer {
4279         get {
4280                 return lexer;
4281         }
4282 }                  
4283
4284 public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
4285 {
4286         current_namespace = new NamespaceEntry (null, file, null, Location.Null);
4287         this.name = file.Name;
4288         this.file = file;
4289         current_container = RootContext.Tree.Types;
4290         current_container.NamespaceEntry = current_namespace;
4291         oob_stack = new Stack ();
4292         switch_stack = new Stack ();
4293
4294         lexer = new Tokenizer (reader, file, defines);
4295 }
4296
4297 public override void parse ()
4298 {
4299         try {
4300                 if (yacc_verbose_flag)
4301                         yyparse (lexer, new yydebug.yyDebugSimple ());
4302                 else
4303                         yyparse (lexer);
4304                 Tokenizer tokenizer = lexer as Tokenizer;
4305                 tokenizer.cleanup ();           
4306         } catch (Exception e){
4307                 // Please do not remove this, it is used during debugging
4308                 // of the grammar
4309                 //
4310                 Console.WriteLine (e);
4311                 Report.Error (-25, lexer.Location, "Parsing error");
4312                 if (Driver.parser_verbose)
4313                         Console.WriteLine (e);
4314         }
4315 }
4316
4317 void CheckToken (int error, int yyToken, string msg)
4318 {
4319         if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD){
4320                 Report.Error (error, lexer.Location, String.Format ("{0}: `{1}' is a keyword", msg, yyNames [yyToken].ToLower ()));
4321                 return;
4322         }               
4323         Report.Error (error, lexer.Location, msg);
4324 }
4325
4326 void CheckIdentifierToken (int yyToken)
4327 {
4328         CheckToken (1041, yyToken, "Identifier expected");
4329 }
4330
4331 /* end end end */
4332 }