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