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