2001-10-15 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 CIR;
28 using System;
29
30 namespace CIR
31 {
32         using System.Collections;
33         using Mono.Languages;
34
35         /// <summary>
36         ///    The C# Parser
37         /// </summary>
38         public class CSharpParser : GenericParser {
39                 Namespace     current_namespace;
40                 TypeContainer current_container;
41         
42                 // <summary>
43                 //   Current block is used to add statements as we find
44                 //   them.  
45                 // </summary>
46
47                 Block      current_block;
48
49                 // <summary>
50                 //   Current interface is used by the various declaration
51                 //   productions in the interface declaration to "add"
52                 //   the interfaces as we find them.
53                 // </summary>
54                 Interface  current_interface;
55
56                 // <summary>
57                 //   This is used by the unary_expression code to resolve
58                 //   a name against a parameter.  
59                 // </summary>
60                 Parameters current_local_parameters;
61
62                 // <summary>
63                 //   Using during property parsing to describe the implicit
64                 //   value parameter that is passed to the "set" accesor
65                 //   method
66                 // </summary>
67                 Parameter [] implicit_value_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                 // <summary>
76                 //   Used to record all types defined
77                 // </summary>
78                 Tree tree;
79
80                 RootContext rc; 
81
82 %}
83
84 %token EOF
85 %token NONE   /* This token is never returned by our lexer */
86 %token ERROR            // This is used not by the parser, but by the tokenizer.
87                         // do not remove.
88
89 /*
90  *These are the C# keywords
91  */
92 %token ABSTRACT 
93 %token AS
94 %token ADD
95 %token BASE     
96 %token BOOL     
97 %token BREAK    
98 %token BYTE     
99 %token CASE     
100 %token CATCH    
101 %token CHAR     
102 %token CHECKED  
103 %token CLASS    
104 %token CONST    
105 %token CONTINUE 
106 %token DECIMAL  
107 %token DEFAULT  
108 %token DELEGATE 
109 %token DO       
110 %token DOUBLE   
111 %token ELSE     
112 %token ENUM     
113 %token EVENT    
114 %token EXPLICIT 
115 %token EXTERN   
116 %token FALSE    
117 %token FINALLY  
118 %token FIXED    
119 %token FLOAT    
120 %token FOR      
121 %token FOREACH  
122 %token GOTO     
123 %token IF       
124 %token IMPLICIT 
125 %token IN       
126 %token INT      
127 %token INTERFACE
128 %token INTERNAL 
129 %token IS       
130 %token LOCK     
131 %token LONG     
132 %token NAMESPACE
133 %token NEW      
134 %token NULL     
135 %token OBJECT   
136 %token OPERATOR 
137 %token OUT      
138 %token OVERRIDE 
139 %token PARAMS   
140 %token PRIVATE  
141 %token PROTECTED
142 %token PUBLIC   
143 %token READONLY 
144 %token REF      
145 %token RETURN   
146 %token REMOVE
147 %token SBYTE    
148 %token SEALED   
149 %token SHORT    
150 %token SIZEOF   
151 %token STATIC   
152 %token STRING   
153 %token STRUCT   
154 %token SWITCH   
155 %token THIS     
156 %token THROW    
157 %token TRUE     
158 %token TRY      
159 %token TYPEOF   
160 %token UINT     
161 %token ULONG    
162 %token UNCHECKED
163 %token UNSAFE   
164 %token USHORT   
165 %token USING    
166 %token VIRTUAL  
167 %token VOID     
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_attributes opt_namespace_member_declarations EOF
259           {
260                 // Check that using comes only before namespace elements
261           }
262         ;
263
264 using_directives
265         : using_directive 
266         | using_directives using_directive
267         ;
268
269 using_directive
270         : using_alias_directive
271         | using_namespace_directive
272         ;
273
274 using_alias_directive
275         : USING IDENTIFIER ASSIGN 
276           namespace_or_type_name SEMICOLON
277           {
278                   // FIXME : Need to implement actual action.
279           }
280         ;
281
282 using_namespace_directive
283         : USING namespace_name SEMICOLON 
284           {
285                 current_namespace.Using ((string) $2);
286           }
287         ;
288
289 //  namespace_declarations
290 //      : namespace_declaration
291 //      | namespace_declarations namespace_declaration
292
293 namespace_declaration
294         : NAMESPACE qualified_identifier 
295           {
296                 current_namespace = new Namespace (current_namespace, (string) $2);
297                 tree.RecordNamespace ((string) $2, current_namespace);
298           } 
299           namespace_body opt_semicolon
300           { 
301                 current_namespace = current_namespace.Parent;
302           }
303         ;
304
305 opt_semicolon
306         : /* empty */
307         | SEMICOLON
308         ;
309
310 opt_comma
311         : /* empty */
312         | COMMA
313         ;
314
315 qualified_identifier
316         : IDENTIFIER
317         | qualified_identifier DOT IDENTIFIER { 
318             $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
319         ;
320
321
322 namespace_name
323         : namespace_or_type_name
324         ;
325
326 namespace_body
327         : OPEN_BRACE
328           opt_using_directives
329           opt_namespace_member_declarations
330           CLOSE_BRACE
331           {
332           }
333         ;
334
335 opt_using_directives
336         : /* empty */
337         | using_directives
338         ;
339
340 opt_namespace_member_declarations
341         : /* empty */
342         | namespace_member_declarations
343         ;
344
345 namespace_member_declarations
346         : namespace_member_declaration
347         | namespace_member_declarations namespace_member_declaration
348         ;
349
350 namespace_member_declaration
351         : type_declaration
352           {
353                 int mod_flags = 0;
354                 string name = "";
355
356                 if ($1 is Class){
357                         Class c = (Class) $1;
358                         mod_flags = c.ModFlags;
359                         name = c.Name;
360                 } else if ($1 is Struct){
361                         Struct s = (Struct) $1;
362                         mod_flags = s.ModFlags;
363                         name = s.Name;
364                 } else
365                         break;
366
367                 //
368                 // We remove this error until we can 
369                 //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
370                 //      error (1527, "Namespace elements cant be explicitly " +
371                 //                   "declared private or protected in `" + name + "'");
372                 //}
373           }
374         | namespace_declaration
375         ;
376
377 type_declaration
378         : class_declaration             
379         | struct_declaration            
380         | interface_declaration         
381         | enum_declaration              
382         | delegate_declaration         
383         ;
384
385 //
386 // Attributes 17.2
387 //
388 opt_attributes
389         : /* empty */ { $$ = null; }
390         | attribute_section opt_attributes
391           {
392                 Attributes attrs;
393                 
394                 if ($2 != null) {
395                         attrs = (Attributes) $2;
396                         attrs.AddAttribute ((Attribute) $1);
397                 } else
398                         attrs = new Attributes ((Attribute) $1);
399                 
400                 $$ = attrs;
401           }
402         ;
403
404 attribute_section
405         : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
406           {
407                 string target = null;
408                 
409                 if ($2 != null)
410                         target = (string) $2;
411                 
412                 $$ = new Attribute (target, (ArrayList) $3);
413           }
414         | OPEN_BRACKET attribute_list CLOSE_BRACKET
415           {
416                 $$ = new Attribute (null, (ArrayList) $2);
417           }
418         ;
419  
420 attribute_target_specifier
421         : attribute_target COLON
422           {
423                 $$ = $1;
424           }
425         ;
426
427 attribute_target
428         : IDENTIFIER
429           {
430                 CheckAttributeTarget ((string) $1);
431                 $$ = $1;
432           }
433         | EVENT  { $$ = "event"; }        
434         | RETURN { $$ = "return"; }
435         ;
436
437 attribute_list
438         : attribute
439           {
440                 ArrayList attrs = new ArrayList ();
441                 attrs.Add ($1);
442
443                 $$ = attrs;
444                
445           }
446         | attribute_list COMMA attribute
447           {
448                 ArrayList attrs = (ArrayList) $1;
449                 attrs.Add ($3);
450
451                 $$ = attrs;
452           }
453         ;
454
455 attribute
456         : attribute_name opt_attribute_arguments
457           {
458                 $$ = new DictionaryEntry ($1, $2);
459           }
460         ;
461
462 attribute_name
463         : type_name  { /* reserved attribute name or identifier: 17.4 */ }
464         ;
465
466 opt_attribute_arguments
467         : /* empty */   { $$ = null; }
468         | OPEN_PARENS attribute_arguments CLOSE_PARENS
469           {
470                 $$ = $2;
471           }
472         ;
473
474 attribute_arguments
475         : expression
476           {
477                 ArrayList args = new ArrayList ();
478                 args.Add ($1);
479                 
480                 $$ = args;
481           }
482         | attribute_arguments COMMA expression
483           {
484                 ArrayList args = (ArrayList) $1;
485                 args.Add ($3);
486
487                 $$ = args;
488           }
489         ;
490
491
492 class_body
493         :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
494         ;
495
496 opt_class_member_declarations
497         : /* empty */
498         | class_member_declarations
499         ;
500
501 class_member_declarations
502         : class_member_declaration
503         | class_member_declarations 
504           class_member_declaration
505         ;
506
507 class_member_declaration
508         : constant_declaration                  // done
509         | field_declaration                     // done
510         | method_declaration                    // done
511         | property_declaration                  // done
512         | event_declaration                     // done
513         | indexer_declaration                   // done
514         | operator_declaration                  // done
515         | constructor_declaration               // done
516         | destructor_declaration                // done
517         | type_declaration
518         ;
519
520 struct_declaration
521         : opt_attributes
522           opt_modifiers
523           STRUCT IDENTIFIER
524           { 
525                 Struct new_struct;
526                 string full_struct_name = MakeName ((string) $4);
527
528                 new_struct = new Struct (rc, current_container, full_struct_name, (int) $2, 
529                                          (Attributes) $1, lexer.Location);
530                 current_container = new_struct;
531                 current_container.Namespace = current_namespace;
532                 tree.RecordStruct (full_struct_name, new_struct);
533           }
534           opt_struct_interfaces
535           struct_body
536           opt_semicolon
537           {
538                 Struct new_struct = (Struct) current_container;
539
540                 current_container = current_container.Parent;
541                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
542                 $$ = new_struct;
543           }
544         ;
545
546 opt_struct_interfaces
547         : /* empty */
548         | struct_interfaces
549         ;
550
551 struct_interfaces
552         : struct_interface
553         | struct_interfaces struct_interface
554         ; 
555
556 struct_interface
557         : COLON type_list
558         ;
559
560 struct_body
561         : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
562         ;
563
564 opt_struct_member_declarations
565         : /* empty */
566         | struct_member_declarations
567         ;
568
569 struct_member_declarations
570         : struct_member_declaration
571         | struct_member_declarations struct_member_declaration
572         ;
573
574 struct_member_declaration
575         : constant_declaration
576         | field_declaration
577         | method_declaration
578         | property_declaration
579         | event_declaration
580         | indexer_declaration
581         | operator_declaration
582         | constructor_declaration
583         | type_declaration
584         ;
585
586 constant_declaration
587         : opt_attributes 
588           opt_modifiers
589           CONST
590           type
591           constant_declarators
592           SEMICOLON
593           {
594                 foreach (DictionaryEntry constant in (ArrayList) $5){
595                         Constant c = new Constant (
596                                 (string) $4, (string) constant.Key, 
597                                 (Expression) constant.Value, (int) $2, (Attributes) $1);
598
599                         CheckDef (current_container.AddConstant (c), c.Name);
600                 }
601           }
602         ;
603
604 constant_declarators
605         : constant_declarator 
606           {
607                 ArrayList constants = new ArrayList ();
608                 constants.Add ($1);
609                 $$ = constants;
610           }
611         | constant_declarators COMMA constant_declarator
612           {
613                 ArrayList constants = (ArrayList) $1;
614
615                 constants.Add ($3);
616           }
617         ;
618
619 constant_declarator
620         : IDENTIFIER ASSIGN constant_expression
621           {
622                 $$ = new DictionaryEntry ($1, $3);
623           }
624         ;
625
626 field_declaration
627         : opt_attributes
628           opt_modifiers
629           type 
630           variable_declarators
631           SEMICOLON
632         { 
633                 string type = (string) $3;
634                 int mod = (int) $2;
635
636                 foreach (VariableDeclaration var in (ArrayList) $4){
637                         Field field = new Field (type, mod, var.identifier, 
638                                                  var.expression_or_array_initializer, (Attributes) $1);
639
640                         CheckDef (current_container.AddField (field), field.Name);
641                 }
642         }
643
644         ;
645
646 variable_declarators
647         : variable_declarator 
648           {
649                 ArrayList decl = new ArrayList ();
650                 decl.Add ($1);
651                 $$ = decl;
652           }
653         | variable_declarators COMMA variable_declarator
654           {
655                 ArrayList decls = (ArrayList) $1;
656                 decls.Add ($3);
657                 $$ = $1;
658           }
659         ;
660
661 variable_declarator
662         : IDENTIFIER ASSIGN variable_initializer
663           {
664                 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
665           }
666         | IDENTIFIER
667           {
668                 $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
669           }
670         ;
671
672 variable_initializer
673         : expression
674           {
675                 $$ = $1;
676           }
677         | array_initializer
678         {
679                 $$ = $1;
680         }
681         ;
682
683 method_declaration
684         : method_header
685           method_body
686           {
687                 Method method = (Method) $1;
688                 Block b = (Block) $2;
689                 
690                 if (b == null){
691                         if ((method.ModFlags & (Modifiers.EXTERN | Modifiers.ABSTRACT)) == 0){
692                                 Report.Error (
693                                         501, lexer.Location, "`" + 
694                                         current_container.Name + "." + method.Name + "'" +
695                                         "must declare a body because it is not marked abstract or extern");
696                         }
697                 }
698
699                 method.Block = (Block) $2;
700                 CheckDef (current_container.AddMethod (method), method.Name);
701
702                 current_local_parameters = null;
703           }
704         ;
705
706 method_header
707         : opt_attributes
708           opt_modifiers
709           type
710           member_name
711           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
712           {
713                 Method method = new Method ((string) $3, (int) $2, (string) $4, 
714                                             (Parameters) $6, (Attributes) $1, lexer.Location);
715
716                 current_local_parameters = (Parameters) $6;
717
718                 $$ = method;
719           }
720         | opt_attributes
721           opt_modifiers
722           VOID
723           member_name
724           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
725           {
726                 Method method = new Method ("System.Void", (int) $2, (string) $4, 
727                                             (Parameters) $6, (Attributes) $1, lexer.Location);
728
729                 current_local_parameters = (Parameters) $6;
730                 $$ = method;
731           }
732         ;
733
734 method_body
735         : block
736         | SEMICOLON             { $$ = null; }
737         ;
738
739 opt_formal_parameter_list
740         : /* empty */                   { $$ = new Parameters (null, null); }
741         | formal_parameter_list
742         ;
743
744 formal_parameter_list
745         : fixed_parameters              
746           { 
747                 ArrayList pars_list = (ArrayList) $1;
748
749                 Parameter [] pars = new Parameter [pars_list.Count];
750                 pars_list.CopyTo (pars);
751
752                 $$ = new Parameters (pars, null); 
753           } 
754         | fixed_parameters COMMA parameter_array
755           {
756                 ArrayList pars_list = (ArrayList) $1;
757
758                 Parameter [] pars = new Parameter [pars_list.Count];
759                 pars_list.CopyTo (pars);
760
761                 $$ = new Parameters (pars, (Parameter) $3); 
762           }
763         | parameter_array 
764           {
765                 $$ = new Parameters (null, (Parameter) $1);
766           }
767         ;
768
769 fixed_parameters
770         : fixed_parameter       
771           {
772                 ArrayList pars = new ArrayList ();
773
774                 pars.Add ($1);
775                 $$ = pars;
776           }
777         | fixed_parameters COMMA fixed_parameter
778           {
779                 ArrayList pars = (ArrayList) $1;
780
781                 pars.Add ($3);
782                 $$ = $1;
783           }
784         ;
785
786 fixed_parameter
787         : opt_attributes
788           opt_parameter_modifier
789           type
790           IDENTIFIER
791           {
792                 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
793           }
794         ;
795
796 opt_parameter_modifier
797         : /* empty */           { $$ = Parameter.Modifier.NONE; }
798         | parameter_modifier
799         ;
800
801 parameter_modifier
802         : REF                   { $$ = Parameter.Modifier.REF; }
803         | OUT                   { $$ = Parameter.Modifier.OUT; }
804         ;
805
806 parameter_array
807         : opt_attributes PARAMS type IDENTIFIER
808           { 
809                 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
810                 note ("type must be a single-dimension array type"); 
811           }
812         ;
813
814 member_name 
815         : IDENTIFIER { $$ = $1.ToString (); }
816         | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
817         ;
818
819 property_declaration
820         : opt_attributes
821           opt_modifiers
822           type member_name
823           OPEN_BRACE 
824           {
825                 Parameter implicit_value_parameter;
826                 implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE, null);
827
828                 lexer.properties = true;
829                 
830                 implicit_value_parameters = new Parameter [1];
831                 implicit_value_parameters [0] = implicit_value_parameter;
832           }
833           accessor_declarations 
834           {
835                 lexer.properties = false;
836           }
837           CLOSE_BRACE
838           { 
839                 Property prop;
840                 DictionaryEntry pair = (DictionaryEntry) $7;
841                 Block get_block = null;
842                 Block set_block = null;
843
844                 if (pair.Key != null)
845                         get_block = (Block) pair.Key;
846                 if (pair.Value != null)
847                         set_block = (Block) pair.Value;
848
849                 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block, (Attributes) $1);
850                 
851                 CheckDef (current_container.AddProperty (prop), prop.Name);
852                 implicit_value_parameters = null;
853           }
854         ;
855
856 accessor_declarations
857         : get_accessor_declaration opt_set_accessor_declaration
858           { 
859                 $$ = new DictionaryEntry ($1, $2);
860           }
861         | set_accessor_declaration opt_get_accessor_declaration
862           {
863                 $$ = new DictionaryEntry ($2, $1);
864           }
865         ;
866
867 opt_get_accessor_declaration
868         : /* empty */                   { $$ = null; }
869         | get_accessor_declaration
870         ;
871
872 opt_set_accessor_declaration
873         : /* empty */                   { $$ = null; }
874         | set_accessor_declaration
875         ;
876
877 get_accessor_declaration
878         : opt_attributes GET
879           {
880                 // If this is not the case, then current_local_parameters has already
881                 // been set in indexer_declaration
882                   if (parsing_indexer == false)
883                           current_local_parameters = new Parameters (implicit_value_parameters, null);
884
885                 
886           }
887           accessor_body
888           {
889                 $$ = $4;
890                 current_local_parameters = null;
891           }
892         ;
893
894 set_accessor_declaration
895         : opt_attributes SET 
896           {
897                   if (parsing_indexer == false)  
898                           current_local_parameters = new Parameters (implicit_value_parameters, null);
899           }
900           accessor_body
901           {
902                 $$ = $4;
903                 current_local_parameters = null;
904           }
905         ;
906
907 accessor_body
908         : block 
909         | SEMICOLON             { $$ = new Block (null); }
910         ;
911
912 interface_declaration
913         : opt_attributes
914           opt_modifiers
915           INTERFACE IDENTIFIER
916           {
917                 Interface new_interface;
918                 string full_interface_name = MakeName ((string) $4);
919
920                 new_interface = new Interface (rc, current_container, full_interface_name, (int) $2, 
921                                                (Attributes) $1, lexer.Location);
922                 if (current_interface != null) {
923                         Location l = lexer.Location;
924                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
925                 }
926                 current_interface = new_interface;
927                 tree.RecordInterface (full_interface_name, new_interface);
928           }
929           opt_interface_base
930           interface_body
931           { 
932                 Interface new_interface = (Interface) current_interface;
933
934                 if ($6 != null)
935                         new_interface.Bases = (ArrayList) $6;
936
937                 current_interface = null;
938                 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
939           }
940         ;
941
942 opt_interface_base
943         : /* empty */                     { $$ = null; }
944         | interface_base
945         ;
946
947 interface_base
948         : COLON interface_type_list       { $$ = $2; }
949         ;
950
951 interface_type_list
952         : interface_type
953           {
954                 ArrayList interfaces = new ArrayList ();
955
956                 interfaces.Add ($1);
957                 $$ = interfaces;
958           }
959         | interface_type_list COMMA interface_type
960           {
961                 ArrayList interfaces = (ArrayList) $1;
962                 interfaces.Add ($3);
963                 $$ = interfaces;
964           }
965         ;
966
967 interface_body
968         : OPEN_BRACE
969           opt_interface_member_declarations
970           CLOSE_BRACE
971         ;
972
973 opt_interface_member_declarations
974         : /* empty */
975         | interface_member_declarations
976         ;
977
978 interface_member_declarations
979         : interface_member_declaration
980         | interface_member_declarations interface_member_declaration
981         ;
982
983 interface_member_declaration
984         : interface_method_declaration          
985           { 
986                 InterfaceMethod m = (InterfaceMethod) $1;
987
988                 CheckDef (current_interface.AddMethod (m), m.Name);
989           }
990         | interface_property_declaration        
991           { 
992                 InterfaceProperty p = (InterfaceProperty) $1;
993
994                 CheckDef (current_interface.AddProperty (p), p.Name);
995           }
996         | interface_event_declaration 
997           { 
998                 InterfaceEvent e = (InterfaceEvent) $1;
999
1000                 CheckDef (current_interface.AddEvent (e), e.Name);
1001           }
1002         | interface_indexer_declaration
1003           { 
1004                 InterfaceIndexer i = (InterfaceIndexer) $1;
1005
1006                 CheckDef (current_interface.AddIndexer (i), "indexer");
1007           }
1008         ;
1009
1010 opt_new
1011         : /* empty */   { $$ = false; }
1012         | NEW           { $$ = true; }
1013         ;
1014
1015 interface_method_declaration
1016         : opt_attributes opt_new type IDENTIFIER 
1017           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1018           SEMICOLON
1019           {
1020                 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
1021           }
1022         | opt_attributes opt_new VOID IDENTIFIER 
1023           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1024           SEMICOLON
1025           {
1026                 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
1027           }
1028         ;
1029
1030 interface_property_declaration
1031         : opt_attributes
1032           opt_new
1033           type IDENTIFIER 
1034           OPEN_BRACE 
1035           { lexer.properties = true; }
1036           interface_accesors 
1037           { lexer.properties = false; }
1038           CLOSE_BRACE
1039           {
1040                 int gs = (int) $7;
1041
1042                 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2, 
1043                                             (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1);
1044           }
1045         ;
1046
1047 interface_accesors
1048         : opt_attributes GET SEMICOLON          { $$ = 1; }
1049         | opt_attributes SET SEMICOLON          { $$ = 2; }
1050         | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON 
1051           { $$ = 3; }
1052         | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
1053           { $$ = 3; }
1054         ;
1055
1056 interface_event_declaration
1057         : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
1058           {
1059                 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
1060           }
1061         ;
1062
1063 interface_indexer_declaration 
1064         : opt_attributes opt_new type THIS 
1065           OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1066           OPEN_BRACE 
1067           { lexer.properties = true; }
1068           interface_accesors 
1069           { lexer.properties = false; }
1070           CLOSE_BRACE
1071           {
1072                 int a_flags = (int) $10;
1073
1074                 bool do_get = (a_flags & 1) == 1;
1075                 bool do_set = (a_flags & 2) == 2;
1076
1077                 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2, (Attributes) $1);
1078           }
1079         ;
1080
1081 operator_declaration
1082         : opt_attributes opt_modifiers operator_declarator block
1083           {
1084                 OperatorDeclaration decl = (OperatorDeclaration) $3;
1085                 
1086                 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
1087                                             decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
1088
1089                 // Note again, checking is done in semantic analysis
1090                 current_container.AddOperator (op);
1091           }
1092         ;
1093
1094 operator_declarator
1095         : type OPERATOR overloadable_operator 
1096           OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1097         {
1098                 CheckUnaryOperator ((Operator.OpType) $3);
1099
1100                 $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
1101                                               null, null, lexer.Location);
1102         }
1103         | type OPERATOR overloadable_operator
1104           OPEN_PARENS 
1105                 type IDENTIFIER COMMA
1106                 type IDENTIFIER 
1107           CLOSE_PARENS
1108         {
1109                CheckBinaryOperator ((Operator.OpType) $3);
1110                
1111                $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
1112                                              (string) $8, (string) $9, lexer.Location);
1113         }
1114         | conversion_operator_declarator
1115         ;
1116
1117 overloadable_operator
1118 // Unary operators:
1119         : BANG   { $$ = Operator.OpType.Negate; }
1120         | TILDE  { $$ = Operator.OpType.BitComplement; }  
1121         | OP_INC { $$ = Operator.OpType.Increment; }
1122         | OP_DEC { $$ = Operator.OpType.Decrement; }
1123         | TRUE   { $$ = Operator.OpType.True; }
1124         | FALSE  { $$ = Operator.OpType.False; }
1125 // Unary and binary:
1126         | PLUS { $$ = Operator.OpType.Addition; }
1127         | MINUS { $$ = Operator.OpType.Subtraction; }
1128 // Binary:
1129         | STAR { $$ = Operator.OpType.Multiply; }
1130         | DIV {  $$ = Operator.OpType.Division; }
1131         | PERCENT { $$ = Operator.OpType.Modulus; }
1132         | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
1133         | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
1134         | CARRET { $$ = Operator.OpType.ExclusiveOr; }
1135         | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
1136         | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
1137         | OP_EQ { $$ = Operator.OpType.Equality; }
1138         | OP_NE { $$ = Operator.OpType.Inequality; }
1139         | OP_GT { $$ = Operator.OpType.GreaterThan; }
1140         | OP_LT { $$ = Operator.OpType.LessThan; }
1141         | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
1142         | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
1143         ;
1144
1145 conversion_operator_declarator
1146         : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1147           {
1148                 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
1149                                               null, null, lexer.Location);
1150           }
1151         | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1152           {
1153                 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
1154                                               null, null, lexer.Location);
1155           }
1156         ;
1157
1158 constructor_declaration
1159         : opt_attributes
1160           opt_modifiers
1161           constructor_declarator
1162           block
1163           { 
1164                 Constructor c = (Constructor) $3;
1165                 c.Block = (Block) $4;
1166                 c.ModFlags = (int) $2;
1167
1168                 if ((c.ModFlags & Modifiers.STATIC) != 0){
1169                         if ((c.ModFlags & Modifiers.Accessibility) != 0) {
1170                                 Location l = lexer.Location;
1171                                 Report.Error (515, l, "Access modifiers are not allowed on static constructors");
1172                         }
1173
1174                         if (c.Initializer != null){
1175                                 Location l = lexer.Location;
1176                                 Report.Error (514, l, "Static constructors can not have an explicit this or base constructor invocations");
1177                         }
1178
1179                         if (!c.Parameters.Empty){
1180                                 Location l = lexer.Location;
1181                                 Report.Error (103, l, "Static constructors should not have parameters");
1182                         }
1183                 } 
1184                 
1185                 CheckDef (current_container.AddConstructor (c), c.Name);
1186
1187                 current_local_parameters = null;
1188           }
1189         ;
1190
1191 constructor_declarator
1192         : IDENTIFIER 
1193           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
1194           opt_constructor_initializer
1195           {
1196                 Location l = lexer.Location;
1197
1198                 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $5, l);
1199         
1200                 current_local_parameters = (Parameters) $3;
1201           }
1202         ;
1203
1204 opt_constructor_initializer
1205         : /* empty */                   { $$ = null; }
1206         | constructor_initializer
1207         ;
1208
1209 constructor_initializer
1210         : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1211           {
1212                 $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
1213           }
1214         | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1215           {
1216                 $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
1217           }
1218         ;
1219
1220 destructor_declaration
1221         : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1222           {
1223                 Method d = new Method ("System.Void", 0, "Finalize", 
1224                                        new Parameters (null, null), (Attributes) $1, lexer.Location);
1225                   
1226                 d.Block = (Block) $6;
1227                 CheckDef (current_container.AddMethod (d), d.Name);
1228           }
1229         ;
1230
1231 event_declaration
1232         : opt_attributes
1233           opt_modifiers
1234           EVENT type variable_declarators SEMICOLON
1235           {
1236                 foreach (VariableDeclaration var in (ArrayList) $5) {
1237
1238                         // FIXME : Is this right ?
1239                         Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
1240                                              (int) $2, null, null, (Attributes) $1);
1241
1242                         CheckDef (current_container.AddEvent (e), e.Name);
1243                                        
1244                 }
1245           }
1246         | opt_attributes
1247           opt_modifiers
1248           EVENT type member_name 
1249           OPEN_BRACE event_accessor_declarations CLOSE_BRACE
1250         {
1251                 DictionaryEntry pair = (DictionaryEntry) $7;
1252                 Block add_block = null;
1253                 Block rem_block = null;
1254
1255                 if (pair.Key != null)
1256                         add_block = (Block) pair.Key;
1257                 if (pair.Value != null)
1258                         rem_block = (Block) pair.Value;
1259                 
1260                 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);
1261                 
1262                 CheckDef (current_container.AddEvent (e), e.Name);
1263         }
1264         ;
1265
1266 event_accessor_declarations
1267         : add_accessor_declaration remove_accessor_declaration
1268         {
1269                 $$ = new DictionaryEntry ($1, $2);
1270         }
1271         | remove_accessor_declaration add_accessor_declaration
1272         {
1273                 $$ = new DictionaryEntry ($2, $1);
1274         }       
1275         ;
1276
1277 add_accessor_declaration
1278         : opt_attributes ADD block
1279           {
1280                 $$ = $3;
1281           }
1282         ;
1283
1284 remove_accessor_declaration
1285         : opt_attributes REMOVE block
1286         {
1287                 $$ = $3;
1288         }
1289         ;
1290
1291 indexer_declaration
1292         : opt_attributes opt_modifiers indexer_declarator 
1293           OPEN_BRACE 
1294           {
1295                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1296                   
1297                 lexer.properties = true;
1298                 parsing_indexer  = true;
1299                 
1300                 current_local_parameters = decl.param_list;
1301           }
1302           accessor_declarations 
1303           {
1304                   lexer.properties = false;
1305                   parsing_indexer  = false;
1306           }
1307           CLOSE_BRACE
1308           { 
1309                 // The signature is computed from the signature of the indexer.  Look
1310                 // at section 3.6 on the spec
1311
1312                 Indexer indexer;
1313                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1314                 DictionaryEntry pair = (DictionaryEntry) $6;
1315                 Block get_block = null;
1316                 Block set_block = null;
1317
1318                 if (pair.Key != null)
1319                         get_block = (Block) pair.Key;
1320                 if (pair.Value != null)
1321                         set_block = (Block) pair.Value;
1322
1323                 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
1324                                        get_block, set_block, (Attributes) $1);
1325
1326                 // Note that there is no equivalent of CheckDef for this case
1327                 // We shall handle this in semantic analysis
1328                 
1329                 current_container.AddIndexer (indexer);
1330                 
1331                 current_local_parameters = null;
1332           }
1333         ;
1334
1335 indexer_declarator
1336         : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1337           {
1338                 $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
1339           }
1340         | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1341           {
1342                 $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
1343           }
1344         ;
1345
1346 enum_declaration
1347         : opt_attributes
1348           opt_modifiers
1349           ENUM IDENTIFIER
1350           opt_enum_base
1351           enum_body
1352           opt_semicolon
1353           { 
1354                 string name = (string) $4;
1355                 Enum e = new Enum ((string) $5, (int) $2, name, (Attributes) $1, lexer.Location);
1356
1357                 foreach (VariableDeclaration ev in (ArrayList) $6){
1358                         CheckDef (e.AddEnumMember (ev.identifier, 
1359                                                    (Expression) ev.expression_or_array_initializer),
1360                                   ev.identifier);
1361                 }
1362
1363                 CheckDef (current_container.AddEnum (e), name);
1364           }
1365         ;
1366
1367 opt_enum_base
1368         : /* empty */                   { $$ = "System.Int32"; }
1369         | COLON integral_type           { $$ = $2;   }
1370         ;
1371
1372 enum_body
1373         : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1374           {
1375                 $$ = $2;
1376           }
1377         ;
1378
1379 opt_enum_member_declarations
1380         : /* empty */                   { $$ = new ArrayList (); }
1381         | enum_member_declarations opt_comma { $$ = $1; }
1382         ;
1383
1384 enum_member_declarations
1385         : enum_member_declaration 
1386           {
1387                 ArrayList l = new ArrayList ();
1388
1389                 l.Add ($1);
1390                 $$ = l;
1391           }
1392         | enum_member_declarations COMMA enum_member_declaration
1393           {
1394                 ArrayList l = (ArrayList) $1;
1395
1396                 l.Add ($3);
1397
1398                 $$ = l;
1399           }
1400         ;
1401
1402 enum_member_declaration
1403         : opt_attributes IDENTIFIER 
1404           {
1405                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
1406           }
1407         | opt_attributes IDENTIFIER ASSIGN expression
1408           { 
1409                 $$ = new VariableDeclaration ((string) $2, $4, lexer.Location);
1410           }
1411         ;
1412
1413 delegate_declaration
1414         : opt_attributes
1415           opt_modifiers
1416           DELEGATE type   
1417           IDENTIFIER OPEN_PARENS 
1418           formal_parameter_list
1419           CLOSE_PARENS 
1420           SEMICOLON
1421           {
1422                 Delegate del = new Delegate (rc, (string) $4, (int) $2, MakeName ((string) $5), (Parameters) $7, 
1423                                              (Attributes) $1, lexer.Location);
1424                   
1425                 CheckDef (current_container.AddDelegate (del), del.Name);
1426           }     
1427         | opt_attributes
1428           opt_modifiers
1429           DELEGATE VOID   
1430           IDENTIFIER OPEN_PARENS 
1431           formal_parameter_list
1432           CLOSE_PARENS 
1433           SEMICOLON
1434           {
1435                 Delegate del = new Delegate (rc, "System.Void", (int) $2, (string) $5, (Parameters) $7, 
1436                                              (Attributes) $1, lexer.Location);
1437
1438                 CheckDef (current_container.AddDelegate (del), del.Name);
1439           }
1440         ;
1441
1442 type_name
1443         : namespace_or_type_name
1444         ;
1445
1446 namespace_or_type_name
1447         : qualified_identifier
1448         ;
1449
1450 /* 
1451  * Before you think of adding a return_type, notice that we have been
1452  * using two rules in the places where it matters (one rule using type
1453  * and another identical one that uses VOID as the return type).  This
1454  * gets rid of a shift/reduce couple
1455  */
1456 type
1457         : type_name {   /* class_type */
1458                 /* 
1459                    This does interfaces, delegates, struct_types, class_types, 
1460                    parent classes, and more! 4.2 
1461                  */
1462                 $$ = $1; 
1463           }
1464         | builtin_types
1465         | array_type
1466         ;
1467
1468 type_list
1469         : type
1470           {
1471                 ArrayList types = new ArrayList ();
1472
1473                 types.Add ($1);
1474                 $$ = types;
1475           }
1476         | type_list COMMA type
1477           {
1478                 ArrayList types = (ArrayList) $1;
1479
1480                 types.Add ($3);
1481                 $$ = types;
1482           }
1483         ;
1484
1485 /*
1486  * replaces all the productions for isolating the various
1487  * simple types, but we need this to reuse it easily in local_variable_type
1488  */
1489 builtin_types
1490         : OBJECT        { $$ = "System.Object"; }
1491         | STRING        { $$ = "System.String"; }
1492         | BOOL          { $$ = "System.Boolean"; }
1493         | DECIMAL       { $$ = "System.Decimal"; }
1494         | FLOAT         { $$ = "System.Single"; }
1495         | DOUBLE        { $$ = "System.Double"; }
1496         | integral_type
1497         ;
1498
1499 integral_type
1500         : SBYTE         { $$ = "System.SByte"; }
1501         | BYTE          { $$ = "System.Byte"; }
1502         | SHORT         { $$ = "System.Int16"; }
1503         | USHORT        { $$ = "System.UInt16"; }
1504         | INT           { $$ = "System.Int32"; }
1505         | UINT          { $$ = "System.UInt32"; }
1506         | LONG          { $$ = "System.Int64"; }
1507         | ULONG         { $$ = "System.UInt64"; }
1508         | CHAR          { $$ = "System.Char"; }
1509         ;
1510
1511 interface_type
1512         : type_name
1513         ;
1514
1515 array_type
1516         : type rank_specifiers
1517           {
1518                   $$ = (string) $1 + (string) $2;
1519           }
1520         ;
1521
1522 //
1523 // Expressions, section 7.5
1524 //
1525 primary_expression
1526         : literal
1527           {
1528                 // 7.5.1: Literals
1529           }
1530  
1531         | qualified_identifier
1532           {
1533                 string name = (string) $1;
1534
1535                 $$ = null;
1536                 $$ = DecomposeQI (name, lexer.Location);
1537           }
1538         | parenthesized_expression
1539         | member_access
1540         | invocation_expression
1541         | element_access
1542         | this_access
1543         | base_access
1544         | post_increment_expression
1545         | post_decrement_expression
1546         | new_expression
1547         | typeof_expression
1548         | sizeof_expression
1549         | checked_expression
1550         | unchecked_expression
1551         ;
1552
1553 literal
1554         : boolean_literal
1555         | integer_literal
1556         | real_literal
1557         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
1558         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
1559         | NULL                  { $$ = new NullLiteral (); }
1560         ;
1561
1562 real_literal
1563         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
1564         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
1565         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1566         ;
1567
1568 integer_literal
1569         : LITERAL_INTEGER       { 
1570                 object v = lexer.Value;
1571
1572                 // 
1573                 // FIXME: Possible optimization would be to 
1574                 // compute the *Literal objects directly in the scanner
1575                 //
1576                 if (v is int)
1577                         $$ = new IntLiteral ((Int32) v); 
1578                 else if (v is uint)
1579                         $$ = new UIntLiteral ((UInt32) v);
1580                 else if (v is long)
1581                         $$ = new LongLiteral ((Int64) v);
1582                 else if (v is ulong)
1583                         $$ = new ULongLiteral ((UInt64) v);
1584                 else
1585                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
1586           }
1587         ;
1588
1589 boolean_literal
1590         : TRUE                  { $$ = new BoolLiteral (true); }
1591         | FALSE                 { $$ = new BoolLiteral (false); }
1592         ;
1593
1594 parenthesized_expression
1595         : OPEN_PARENS expression CLOSE_PARENS
1596           { $$ = $2; }
1597         ;
1598
1599 member_access
1600         : primary_expression DOT IDENTIFIER
1601           {
1602                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1603           }
1604         | predefined_type DOT IDENTIFIER
1605           {
1606                 $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
1607           }
1608         ;
1609
1610 predefined_type
1611         : builtin_types
1612         ;
1613
1614 invocation_expression
1615         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
1616           {
1617                 // FIXME:
1618                 // if $1 is MethodGroup
1619                 //      $$ = new Call ($1, $3);
1620                 // else 
1621                 //      $$ = new DelegateCall ($1, $3);
1622                 if ($1 == null) {
1623                         Location l = lexer.Location;
1624                         Report.Error (1, l, "THIS IS CRAZY");
1625                 }
1626                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
1627                 
1628           }
1629         ; 
1630
1631 opt_argument_list
1632         : /* empty */           { $$ = null; }
1633         | argument_list
1634         ;
1635
1636 argument_list
1637         : argument              
1638           { 
1639                 ArrayList list = new ArrayList ();
1640                 list.Add ($1);
1641                 $$ = list;
1642           }
1643         | argument_list COMMA argument
1644           {
1645                 ArrayList list = (ArrayList) $1;
1646                 list.Add ($3);
1647                 $$ = list;
1648           }
1649         ;
1650
1651 argument
1652         : expression
1653           {
1654                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
1655           }
1656         | REF variable_reference 
1657           { 
1658                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
1659           }
1660         | OUT variable_reference 
1661           { 
1662                 $$ = new Argument ((Expression) $2, Argument.AType.Out);
1663           }
1664         ;
1665
1666 variable_reference
1667         : expression { note ("section 5.4"); $$ = $1; }
1668         ;
1669
1670 element_access
1671         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
1672           {
1673                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
1674           }
1675         ;
1676
1677 expression_list
1678         : expression
1679           {
1680                 ArrayList list = new ArrayList ();
1681                 list.Add ($1);
1682                 $$ = list;
1683           }
1684         | expression_list COMMA expression
1685           {
1686                 ArrayList list = (ArrayList) $1;
1687                 list.Add ($3);
1688                 $$ = list;
1689           }
1690         ;
1691
1692 this_access
1693         : THIS
1694           {
1695                 $$ = new This (lexer.Location);
1696           }
1697         ;
1698
1699 base_access
1700         : BASE DOT IDENTIFIER
1701           {
1702                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);
1703           }
1704         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
1705           {
1706                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);
1707           }
1708         ;
1709
1710 post_increment_expression
1711         : primary_expression OP_INC
1712           {
1713                 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1, lexer.Location);
1714           }
1715         ;
1716
1717 post_decrement_expression
1718         : primary_expression OP_DEC
1719           {
1720                 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1, lexer.Location);
1721           }
1722         ;
1723
1724 new_expression
1725         : object_or_delegate_creation_expression
1726         | array_creation_expression
1727         ;
1728
1729 object_or_delegate_creation_expression
1730         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
1731           {
1732                 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
1733           }
1734         ;
1735
1736 array_creation_expression
1737         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
1738           opt_rank_specifier
1739           opt_array_initializer
1740           {
1741                 $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
1742           }
1743         ;
1744
1745 opt_rank_specifier
1746         : /* empty */
1747           {
1748                   $$ = "";
1749           }
1750         | rank_specifiers
1751           {
1752                         $$ = $1;
1753           }
1754         ;
1755
1756 rank_specifiers
1757         : rank_specifier
1758           {
1759                   $$ = $1;
1760           }
1761         | rank_specifiers rank_specifier
1762           {
1763                   $$ = (string) $2 + (string) $1;
1764           }             
1765         ;
1766
1767 rank_specifier
1768         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
1769           {
1770                 $$ = "[" + (string) $2 + "]";
1771           }
1772         ;
1773
1774 opt_dim_separators
1775         : /* empty */
1776           {
1777                 $$ = "";
1778           }
1779         | dim_separators
1780           {
1781                   $$ = $1;
1782           }               
1783         ;
1784
1785 dim_separators
1786         : COMMA
1787           {
1788                 $$ = ",";
1789           }
1790         | dim_separators COMMA
1791           {
1792                 $$ = (string) $1 + ",";
1793           }
1794         ;
1795
1796 opt_array_initializer
1797         : /* empty */
1798           {
1799                 $$ = null;
1800           }
1801         | array_initializer
1802           {
1803                 $$ = $1;
1804           }
1805         ;
1806
1807 array_initializer
1808         : OPEN_BRACE CLOSE_BRACE
1809           {
1810                 ArrayList list = new ArrayList ();
1811                 $$ = list;
1812           }
1813         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
1814           {
1815                 $$ = (ArrayList) $2;
1816           }
1817         ;
1818
1819 variable_initializer_list
1820         : variable_initializer
1821           {
1822                 ArrayList list = new ArrayList ();
1823                 list.Add ($1);
1824                 $$ = list;
1825           }
1826         | variable_initializer_list COMMA variable_initializer
1827           {
1828                 ArrayList list = (ArrayList) $1;
1829                 list.Add ($3);
1830                 $$ = list;
1831           }
1832         ;
1833
1834 typeof_expression
1835         : TYPEOF OPEN_PARENS type CLOSE_PARENS
1836           {
1837                 $$ = new TypeOf ((string) $3);
1838           }
1839         ;
1840
1841 sizeof_expression
1842         : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
1843                 $$ = new SizeOf ((string) $3);
1844
1845                 note ("Verify type is unmanaged"); 
1846                 note ("if (5.8) builtin, yield constant expression");
1847           }
1848         ;
1849
1850 checked_expression
1851         : CHECKED OPEN_PARENS expression CLOSE_PARENS
1852           {
1853                 $$ = new CheckedExpr ((Expression) $3);
1854           }
1855         ;
1856
1857 unchecked_expression
1858         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
1859           {
1860                 $$ = new UnCheckedExpr ((Expression) $3);
1861           }
1862         ;
1863
1864 unary_expression
1865         : primary_expression
1866         | PLUS unary_expression
1867           { 
1868                 $$ = new Unary (Unary.Operator.Addition, (Expression) $2, lexer.Location);
1869           } 
1870         | MINUS unary_expression 
1871           { 
1872                 $$ = new Unary (Unary.Operator.Subtraction, (Expression) $2, lexer.Location);
1873           }
1874         | BANG unary_expression 
1875           {
1876                 $$ = new Unary (Unary.Operator.Negate, (Expression) $2, lexer.Location);
1877           }
1878         | TILDE unary_expression
1879           {
1880                 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2, lexer.Location);
1881           }
1882         | STAR unary_expression
1883           {
1884                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
1885           }
1886         | BITWISE_AND unary_expression
1887           {
1888                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
1889           }
1890         | OP_INC unary_expression 
1891           {
1892                 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
1893           }
1894         | OP_DEC unary_expression 
1895           {
1896                 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);
1897           }
1898         | cast_expression 
1899         /*
1900          we can not do cast expressions at this level,
1901          as there is an ambiguity.  Check "Cast Expressions" 7.6.8
1902          for the recipe to handle this.
1903          */
1904         ;
1905
1906 pre_increment_expression
1907         : OP_INC unary_expression 
1908           {
1909                 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
1910           }
1911         ;
1912
1913 pre_decrement_expression
1914         : OP_DEC unary_expression 
1915           {
1916                 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);
1917           }
1918         ;
1919
1920 cast_expression
1921         /* 
1922          * FIXME: This is actually wrong, it should be `type' but that
1923          * introduces a lot of {shift,reduce}/reduces
1924          *
1925          * This is really really wrong.  We need to track down
1926          * the source of problems with QIs because expressions like:
1927          * foreach (string s in (string []) object) wont be parsed.
1928          */
1929         : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
1930           {
1931                 $$ = new Cast ((string) $2, (Expression) $4, lexer.Location);
1932           }
1933         | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
1934           {
1935                 $$ = new Cast ((string) $2, (Expression) $4, lexer.Location);
1936           }
1937         ;
1938
1939 multiplicative_expression
1940         : unary_expression
1941         | multiplicative_expression STAR unary_expression
1942           {
1943                 $$ = new Binary (Binary.Operator.Multiply, 
1944                                  (Expression) $1, (Expression) $3, lexer.Location);
1945           }
1946         | multiplicative_expression DIV unary_expression
1947           {
1948                 $$ = new Binary (Binary.Operator.Division, 
1949                                  (Expression) $1, (Expression) $3, lexer.Location);
1950           }
1951         | multiplicative_expression PERCENT unary_expression 
1952           {
1953                 $$ = new Binary (Binary.Operator.Modulus, 
1954                                  (Expression) $1, (Expression) $3, lexer.Location);
1955           }
1956         ;
1957
1958 additive_expression
1959         : multiplicative_expression
1960         | additive_expression PLUS multiplicative_expression 
1961           {
1962                 $$ = new Binary (Binary.Operator.Addition, 
1963                                  (Expression) $1, (Expression) $3, lexer.Location);
1964           }
1965         | additive_expression MINUS multiplicative_expression
1966           {
1967                 $$ = new Binary (Binary.Operator.Subtraction, 
1968                                  (Expression) $1, (Expression) $3, lexer.Location);
1969           }
1970         ;
1971
1972 shift_expression
1973         : additive_expression
1974         | shift_expression OP_SHIFT_LEFT additive_expression
1975           {
1976                 $$ = new Binary (Binary.Operator.LeftShift, 
1977                                  (Expression) $1, (Expression) $3, lexer.Location);
1978           }
1979         | shift_expression OP_SHIFT_RIGHT additive_expression
1980           {
1981                 $$ = new Binary (Binary.Operator.RightShift, 
1982                                  (Expression) $1, (Expression) $3, lexer.Location);
1983           }
1984         ; 
1985
1986 relational_expression
1987         : shift_expression
1988         | relational_expression OP_LT shift_expression
1989           {
1990                 $$ = new Binary (Binary.Operator.LessThan, 
1991                                  (Expression) $1, (Expression) $3, lexer.Location);
1992           }
1993         | relational_expression OP_GT shift_expression
1994           {
1995                 $$ = new Binary (Binary.Operator.GreaterThan, 
1996                                  (Expression) $1, (Expression) $3, lexer.Location);
1997           }
1998         | relational_expression OP_LE shift_expression
1999           {
2000                 $$ = new Binary (Binary.Operator.LessThanOrEqual, 
2001                                  (Expression) $1, (Expression) $3, lexer.Location);
2002           }
2003         | relational_expression OP_GE shift_expression
2004           {
2005                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
2006                                  (Expression) $1, (Expression) $3, lexer.Location);
2007           }
2008         | relational_expression IS type
2009           {
2010                 $$ = new Probe (Probe.Operator.Is, 
2011                                  (Expression) $1, (string) $3);
2012           }
2013         | relational_expression AS type
2014           {
2015                 $$ = new Probe (Probe.Operator.As, 
2016                                  (Expression) $1, (string) $3);
2017           }
2018         ;
2019
2020 equality_expression
2021         : relational_expression
2022         | equality_expression OP_EQ relational_expression
2023           {
2024                 $$ = new Binary (Binary.Operator.Equality, 
2025                                  (Expression) $1, (Expression) $3, lexer.Location);
2026           }
2027         | equality_expression OP_NE relational_expression
2028           {
2029                 $$ = new Binary (Binary.Operator.Inequality, 
2030                                  (Expression) $1, (Expression) $3, lexer.Location);
2031           }
2032         ; 
2033
2034 and_expression
2035         : equality_expression
2036         | and_expression BITWISE_AND equality_expression
2037           {
2038                 $$ = new Binary (Binary.Operator.BitwiseAnd, 
2039                                  (Expression) $1, (Expression) $3, lexer.Location);
2040           }
2041         ;
2042
2043 exclusive_or_expression
2044         : and_expression
2045         | exclusive_or_expression CARRET and_expression
2046           {
2047                 $$ = new Binary (Binary.Operator.ExclusiveOr, 
2048                                  (Expression) $1, (Expression) $3, lexer.Location);
2049           }
2050         ;
2051
2052 inclusive_or_expression
2053         : exclusive_or_expression
2054         | inclusive_or_expression BITWISE_OR exclusive_or_expression
2055           {
2056                 $$ = new Binary (Binary.Operator.BitwiseOr, 
2057                                  (Expression) $1, (Expression) $3, lexer.Location);
2058           }
2059         ;
2060
2061 conditional_and_expression
2062         : inclusive_or_expression
2063         | conditional_and_expression OP_AND inclusive_or_expression
2064           {
2065                 $$ = new Binary (Binary.Operator.LogicalAnd, 
2066                                  (Expression) $1, (Expression) $3, lexer.Location);
2067           }
2068         ;
2069
2070 conditional_or_expression
2071         : conditional_and_expression
2072         | conditional_or_expression OP_OR conditional_and_expression
2073           {
2074                 $$ = new Binary (Binary.Operator.LogicalOr, 
2075                                  (Expression) $1, (Expression) $3, lexer.Location);
2076           }
2077         ;
2078
2079 conditional_expression
2080         : conditional_or_expression
2081         | conditional_or_expression INTERR expression COLON expression 
2082           {
2083                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2084           }
2085         ;
2086
2087 assignment_expression
2088         : unary_expression ASSIGN expression
2089           {
2090                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2091           }
2092         | unary_expression OP_MULT_ASSIGN expression
2093           {
2094                 Location l = lexer.Location;
2095
2096                 $$ = new Assign ((Expression) $1,
2097                                  new Binary (Binary.Operator.Multiply, 
2098                                              (Expression) $1,
2099                                              (Expression) $3, l), l);
2100           }
2101         | unary_expression OP_DIV_ASSIGN expression
2102           {
2103                 Location l = lexer.Location;
2104
2105                 $$ = new Assign ((Expression) $1,
2106                                  new Binary (Binary.Operator.Division, 
2107                                              (Expression) $1,
2108                                              (Expression) $3, l), l);
2109           }
2110         | unary_expression OP_MOD_ASSIGN expression
2111           {
2112                 Location l = lexer.Location;
2113
2114                 $$ = new Assign ((Expression) $1,
2115                                  new Binary (Binary.Operator.Modulus, 
2116                                              (Expression) $1,
2117                                              (Expression) $3, l), l);
2118           }
2119         | unary_expression OP_ADD_ASSIGN expression
2120           {
2121                 Location l = lexer.Location;
2122
2123                 $$ = new Assign ((Expression) $1,
2124                                  new Binary (Binary.Operator.Addition, 
2125                                              (Expression) $1,
2126                                              (Expression) $3, l), l);
2127           }
2128         | unary_expression OP_SUB_ASSIGN expression
2129           {
2130                 Location l = lexer.Location;
2131
2132                 $$ = new Assign ((Expression) $1,
2133                                  new Binary (Binary.Operator.Subtraction, 
2134                                              (Expression) $1,
2135                                              (Expression) $3, l), l);
2136           }
2137         | unary_expression OP_SHIFT_LEFT_ASSIGN expression
2138           {
2139                 Location l = lexer.Location;
2140
2141                 $$ = new Assign ((Expression) $1,
2142                                  new Binary (Binary.Operator.LeftShift, 
2143                                              (Expression) $1,
2144                                              (Expression) $3, l), l);
2145           }
2146         | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2147           {
2148                 Location l = lexer.Location;
2149
2150                 $$ = new Assign ((Expression) $1,
2151                                  new Binary (Binary.Operator.RightShift, 
2152                                              (Expression) $1,
2153                                              (Expression) $3, l), l);
2154           }
2155         | unary_expression OP_AND_ASSIGN expression
2156           {
2157                 Location l = lexer.Location;
2158
2159                 $$ = new Assign ((Expression) $1,
2160                                  new Binary (Binary.Operator.BitwiseAnd, 
2161                                              (Expression) $1,
2162                                              (Expression) $3, l), l);
2163           }
2164         | unary_expression OP_OR_ASSIGN expression
2165           {
2166                 Location l = lexer.Location;
2167
2168                 $$ = new Assign ((Expression) $1,
2169                                  new Binary (Binary.Operator.BitwiseOr, 
2170                                              (Expression) $1,
2171                                              (Expression) $3, l), l);
2172           }
2173         | unary_expression OP_XOR_ASSIGN expression
2174           {
2175                 Location l = lexer.Location;
2176
2177                 $$ = new Assign ((Expression) $1,
2178                                  new Binary (Binary.Operator.ExclusiveOr, 
2179                                              (Expression) $1,
2180                                              (Expression) $3, l), l);
2181           }
2182         ;
2183
2184 expression
2185         : conditional_expression
2186         | assignment_expression
2187         ;
2188
2189 constant_expression
2190         : expression
2191         ;
2192
2193 boolean_expression
2194         : expression    { CheckBoolean ((Expression) $1); $$ = $1; } 
2195         ;
2196
2197 //
2198 // 10 classes
2199 //
2200 class_declaration
2201         : opt_attributes
2202           opt_modifiers
2203           CLASS IDENTIFIER
2204           {
2205                 Class new_class;
2206                 string full_class_name = MakeName ((string) $4);
2207
2208                 new_class = new Class (rc, current_container, full_class_name, (int) $2, 
2209                                        (Attributes) $1, lexer.Location);
2210                 current_container = new_class;
2211                 current_container.Namespace = current_namespace;
2212                 tree.RecordClass (full_class_name, new_class);
2213           }
2214           opt_class_base
2215           class_body 
2216           opt_semicolon 
2217           {
2218                 Class new_class = (Class) current_container;
2219
2220                 if ($6 != null)
2221                         new_class.Bases = (ArrayList) $6;
2222
2223                 current_container = current_container.Parent;
2224                 CheckDef (current_container.AddClass (new_class), new_class.Name);
2225
2226                 $$ = new_class;
2227           }
2228         ;       
2229
2230 opt_modifiers
2231         : /* empty */           { $$ = (int) 0; }
2232         | modifiers
2233         ;
2234
2235 modifiers
2236         : modifier
2237         | modifiers modifier
2238           { 
2239                 int m1 = (int) $1;
2240                 int m2 = (int) $2;
2241
2242                 if ((m1 & m2) != 0) {
2243                         Location l = lexer.Location;
2244                         Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2245                 }
2246                 $$ = (int) (m1 | m2);
2247           }
2248         ;
2249
2250 modifier
2251         : NEW                   { $$ = Modifiers.NEW; }
2252         | PUBLIC                { $$ = Modifiers.PUBLIC; }
2253         | PROTECTED             { $$ = Modifiers.PROTECTED; }
2254         | INTERNAL              { $$ = Modifiers.INTERNAL; }
2255         | PRIVATE               { $$ = Modifiers.PRIVATE; }
2256         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
2257         | SEALED                { $$ = Modifiers.SEALED; }
2258         | STATIC                { $$ = Modifiers.STATIC; }
2259         | READONLY              { $$ = Modifiers.READONLY; }
2260         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
2261         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
2262         | EXTERN                { $$ = Modifiers.EXTERN; }
2263         ;
2264
2265 opt_class_base
2266         : /* empty */           { $$ = null; }
2267         | class_base            { $$ = $1;   }
2268         ;
2269
2270 class_base
2271         : COLON type_list { $$ = $2; }
2272         ;
2273
2274 //
2275 // Statements (8.2)
2276 //
2277
2278 //
2279 // A block is "contained" on the following places:
2280 //      method_body
2281 //      property_declaration as part of the accessor body (get/set)
2282 //      operator_declaration
2283 //      constructor_declaration
2284 //      destructor_declaration
2285 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2286 //      
2287 block
2288         : OPEN_BRACE 
2289           {
2290                 current_block = new Block (current_block);
2291           } 
2292           opt_statement_list CLOSE_BRACE 
2293           { 
2294                 while (current_block.Implicit)
2295                         current_block = current_block.Parent;
2296                 $$ = current_block;
2297                 current_block = current_block.Parent;
2298           }
2299         ;
2300
2301 opt_statement_list
2302         : /* empty */
2303         | statement_list 
2304         ;
2305
2306 statement_list
2307         : statement
2308         | statement_list statement
2309         ;
2310
2311 statement
2312         : declaration_statement
2313           {
2314                 if ((Block) $1 != current_block){
2315                         current_block.AddStatement ((Statement) $1);
2316                         current_block = (Block) $1;
2317                 }
2318           }
2319         | embedded_statement
2320           {
2321                 current_block.AddStatement ((Statement) $1);
2322           }
2323         | labeled_statement 
2324           {
2325                 current_block.AddStatement ((Statement) $1);
2326           }
2327         ;
2328
2329 embedded_statement
2330         : block
2331         | empty_statement
2332         | expression_statement
2333         | selection_statement
2334         | iteration_statement
2335         | jump_statement                  
2336         | try_statement
2337         | checked_statement
2338         | unchecked_statement
2339         | lock_statement
2340         | using_statement
2341         ;
2342
2343 empty_statement
2344         : SEMICOLON
2345           {
2346                   $$ = new EmptyStatement ();
2347           }
2348         ;
2349
2350 labeled_statement
2351         : IDENTIFIER COLON statement
2352           {
2353                 string lab = (String) $1;
2354                 Block block;
2355
2356                 block = new Block (current_block, lab);
2357                 block.AddStatement ((Statement) $3);
2358                 $$ = block;
2359
2360                 if (!current_block.AddLabel (lab, block)){
2361                         Location l = lexer.Location;
2362                         Report.Error (140, l, "The label '" + lab + "' is a duplicate");
2363                         $$ = $3;
2364                 }       
2365           }
2366         ;
2367
2368 declaration_statement
2369         : local_variable_declaration SEMICOLON          // done
2370         | local_constant_declaration SEMICOLON          // finishme
2371         ;
2372
2373 /* 
2374  * The following is from Rhys' grammar:
2375  * > Types in local variable declarations must be recognized as 
2376  * > expressions to prevent reduce/reduce errors in the grammar.
2377  * > The expressions are converted into types during semantic analysis.
2378  */
2379 local_variable_type
2380         : primary_expression opt_rank_specifier
2381           { 
2382                 // FIXME: Do something smart here regarding the composition of the type.
2383
2384                 // Ok, the above "primary_expression" is there to get rid of
2385                 // both reduce/reduce and shift/reduces in the grammar, it should
2386                 // really just be "type_name".  If you use type_name, a reduce/reduce
2387                 // creeps up.  If you use qualified_identifier (which is all we need
2388                 // really) two shift/reduces appear.
2389                 // 
2390                 // So, instead we do a super trick: we just allow ($1) to be a 
2391                 // SimpleName Expression.
2392                 //
2393                 if (((Expression) $1) is SimpleName)
2394                         $$ = ((SimpleName) $1).Name;
2395                 else {
2396                         Location l = lexer.Location;
2397                         Report.Error (-1, l, "Invalid Type definition");
2398                         $$ = "System.Object";
2399                 }
2400           }
2401         | builtin_types opt_rank_specifier
2402           {
2403                   $$ = (string) $1 + (string) $2;
2404           }
2405         ;
2406
2407 // FIXME : How can the type of a local variable be void ? I don't quite see ;-)
2408 //          | VOID 
2409 //        {
2410 //              // FIXME: this is a string that represents the type
2411 //              // Figure out something to make this work.
2412 //              $$ = "void";
2413 //        }
2414 //      ;
2415
2416 local_variable_declaration
2417         : local_variable_type variable_declarators
2418           {
2419                 $$ = declare_local_variables ((string) $1, (ArrayList) $2);
2420           }
2421         ;
2422
2423 local_constant_declaration
2424         : CONST type constant_declarator
2425                 // finishme     
2426         ;
2427
2428 expression_statement
2429         : statement_expression SEMICOLON
2430           {
2431                 $$ = $1;
2432           }
2433         ;
2434
2435         //
2436         // We have to do the wrapping here and not in the case above,
2437         // because statement_expression is used for example in for_statement
2438         //
2439 statement_expression
2440         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2441         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1); }
2442         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2443         | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2444         | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2445         | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2446         | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2447         ;
2448
2449 object_creation_expression
2450         : object_or_delegate_creation_expression
2451           { note ("complain if this is a delegate maybe?"); } 
2452         ;
2453
2454 selection_statement
2455         : if_statement
2456         | switch_statement
2457         ; 
2458
2459 if_statement
2460         : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
2461           embedded_statement
2462           { 
2463                 $$ = new If ((Expression) $3, (Statement) $5);
2464           }
2465         | IF OPEN_PARENS boolean_expression CLOSE_PARENS
2466           embedded_statement ELSE embedded_statement
2467           {
2468                 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
2469           }
2470         ;
2471
2472 switch_statement
2473         : SWITCH OPEN_PARENS expression CLOSE_PARENS 
2474           switch_block
2475           {
2476                 $$ = new Switch ((Expression) $3, (ArrayList) $5);
2477           }
2478         ;
2479
2480 switch_block
2481         : OPEN_BRACE
2482           opt_switch_sections
2483           CLOSE_BRACE
2484           {
2485                 $$ = $2;
2486           }
2487         ;
2488
2489 opt_switch_sections
2490         : /* empty */           { $$ = new ArrayList (); }
2491         | switch_sections
2492         ;
2493
2494 switch_sections
2495         : switch_section 
2496           {
2497                 ArrayList sections = new ArrayList ();
2498
2499                 sections.Add ($1);
2500                 $$ = sections;
2501           }
2502         | switch_sections switch_section
2503           {
2504                 ArrayList sections = (ArrayList) $1;
2505
2506                 sections.Add ($2);
2507                 $$ = sections;
2508           }
2509         ;
2510
2511 switch_section
2512         : switch_labels
2513           {
2514                 current_block = new Block (current_block);
2515           }
2516           statement_list 
2517           {
2518                 while (current_block.Implicit)
2519                         current_block = current_block.Parent;
2520                 $$ = new SwitchSection ((ArrayList) $1, current_block);
2521                 current_block = current_block.Parent;
2522           }
2523         ;
2524
2525 switch_labels
2526         : switch_label 
2527           {
2528                 ArrayList labels = new ArrayList ();
2529
2530                 labels.Add ($1);
2531                 $$ = labels;
2532           }
2533         | switch_labels switch_label 
2534           {
2535                 ArrayList labels = (ArrayList) ($1);
2536                 labels.Add ($2);
2537
2538                 $$ = labels;
2539           }
2540         ;
2541
2542 switch_label
2543         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2); }
2544         | DEFAULT COLON                         { $$ = new SwitchLabel (null); }
2545         ;
2546
2547 iteration_statement
2548         : while_statement
2549         | do_statement
2550         | for_statement
2551         | foreach_statement
2552         ;
2553
2554 while_statement
2555         : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
2556         {
2557                 $$ = new While ((Expression) $3, (Statement) $5);
2558         }
2559         ;
2560
2561 do_statement
2562         : DO embedded_statement 
2563           WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
2564           {
2565                 $$ = new Do ((Statement) $2, (Expression) $5);
2566           }
2567         ;
2568
2569 for_statement
2570         : FOR OPEN_PARENS 
2571           opt_for_initializer SEMICOLON
2572           opt_for_condition SEMICOLON
2573           opt_for_iterator CLOSE_PARENS 
2574           embedded_statement
2575           {
2576                 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
2577           }
2578         ;
2579
2580 opt_for_initializer
2581         : /* empty */           { $$ = new EmptyStatement (); }
2582         | for_initializer       
2583         ;
2584
2585 for_initializer
2586         : local_variable_declaration 
2587           {
2588                 if ((Block) $1 != current_block){
2589                         current_block.AddStatement ((Statement) $1);
2590                         current_block = (Block) $1;
2591                 }
2592           }
2593         | statement_expression_list
2594         ;
2595
2596 opt_for_condition
2597         : /* empty */           { $$ = new BoolLiteral (true); }
2598         | boolean_expression
2599         ;
2600
2601 opt_for_iterator
2602         : /* empty */           { $$ = new EmptyStatement (); }
2603         | for_iterator
2604         ;
2605
2606 for_iterator
2607         : statement_expression_list
2608         ;
2609
2610 statement_expression_list
2611         : statement_expression  
2612           {
2613                 Block b = new Block (null, true);
2614
2615                 b.AddStatement ((Statement) $1);
2616                 $$ = b;
2617           }
2618         | statement_expression_list COMMA statement_expression
2619           {
2620                 Block b = (Block) $1;
2621
2622                 b.AddStatement ((Statement) $3);
2623                 $$ = $1;
2624           }
2625         ;
2626
2627 foreach_statement
2628         : FOREACH OPEN_PARENS type IDENTIFIER IN 
2629           { 
2630                 $1 = lexer.Location;
2631           } 
2632           expression CLOSE_PARENS 
2633           embedded_statement
2634           {
2635                 Block foreach_block = new Block (current_block, true);
2636                 LocalVariableReference v;
2637
2638                 foreach_block.AddVariable ((string) $3, (string) $4, (Location) $1);
2639                 v = new LocalVariableReference (foreach_block, (string) $4);
2640                 foreach_block.AddStatement (new Foreach ((string) $3, v, (Expression) $7, 
2641                                             (Statement) $9, (Location) $1));
2642                 $$ = foreach_block;
2643           }
2644         ;
2645
2646 jump_statement
2647         : break_statement
2648         | continue_statement
2649         | goto_statement
2650         | return_statement
2651         | throw_statement
2652         ;
2653
2654 break_statement
2655         : BREAK SEMICOLON
2656           {
2657                 $$ = new Break ();
2658           }
2659         ;
2660
2661 continue_statement
2662         : CONTINUE SEMICOLON
2663           {
2664                 $$ = new Continue ();
2665           }
2666         ;
2667
2668 goto_statement
2669         : GOTO IDENTIFIER SEMICOLON 
2670           {
2671                 $$ = new Goto ((string) $2);
2672           }
2673         | GOTO CASE constant_expression SEMICOLON
2674         | GOTO DEFAULT SEMICOLON 
2675         ; 
2676
2677 return_statement
2678         : RETURN opt_expression SEMICOLON
2679           {
2680                 $$ = new Return ((Expression) $2, lexer.Location);
2681           }
2682         ;
2683
2684 throw_statement
2685         : THROW opt_expression SEMICOLON
2686           {
2687                 $$ = new Throw ((Expression) $2);
2688           }
2689         ;
2690
2691 opt_expression
2692         : /* empty */
2693         | expression
2694         ;
2695
2696 try_statement
2697         : TRY block catch_clauses 
2698         {
2699                 Catch g = null;
2700                 ArrayList s = new ArrayList ();
2701                 
2702                 foreach (Catch cc in (ArrayList) $3) {
2703                         if (cc.Type == null)
2704                                 g = cc;
2705                         else
2706                                 s.Add (cc);
2707                 }
2708
2709                 // Now s contains the list of specific catch clauses
2710                 // and g contains the general one.
2711                 
2712                 $$ = new Try ((Block) $2, s, g, null);
2713         }
2714         | TRY block opt_catch_clauses FINALLY block
2715           {
2716                 Catch g = null;
2717                 ArrayList s = new ArrayList ();
2718                 
2719                 foreach (Catch cc in (ArrayList) $3) {
2720                         if (cc.Type == null)
2721                                 g = cc;
2722                         else
2723                                 s.Add (cc);
2724                 }
2725
2726                 $$ = new Try ((Block) $2, s, g, (Block) $5);
2727           }
2728         ;
2729
2730 opt_catch_clauses
2731         : /* empty */  { $$ = null; }
2732         | catch_clauses
2733         ;
2734
2735 catch_clauses
2736         : catch_clause 
2737           {
2738                 ArrayList l = new ArrayList ();
2739
2740                 l.Add ($1);
2741                 $$ = l;
2742           }
2743         | catch_clauses catch_clause
2744           {
2745                 ArrayList l = (ArrayList) $1;
2746
2747                 l.Add ($2);
2748                 $$ = l;
2749           }
2750         ;
2751
2752 opt_identifier
2753         : /* empty */   { $$ = null; }
2754         | IDENTIFIER
2755         ;
2756
2757 catch_clause 
2758         : CATCH opt_catch_args 
2759         {
2760                 string type = null, id = null;
2761                 
2762                 if ($2 != null) {
2763                         DictionaryEntry cc = (DictionaryEntry) $2;
2764                         type = (string) cc.Key;
2765                         id   = (string) cc.Value;
2766
2767                         if (id != null){
2768                                 ArrayList one = new ArrayList ();
2769                                 one.Add (new VariableDeclaration (id, null, lexer.Location));
2770
2771                                 $1 = current_block;
2772                                 current_block = new Block (current_block);
2773                                 Block b = declare_local_variables (type, one);
2774                                 current_block = b;
2775
2776                                 
2777                         }
2778                 }
2779         } block {
2780                 string type = null, id = null;
2781
2782                 if ($2 != null){
2783                         DictionaryEntry cc = (DictionaryEntry) $2;
2784                         type = (string) cc.Key;
2785                         id   = (string) cc.Value;
2786
2787                         if ($1 != null){
2788                                 while (current_block != (Block) $1)
2789                                         current_block = current_block.Parent;
2790                         }
2791                 }
2792
2793
2794                 $$ = new Catch (type, id , (Block) $4);
2795         }
2796         ;
2797
2798 opt_catch_args
2799         : /* empty */ { $$ = null; }
2800         | catch_args
2801         ;         
2802
2803 catch_args 
2804         : OPEN_PARENS type opt_identifier CLOSE_PARENS 
2805         {
2806                 $$ = new DictionaryEntry ($2, $3);
2807         }
2808         ;
2809
2810 checked_statement
2811         : CHECKED block
2812           {
2813                 $$ = new Checked ((Block) $2);
2814           }
2815         ;
2816
2817 unchecked_statement
2818         : UNCHECKED block
2819           {
2820                 $$ = new Unchecked ((Block) $2);
2821           }
2822         ;
2823
2824 lock_statement
2825         : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
2826           {
2827                 $$ = new Lock ((Expression) $3, (Statement) $5);
2828           }
2829         ;
2830
2831 using_statement
2832         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
2833           // finishme
2834         ; 
2835
2836 resource_acquisition
2837         : local_variable_declaration
2838           {
2839                 // FIXME: Add the current block chaining for local_variable_decl
2840           }
2841           expression
2842           // finishme
2843         ;
2844
2845 %%
2846
2847 // <summary>
2848 //   A class used to pass around variable declarations and constants
2849 // </summary>
2850 public class VariableDeclaration {
2851         public string identifier;
2852         public object expression_or_array_initializer;
2853         public Location Location;
2854
2855         public VariableDeclaration (string id, object eoai, Location l){
2856                 this.identifier = id;
2857                 this.expression_or_array_initializer = eoai;
2858                 this.Location = l;
2859         }
2860 }
2861
2862 // <summary>
2863 //   A class used to hold info about an indexer declarator
2864 // </summary>
2865
2866 public class IndexerDeclaration {
2867         public string type;
2868         public string interface_type;
2869         public Parameters param_list;
2870
2871         public IndexerDeclaration (string type, string interface_type, Parameters param_list)
2872         {
2873                 this.type = type;
2874                 this.interface_type = interface_type;
2875                 this.param_list = param_list;
2876         }
2877 }
2878
2879 // <summary>
2880 //  A class used to hold info about an operator declarator
2881 // </summary>
2882
2883 public class OperatorDeclaration {
2884         public Operator.OpType optype;
2885         public string ret_type;
2886         public string arg1type;
2887         public string arg1name;
2888         public string arg2type;
2889         public string arg2name;
2890         public Location location;
2891
2892         public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
2893                                     string arg2type, string arg2name, Location location)
2894         {
2895                 optype = op;
2896                 this.ret_type = ret_type;
2897                 this.arg1type = arg1type;
2898                 this.arg1name = arg1name;
2899                 this.arg2type = arg2type;
2900                 this.arg2name = arg2name;
2901                 this.location = location;
2902         }
2903
2904 }
2905
2906 // <summary>
2907 //   Given the @class_name name, it creates a fully qualified name
2908 //   based on the containing declaration space
2909 // </summary>
2910 string 
2911 MakeName (string class_name)
2912 {
2913         string ns = current_namespace.Name;
2914         string container_name = current_container.Name;
2915
2916         if (container_name == ""){
2917                 if (ns != "")
2918                         return ns + "." + class_name;
2919                 else
2920                         return class_name;
2921         } else
2922                 return container_name + "." + class_name;
2923 }
2924
2925 // <summary>
2926 //   Used to report back to the user the result of a declaration
2927 //   in the current declaration space
2928 // </summary>
2929 void 
2930 CheckDef (DeclSpace.AdditionResult result, string name)
2931 {
2932         if (result == DeclSpace.AdditionResult.Success)
2933                 return;
2934
2935         Location l = lexer.Location;
2936         
2937         switch (result){
2938         case DeclSpace.AdditionResult.NameExists:
2939                 Report.Error (102, l, "The namespace `" + current_container.Name + 
2940                                  "' already contains a definition for `"+
2941                                  name + "'");
2942                 break;
2943
2944
2945 //      NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
2946 //
2947 //      case DeclSpace.AdditionResult.MethodDuplicated:
2948 //              error (111, "Class `"+current_container.Name+
2949 //                          "' already defines a member called '" + 
2950 //                          name + "' with the same parameter types");
2951 //              break;
2952
2953         case DeclSpace.AdditionResult.EnclosingClash:
2954                 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
2955                 break;
2956                 
2957         case DeclSpace.AdditionResult.NotAConstructor:
2958                 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
2959                 break;
2960         }
2961 }
2962
2963 void 
2964 CheckDef (bool result, string name)
2965 {
2966         if (result)
2967                 return;
2968         CheckDef (DeclSpace.AdditionResult.NameExists, name);
2969 }
2970
2971 Expression
2972 SimpleLookup (string name)
2973 {
2974         //
2975         // we need to check against current_block not being null
2976         // as `expression' is allowed in argument_lists, which 
2977         // do not exist inside a block.  
2978         //
2979         if (current_block != null){
2980                 if (current_block.IsVariableDefined (name))
2981                         return new LocalVariableReference (current_block, name);
2982         }
2983
2984         if (current_local_parameters != null){
2985                 int idx;
2986                 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
2987                 if (par != null)
2988                         return new ParameterReference (current_local_parameters, idx, name);
2989         }
2990
2991         return null;
2992 }
2993
2994 Expression DecomposeQI (string name, Location l)
2995 {
2996         Expression o;
2997
2998         if (name.IndexOf ('.') == -1){
2999                 o = SimpleLookup (name);
3000                 if (o == null)
3001                         return new SimpleName (name, l);
3002                 return o;
3003         } else {
3004                 int pos = name.LastIndexOf (".");
3005                 string left = name.Substring (0, pos);
3006                 string right = name.Substring (pos + 1);
3007
3008                 o = DecomposeQI (left, l);
3009                 return new MemberAccess (o, right, l);
3010         }
3011 }
3012
3013 Block declare_local_variables (string type, ArrayList variable_declarators)
3014 {
3015         Block implicit_block;
3016         ArrayList inits = null;
3017
3018         //
3019         // We use the `Used' property to check whether statements
3020         // have been added to the current block.  If so, we need
3021         // to create another block to contain the new declaration
3022         // otherwise, as an optimization, we use the same block to
3023         // add the declaration.
3024         //
3025         // FIXME: A further optimization is to check if the statements
3026         // that were added were added as part of the initialization
3027         // below.  In which case, no other statements have been executed
3028         // and we might be able to reduce the number of blocks for
3029         // situations like this:
3030         //
3031         // int j = 1;  int k = j + 1;
3032         //
3033         if (current_block.Used)
3034                 implicit_block = new Block (current_block, true);
3035         else
3036                 implicit_block = current_block;
3037
3038         foreach (VariableDeclaration decl in variable_declarators){
3039                 if (implicit_block.AddVariable (type, decl.identifier, decl.Location)){
3040                         if (decl.expression_or_array_initializer != null){
3041                                 if (inits == null)
3042                                         inits = new ArrayList ();
3043                                 inits.Add (decl);
3044                         }
3045                 } else {
3046                         Location l = lexer.Location;
3047                         Report.Error (128, l, "A local variable `" + decl.identifier +
3048                                          "' is already defined in this scope");
3049                 }
3050         }
3051
3052         if (inits == null)
3053                 return implicit_block;
3054
3055         foreach (VariableDeclaration decl in inits){
3056                 if (decl.expression_or_array_initializer is Expression){
3057                         Expression expr = (Expression) decl.expression_or_array_initializer;
3058                         Assign assign;
3059                         
3060                         assign = new Assign (new LocalVariableReference (
3061                                              implicit_block, decl.identifier), 
3062                                              expr, lexer.Location);
3063                         implicit_block.AddStatement (new StatementExpression (assign));
3064                 } else {
3065                         Console.WriteLine ("Not handling Array initializers yet");
3066                 }
3067         }
3068                         
3069         return implicit_block;
3070 }
3071
3072 void CheckConstant (Expression expr)
3073 {
3074         // finishme
3075 }
3076
3077 void CheckBoolean (Expression expr)
3078 {
3079         // finishme
3080 }
3081
3082 void CheckAttributeTarget (string a)
3083 {
3084         switch (a) {
3085
3086         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3087                 return;
3088                 
3089         default :
3090                 Location l = lexer.Location;
3091                 Report.Error (658, l, "Invalid attribute target");
3092                 break;
3093         }
3094
3095 }
3096
3097 void CheckUnaryOperator (Operator.OpType op)
3098 {
3099         switch (op) {
3100                 
3101         case Operator.OpType.Negate: 
3102         case Operator.OpType.BitComplement: 
3103         case Operator.OpType.Increment:
3104         case Operator.OpType.Decrement:
3105         case Operator.OpType.True: 
3106         case Operator.OpType.False: 
3107         case Operator.OpType.Addition: 
3108         case Operator.OpType.Subtraction:
3109                 
3110                 break;
3111                 
3112         default :
3113                 Location l = lexer.Location;
3114                 Report.Error (1019, l, "Overloadable unary operator expected"); 
3115                 break;
3116                 
3117         }
3118 }
3119
3120 void CheckBinaryOperator (Operator.OpType op)
3121 {
3122         switch (op) {
3123                 
3124         case Operator.OpType.Addition: 
3125         case Operator.OpType.Subtraction: 
3126         case Operator.OpType.Multiply:
3127         case Operator.OpType.Division:
3128         case Operator.OpType.Modulus: 
3129         case Operator.OpType.BitwiseAnd: 
3130         case Operator.OpType.BitwiseOr:
3131         case Operator.OpType.ExclusiveOr: 
3132         case Operator.OpType.LeftShift: 
3133         case Operator.OpType.RightShift:
3134         case Operator.OpType.Equality: 
3135         case Operator.OpType.Inequality:
3136         case Operator.OpType.GreaterThan: 
3137         case Operator.OpType.LessThan: 
3138         case Operator.OpType.GreaterThanOrEqual:
3139         case Operator.OpType.LessThanOrEqual:
3140                 break;
3141                 
3142         default :
3143                 Location l = lexer.Location;
3144                 Report.Error (1020, l, "Overloadable binary operator expected");
3145                 break;
3146         }
3147         
3148 }
3149
3150 void output (string s)
3151 {
3152         Console.WriteLine (s);
3153 }
3154
3155 void note (string s)
3156 {
3157         // Used to put annotations
3158 }
3159
3160 Tokenizer lexer;
3161
3162 public Tokenizer Lexer {
3163         get {
3164                 return lexer;
3165         }
3166 }                  
3167
3168 public CSharpParser(RootContext rc, string name, System.IO.Stream input)
3169 {
3170         current_namespace = new Namespace (null, "");
3171         this.rc = rc;
3172         this.tree = rc.Tree;
3173         this.name = name;
3174         this.input = input;
3175         current_container = tree.Types;
3176         current_container.Namespace = current_namespace;
3177
3178         lexer = new Tokenizer (input, name);
3179 }
3180
3181 public override int parse ()
3182 {
3183         StringBuilder value = new StringBuilder ();
3184
3185         global_errors = 0;
3186         try {
3187                 if (yacc_verbose_flag)
3188                         yyparse (lexer, new yydebug.yyDebugSimple ());
3189                 else
3190                         yyparse (lexer);
3191         } catch (Exception e){
3192                 // Console.WriteLine ("Fatal error: " + name);
3193                 // Console.WriteLine (lexer.location);
3194
3195                 Console.WriteLine (lexer.location + "  : Parsing error ");
3196                 Console.WriteLine (e);
3197                 global_errors++;
3198         }
3199         
3200         return global_errors;
3201 }
3202
3203
3204 /* end end end */
3205 }