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