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