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