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