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