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