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