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