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