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