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