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