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