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