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