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