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