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