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