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