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