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