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