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