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