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