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