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