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