2001-11-24 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         | IMPLICIT error 
1271           {
1272                 syntax_error (lexer.Location, "'operator' expected");
1273           }
1274         | EXPLICIT error 
1275           {
1276                 syntax_error (lexer.Location, "'operator' expected");
1277           }
1278         ;
1279
1280 constructor_declaration
1281         : opt_attributes
1282           opt_modifiers
1283           constructor_declarator
1284           block
1285           { 
1286                 Constructor c = (Constructor) $3;
1287                 c.Block = (Block) $4;
1288                 c.ModFlags = (int) $2;
1289                 c.OptAttributes = (Attributes) $1;
1290
1291                 if ((c.ModFlags & Modifiers.STATIC) != 0){
1292                         if ((c.ModFlags & Modifiers.Accessibility) != 0) {
1293                                 Location l = lexer.Location;
1294                                 Report.Error (515, l, "Access modifiers are not allowed on static constructors");
1295                         }
1296
1297                         if (c.Initializer != null){
1298                                 Location l = lexer.Location;
1299                                 Report.Error (514, l, "Static constructors can not have an explicit this or base constructor invocations");
1300                         }
1301
1302                         if (!c.Parameters.Empty){
1303                                 Location l = lexer.Location;
1304                                 Report.Error (103, l, "Static constructors should not have parameters");
1305                         }
1306                 } 
1307                 
1308                 CheckDef (current_container.AddConstructor (c), c.Name);
1309
1310                 current_local_parameters = null;
1311           }
1312         ;
1313
1314 constructor_declarator
1315         : IDENTIFIER 
1316           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
1317           opt_constructor_initializer
1318           {
1319                 Location l = lexer.Location;
1320
1321                 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $5, l);
1322         
1323                 current_local_parameters = (Parameters) $3;
1324           }
1325         ;
1326
1327 opt_constructor_initializer
1328         : /* empty */                   { $$ = null; }
1329         | constructor_initializer
1330         ;
1331
1332 constructor_initializer
1333         : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1334           {
1335                 $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
1336           }
1337         | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1338           {
1339                 $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
1340           }
1341         ;
1342
1343 destructor_declaration
1344         : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1345           {
1346                 //
1347                 // FIXME: The destructor needs to generate special code:
1348                 //
1349                 // ~X ()
1350                 // { balh (); }
1351                 //
1352                 //
1353                 // void Finalize () { 
1354                 // try { code } finally { base.Finalize (); }
1355                 //
1356                 Method d = new Method ("System.Void", 0, "Finalize", 
1357                                        new Parameters (null, null), (Attributes) $1, lexer.Location);
1358                   
1359                 d.Block = (Block) $6;
1360                 CheckDef (current_container.AddMethod (d), d.Name);
1361           }
1362         ;
1363
1364 event_declaration
1365         : opt_attributes
1366           opt_modifiers
1367           EVENT type variable_declarators SEMICOLON
1368           {
1369                 foreach (VariableDeclaration var in (ArrayList) $5) {
1370
1371                         // FIXME : Is this right ?
1372                         Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
1373                                              (int) $2, null, null, (Attributes) $1, lexer.Location);
1374
1375                         CheckDef (current_container.AddEvent (e), e.Name);
1376                                        
1377                 }
1378           }
1379         | opt_attributes
1380           opt_modifiers
1381           EVENT type member_name 
1382           OPEN_BRACE event_accessor_declarations CLOSE_BRACE
1383         {
1384                 DictionaryEntry pair = (DictionaryEntry) $7;
1385                 Block add_block = null;
1386                 Block rem_block = null;
1387
1388                 if (pair.Key != null)
1389                         add_block = (Block) pair.Key;
1390                 if (pair.Value != null)
1391                         rem_block = (Block) pair.Value;
1392                 
1393                 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block,
1394                                      (Attributes) $1, lexer.Location);
1395                 
1396                 CheckDef (current_container.AddEvent (e), e.Name);
1397         }
1398         ;
1399
1400 event_accessor_declarations
1401         : add_accessor_declaration remove_accessor_declaration
1402         {
1403                 $$ = new DictionaryEntry ($1, $2);
1404         }
1405         | remove_accessor_declaration add_accessor_declaration
1406         {
1407                 $$ = new DictionaryEntry ($2, $1);
1408         }       
1409         ;
1410
1411 add_accessor_declaration
1412         : opt_attributes ADD block
1413           {
1414                 $$ = $3;
1415           }
1416         ;
1417
1418 remove_accessor_declaration
1419         : opt_attributes REMOVE block
1420         {
1421                 $$ = $3;
1422         }
1423         ;
1424
1425 indexer_declaration
1426         : opt_attributes opt_modifiers indexer_declarator 
1427           OPEN_BRACE 
1428           {
1429                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1430
1431                 implicit_value_parameter_type = decl.type;
1432                 
1433                 lexer.properties = true;
1434                 parsing_indexer  = true;
1435                 
1436                 indexer_parameters = decl.param_list;
1437                 $$ = lexer.Location;
1438           }
1439           accessor_declarations 
1440           {
1441                   lexer.properties = false;
1442                   parsing_indexer  = false;
1443           }
1444           CLOSE_BRACE
1445           { 
1446                 // The signature is computed from the signature of the indexer.  Look
1447                 // at section 3.6 on the spec
1448
1449                 Indexer indexer;
1450                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1451                 DictionaryEntry pair = (DictionaryEntry) $6;
1452                 Block get_block = null;
1453                 Block set_block = null;
1454
1455                 if (pair.Key != null)
1456                         get_block = (Block) pair.Key;
1457                 if (pair.Value != null)
1458                         set_block = (Block) pair.Value;
1459
1460                 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
1461                                        get_block, set_block, (Attributes) $1, (Location) $5);
1462
1463                 // Note that there is no equivalent of CheckDef for this case
1464                 // We shall handle this in semantic analysis
1465                 
1466                 current_container.AddIndexer (indexer);
1467                 
1468                 current_local_parameters = null;
1469                 implicit_value_parameter_type = null;
1470                 indexer_parameters = null;
1471           }
1472         ;
1473
1474 indexer_declarator
1475         : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1476           {
1477                 $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
1478           }
1479         | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1480           {
1481                 $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
1482           }
1483         ;
1484
1485 enum_declaration
1486         : opt_attributes
1487           opt_modifiers
1488           ENUM IDENTIFIER
1489           opt_enum_base
1490           enum_body
1491           opt_semicolon
1492           { 
1493                 string name = (string) $4;
1494                 Enum e = new Enum (rc, (string) $5, (int) $2, name, (Attributes) $1, lexer.Location);
1495
1496                 foreach (VariableDeclaration ev in (ArrayList) $6){
1497                         CheckDef (e.AddEnumMember (ev.identifier, 
1498                                                    (Expression) ev.expression_or_array_initializer,
1499                                                    (Location) ev.Location),
1500                                   ev.identifier);
1501                 }
1502
1503                 CheckDef (current_container.AddEnum (e), name);
1504           }
1505         ;
1506
1507 opt_enum_base
1508         : /* empty */           { $$ = "System.Int32"; }
1509         | COLON type            { $$ = $2;   }
1510         ;
1511
1512 enum_body
1513         : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1514           {
1515                 $$ = $2;
1516           }
1517         ;
1518
1519 opt_enum_member_declarations
1520         : /* empty */                   { $$ = new ArrayList (); }
1521         | enum_member_declarations opt_comma { $$ = $1; }
1522         ;
1523
1524 enum_member_declarations
1525         : enum_member_declaration 
1526           {
1527                 ArrayList l = new ArrayList ();
1528
1529                 l.Add ($1);
1530                 $$ = l;
1531           }
1532         | enum_member_declarations COMMA enum_member_declaration
1533           {
1534                 ArrayList l = (ArrayList) $1;
1535
1536                 l.Add ($3);
1537
1538                 $$ = l;
1539           }
1540         ;
1541
1542 enum_member_declaration
1543         : opt_attributes IDENTIFIER 
1544           {
1545                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
1546           }
1547         | opt_attributes IDENTIFIER
1548           {
1549                   $$ = lexer.Location;
1550           }
1551           ASSIGN expression
1552           { 
1553                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location);
1554           }
1555         ;
1556
1557 delegate_declaration
1558         : opt_attributes
1559           opt_modifiers
1560           DELEGATE type   
1561           IDENTIFIER OPEN_PARENS 
1562           formal_parameter_list
1563           CLOSE_PARENS 
1564           SEMICOLON
1565           {
1566                 Delegate del = new Delegate (rc, (string) $4, (int) $2, 
1567                                              MakeName ((string) $5), (Parameters) $7, 
1568                                              (Attributes) $1, lexer.Location);
1569                   
1570                 CheckDef (current_container.AddDelegate (del), del.Name);
1571           }     
1572         | opt_attributes
1573           opt_modifiers
1574           DELEGATE VOID   
1575           IDENTIFIER OPEN_PARENS 
1576           formal_parameter_list
1577           CLOSE_PARENS 
1578           SEMICOLON
1579           {
1580                 Delegate del = new Delegate (rc, "System.Void", (int) $2, (string) $5, (Parameters) $7, 
1581                                              (Attributes) $1, lexer.Location);
1582
1583                 CheckDef (current_container.AddDelegate (del), del.Name);
1584           }
1585         ;
1586
1587 type_name
1588         : namespace_or_type_name
1589         ;
1590
1591 namespace_or_type_name
1592         : qualified_identifier
1593         ;
1594
1595 /* 
1596  * Before you think of adding a return_type, notice that we have been
1597  * using two rules in the places where it matters (one rule using type
1598  * and another identical one that uses VOID as the return type).  This
1599  * gets rid of a shift/reduce couple
1600  */
1601 type
1602         : type_name {   /* class_type */
1603                 /* 
1604                    This does interfaces, delegates, struct_types, class_types, 
1605                    parent classes, and more! 4.2 
1606                  */
1607                 $$ = $1; 
1608           }
1609         | builtin_types
1610         | array_type
1611         ;
1612
1613 non_expression_type
1614         : builtin_types 
1615           {
1616                 $$ = new SimpleName ((string) $1, lexer.Location);
1617           }
1618         | non_expression_type rank_specifier
1619           {
1620                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1621           }
1622         | expression rank_specifiers 
1623           {
1624                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1625           }
1626         ;
1627
1628 type_list
1629         : type
1630           {
1631                 ArrayList types = new ArrayList ();
1632
1633                 types.Add ($1);
1634                 $$ = types;
1635           }
1636         | type_list COMMA type
1637           {
1638                 ArrayList types = (ArrayList) $1;
1639
1640                 types.Add ($3);
1641                 $$ = types;
1642           }
1643         ;
1644
1645 /*
1646  * replaces all the productions for isolating the various
1647  * simple types, but we need this to reuse it easily in local_variable_type
1648  */
1649 builtin_types
1650         : OBJECT        { $$ = "System.Object"; }
1651         | STRING        { $$ = "System.String"; }
1652         | BOOL          { $$ = "System.Boolean"; }
1653         | DECIMAL       { $$ = "System.Decimal"; }
1654         | FLOAT         { $$ = "System.Single"; }
1655         | DOUBLE        { $$ = "System.Double"; }
1656         | integral_type
1657         ;
1658
1659 integral_type
1660         : SBYTE         { $$ = "System.SByte"; }
1661         | BYTE          { $$ = "System.Byte"; }
1662         | SHORT         { $$ = "System.Int16"; }
1663         | USHORT        { $$ = "System.UInt16"; }
1664         | INT           { $$ = "System.Int32"; }
1665         | UINT          { $$ = "System.UInt32"; }
1666         | LONG          { $$ = "System.Int64"; }
1667         | ULONG         { $$ = "System.UInt64"; }
1668         | CHAR          { $$ = "System.Char"; }
1669         ;
1670
1671 interface_type
1672         : type_name
1673         ;
1674
1675 array_type
1676         : type rank_specifiers
1677           {
1678                   $$ = (string) $1 + (string) $2;
1679           }
1680         ;
1681
1682 //
1683 // Expressions, section 7.5
1684 //
1685 primary_expression
1686         : literal
1687           {
1688                 // 7.5.1: Literals
1689           }
1690  
1691         | qualified_identifier
1692           {
1693                 string name = (string) $1;
1694
1695                 $$ = null;
1696                 $$ = DecomposeQI (name, lexer.Location);
1697           }
1698         | parenthesized_expression
1699         | member_access
1700         | invocation_expression
1701         | element_access
1702         | this_access
1703         | base_access
1704         | post_increment_expression
1705         | post_decrement_expression
1706         | new_expression
1707         | typeof_expression
1708         | sizeof_expression
1709         | checked_expression
1710         | unchecked_expression
1711         ;
1712
1713 literal
1714         : boolean_literal
1715         | integer_literal
1716         | real_literal
1717         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
1718         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
1719         | NULL                  { $$ = new NullLiteral (); }
1720         ;
1721
1722 real_literal
1723         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
1724         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
1725         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1726         ;
1727
1728 integer_literal
1729         : LITERAL_INTEGER       { 
1730                 object v = lexer.Value;
1731
1732                 // 
1733                 // FIXME: Possible optimization would be to 
1734                 // compute the *Literal objects directly in the scanner
1735                 //
1736                 if (v is int)
1737                         $$ = new IntLiteral ((Int32) v); 
1738                 else if (v is uint)
1739                         $$ = new UIntLiteral ((UInt32) v);
1740                 else if (v is long)
1741                         $$ = new LongLiteral ((Int64) v);
1742                 else if (v is ulong)
1743                         $$ = new ULongLiteral ((UInt64) v);
1744                 else
1745                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
1746           }
1747         ;
1748
1749 boolean_literal
1750         : TRUE                  { $$ = new BoolLiteral (true); }
1751         | FALSE                 { $$ = new BoolLiteral (false); }
1752         ;
1753
1754 parenthesized_expression
1755         : OPEN_PARENS expression CLOSE_PARENS
1756           { $$ = $2; }
1757         ;
1758
1759 member_access
1760         : primary_expression DOT IDENTIFIER
1761           {
1762                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1763           }
1764         | predefined_type DOT IDENTIFIER
1765           {
1766                 $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
1767           }
1768         ;
1769
1770 predefined_type
1771         : builtin_types
1772         ;
1773
1774 invocation_expression
1775         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
1776           {
1777                 if ($1 == null) {
1778                         Location l = lexer.Location;
1779                         Report.Error (1, l, "THIS IS CRAZY");
1780                 }
1781                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
1782                 
1783           }
1784         ; 
1785
1786 opt_argument_list
1787         : /* empty */           { $$ = null; }
1788         | argument_list
1789         ;
1790
1791 argument_list
1792         : argument              
1793           { 
1794                 ArrayList list = new ArrayList ();
1795                 list.Add ($1);
1796                 $$ = list;
1797           }
1798         | argument_list COMMA argument
1799           {
1800                 ArrayList list = (ArrayList) $1;
1801                 list.Add ($3);
1802                 $$ = list;
1803           }
1804         ;
1805
1806 argument
1807         : expression
1808           {
1809                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
1810           }
1811         | REF variable_reference 
1812           { 
1813                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
1814           }
1815         | OUT variable_reference 
1816           { 
1817                 $$ = new Argument ((Expression) $2, Argument.AType.Out);
1818           }
1819         ;
1820
1821 variable_reference
1822         : expression { note ("section 5.4"); $$ = $1; }
1823         ;
1824
1825 element_access
1826         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
1827           {
1828                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
1829           }
1830         ;
1831
1832 expression_list
1833         : expression
1834           {
1835                 ArrayList list = new ArrayList ();
1836                 list.Add ($1);
1837                 $$ = list;
1838           }
1839         | expression_list COMMA expression
1840           {
1841                 ArrayList list = (ArrayList) $1;
1842                 list.Add ($3);
1843                 $$ = list;
1844           }
1845         ;
1846
1847 this_access
1848         : THIS
1849           {
1850                 $$ = new This (lexer.Location);
1851           }
1852         ;
1853
1854 base_access
1855         : BASE DOT IDENTIFIER
1856           {
1857                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);
1858           }
1859         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
1860           {
1861                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);
1862           }
1863         ;
1864
1865 post_increment_expression
1866         : primary_expression OP_INC
1867           {
1868                 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
1869                                        (Expression) $1, lexer.Location);
1870           }
1871         ;
1872
1873 post_decrement_expression
1874         : primary_expression OP_DEC
1875           {
1876                 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
1877                                        (Expression) $1, lexer.Location);
1878           }
1879         ;
1880
1881 new_expression
1882         : object_or_delegate_creation_expression
1883         | array_creation_expression
1884         ;
1885
1886 object_or_delegate_creation_expression
1887         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
1888           {
1889                 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
1890           }
1891         ;
1892
1893 array_creation_expression
1894         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
1895           opt_rank_specifier
1896           opt_array_initializer
1897           {
1898                 $$ = new ArrayCreation ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, 
1899                                         lexer.Location);
1900           }
1901         | NEW type rank_specifiers array_initializer
1902           {
1903                 $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
1904           }
1905         ;
1906
1907 opt_rank_specifier
1908         : /* empty */
1909           {
1910                   $$ = "";
1911           }
1912         | rank_specifiers
1913           {
1914                         $$ = $1;
1915           }
1916         ;
1917
1918 rank_specifiers
1919         : rank_specifier
1920           {
1921                   $$ = $1;
1922           }
1923         | rank_specifiers rank_specifier
1924           {
1925                   $$ = (string) $2 + (string) $1;
1926           }             
1927         ;
1928
1929 rank_specifier
1930         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
1931           {
1932                 $$ = "[" + (string) $2 + "]";
1933           }
1934         ;
1935
1936 opt_dim_separators
1937         : /* empty */
1938           {
1939                 $$ = "";
1940           }
1941         | dim_separators
1942           {
1943                   $$ = $1;
1944           }               
1945         ;
1946
1947 dim_separators
1948         : COMMA
1949           {
1950                 $$ = ",";
1951           }
1952         | dim_separators COMMA
1953           {
1954                 $$ = (string) $1 + ",";
1955           }
1956         ;
1957
1958 opt_array_initializer
1959         : /* empty */
1960           {
1961                 $$ = null;
1962           }
1963         | array_initializer
1964           {
1965                 $$ = $1;
1966           }
1967         ;
1968
1969 array_initializer
1970         : OPEN_BRACE CLOSE_BRACE
1971           {
1972                 ArrayList list = new ArrayList ();
1973                 $$ = list;
1974           }
1975         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
1976           {
1977                 $$ = (ArrayList) $2;
1978           }
1979         ;
1980
1981 variable_initializer_list
1982         : variable_initializer
1983           {
1984                 ArrayList list = new ArrayList ();
1985                 list.Add ($1);
1986                 $$ = list;
1987           }
1988         | variable_initializer_list COMMA variable_initializer
1989           {
1990                 ArrayList list = (ArrayList) $1;
1991                 list.Add ($3);
1992                 $$ = list;
1993           }
1994         ;
1995
1996 typeof_expression
1997         : TYPEOF OPEN_PARENS type CLOSE_PARENS
1998           {
1999                 $$ = new TypeOf ((string) $3);
2000           }
2001         ;
2002
2003 sizeof_expression
2004         : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
2005                 $$ = new SizeOf ((string) $3);
2006
2007                 note ("Verify type is unmanaged"); 
2008                 note ("if (5.8) builtin, yield constant expression");
2009           }
2010         ;
2011
2012 checked_expression
2013         : CHECKED OPEN_PARENS expression CLOSE_PARENS
2014           {
2015                 $$ = new CheckedExpr ((Expression) $3);
2016           }
2017         ;
2018
2019 unchecked_expression
2020         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2021           {
2022                 $$ = new UnCheckedExpr ((Expression) $3);
2023           }
2024         ;
2025
2026 unary_expression
2027         : primary_expression
2028         | BANG prefixed_unary_expression
2029           {
2030                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2031           }
2032         | TILDE prefixed_unary_expression
2033           {
2034                 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2035           }
2036         | OPEN_PARENS expression CLOSE_PARENS unary_expression
2037           {
2038                   $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2039           }
2040         | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2041           {
2042                   $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2043           }
2044         ;
2045
2046         //
2047         // The idea to split this out is from Rhys' grammar
2048         // to solve the problem with casts.
2049         //
2050 prefixed_unary_expression
2051         : unary_expression
2052         | PLUS prefixed_unary_expression
2053           { 
2054                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2055           } 
2056         | MINUS prefixed_unary_expression 
2057           { 
2058                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2059           }
2060         | OP_INC prefixed_unary_expression 
2061           {
2062                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2063                                        (Expression) $2, lexer.Location);
2064           }
2065         | OP_DEC prefixed_unary_expression 
2066           {
2067                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2068                                        (Expression) $2, lexer.Location);
2069           }
2070         | STAR prefixed_unary_expression
2071           {
2072                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2073           }
2074         | BITWISE_AND prefixed_unary_expression
2075           {
2076                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2077           }
2078         ;
2079
2080 pre_increment_expression
2081         : OP_INC prefixed_unary_expression 
2082           {
2083                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2084                                        (Expression) $2, lexer.Location);
2085           }
2086         ;
2087
2088 pre_decrement_expression
2089         : OP_DEC prefixed_unary_expression 
2090           {
2091                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2092                                        (Expression) $2, lexer.Location);
2093           }
2094         ;
2095
2096 multiplicative_expression
2097         : prefixed_unary_expression
2098         | multiplicative_expression STAR prefixed_unary_expression
2099           {
2100                 $$ = new Binary (Binary.Operator.Multiply, 
2101                                  (Expression) $1, (Expression) $3, lexer.Location);
2102           }
2103         | multiplicative_expression DIV prefixed_unary_expression
2104           {
2105                 $$ = new Binary (Binary.Operator.Division, 
2106                                  (Expression) $1, (Expression) $3, lexer.Location);
2107           }
2108         | multiplicative_expression PERCENT prefixed_unary_expression 
2109           {
2110                 $$ = new Binary (Binary.Operator.Modulus, 
2111                                  (Expression) $1, (Expression) $3, lexer.Location);
2112           }
2113         ;
2114
2115 additive_expression
2116         : multiplicative_expression
2117         | additive_expression PLUS multiplicative_expression 
2118           {
2119                 $$ = new Binary (Binary.Operator.Addition, 
2120                                  (Expression) $1, (Expression) $3, lexer.Location);
2121           }
2122         | additive_expression MINUS multiplicative_expression
2123           {
2124                 $$ = new Binary (Binary.Operator.Subtraction, 
2125                                  (Expression) $1, (Expression) $3, lexer.Location);
2126           }
2127         ;
2128
2129 shift_expression
2130         : additive_expression
2131         | shift_expression OP_SHIFT_LEFT additive_expression
2132           {
2133                 $$ = new Binary (Binary.Operator.LeftShift, 
2134                                  (Expression) $1, (Expression) $3, lexer.Location);
2135           }
2136         | shift_expression OP_SHIFT_RIGHT additive_expression
2137           {
2138                 $$ = new Binary (Binary.Operator.RightShift, 
2139                                  (Expression) $1, (Expression) $3, lexer.Location);
2140           }
2141         ; 
2142
2143 relational_expression
2144         : shift_expression
2145         | relational_expression OP_LT shift_expression
2146           {
2147                 $$ = new Binary (Binary.Operator.LessThan, 
2148                                  (Expression) $1, (Expression) $3, lexer.Location);
2149           }
2150         | relational_expression OP_GT shift_expression
2151           {
2152                 $$ = new Binary (Binary.Operator.GreaterThan, 
2153                                  (Expression) $1, (Expression) $3, lexer.Location);
2154           }
2155         | relational_expression OP_LE shift_expression
2156           {
2157                 $$ = new Binary (Binary.Operator.LessThanOrEqual, 
2158                                  (Expression) $1, (Expression) $3, lexer.Location);
2159           }
2160         | relational_expression OP_GE shift_expression
2161           {
2162                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
2163                                  (Expression) $1, (Expression) $3, lexer.Location);
2164           }
2165         | relational_expression IS type
2166           {
2167                 $$ = new Probe (Probe.Operator.Is, 
2168                                  (Expression) $1, (string) $3);
2169           }
2170         | relational_expression AS type
2171           {
2172                 $$ = new Probe (Probe.Operator.As, 
2173                                  (Expression) $1, (string) $3);
2174           }
2175         ;
2176
2177 equality_expression
2178         : relational_expression
2179         | equality_expression OP_EQ relational_expression
2180           {
2181                 $$ = new Binary (Binary.Operator.Equality, 
2182                                  (Expression) $1, (Expression) $3, lexer.Location);
2183           }
2184         | equality_expression OP_NE relational_expression
2185           {
2186                 $$ = new Binary (Binary.Operator.Inequality, 
2187                                  (Expression) $1, (Expression) $3, lexer.Location);
2188           }
2189         ; 
2190
2191 and_expression
2192         : equality_expression
2193         | and_expression BITWISE_AND equality_expression
2194           {
2195                 $$ = new Binary (Binary.Operator.BitwiseAnd, 
2196                                  (Expression) $1, (Expression) $3, lexer.Location);
2197           }
2198         ;
2199
2200 exclusive_or_expression
2201         : and_expression
2202         | exclusive_or_expression CARRET and_expression
2203           {
2204                 $$ = new Binary (Binary.Operator.ExclusiveOr, 
2205                                  (Expression) $1, (Expression) $3, lexer.Location);
2206           }
2207         ;
2208
2209 inclusive_or_expression
2210         : exclusive_or_expression
2211         | inclusive_or_expression BITWISE_OR exclusive_or_expression
2212           {
2213                 $$ = new Binary (Binary.Operator.BitwiseOr, 
2214                                  (Expression) $1, (Expression) $3, lexer.Location);
2215           }
2216         ;
2217
2218 conditional_and_expression
2219         : inclusive_or_expression
2220         | conditional_and_expression OP_AND inclusive_or_expression
2221           {
2222                 $$ = new Binary (Binary.Operator.LogicalAnd, 
2223                                  (Expression) $1, (Expression) $3, lexer.Location);
2224           }
2225         ;
2226
2227 conditional_or_expression
2228         : conditional_and_expression
2229         | conditional_or_expression OP_OR conditional_and_expression
2230           {
2231                 $$ = new Binary (Binary.Operator.LogicalOr, 
2232                                  (Expression) $1, (Expression) $3, lexer.Location);
2233           }
2234         ;
2235
2236 conditional_expression
2237         : conditional_or_expression
2238         | conditional_or_expression INTERR expression COLON expression 
2239           {
2240                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2241           }
2242         ;
2243
2244 assignment_expression
2245         : prefixed_unary_expression ASSIGN expression
2246           {
2247                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2248           }
2249         | prefixed_unary_expression OP_MULT_ASSIGN expression
2250           {
2251                 Location l = lexer.Location;
2252
2253                 $$ = new Assign ((Expression) $1,
2254                                  new Binary (Binary.Operator.Multiply, 
2255                                              (Expression) $1,
2256                                              (Expression) $3, l), l);
2257           }
2258         | prefixed_unary_expression OP_DIV_ASSIGN expression
2259           {
2260                 Location l = lexer.Location;
2261
2262                 $$ = new Assign ((Expression) $1,
2263                                  new Binary (Binary.Operator.Division, 
2264                                              (Expression) $1,
2265                                              (Expression) $3, l), l);
2266           }
2267         | prefixed_unary_expression OP_MOD_ASSIGN expression
2268           {
2269                 Location l = lexer.Location;
2270
2271                 $$ = new Assign ((Expression) $1,
2272                                  new Binary (Binary.Operator.Modulus, 
2273                                              (Expression) $1,
2274                                              (Expression) $3, l), l);
2275           }
2276         | prefixed_unary_expression OP_ADD_ASSIGN expression
2277           {
2278                 Location l = lexer.Location;
2279
2280                 $$ = new Assign ((Expression) $1,
2281                                  new Binary (Binary.Operator.Addition, 
2282                                              (Expression) $1,
2283                                              (Expression) $3, l), l);
2284           }
2285         | prefixed_unary_expression OP_SUB_ASSIGN expression
2286           {
2287                 Location l = lexer.Location;
2288
2289                 $$ = new Assign ((Expression) $1,
2290                                  new Binary (Binary.Operator.Subtraction, 
2291                                              (Expression) $1,
2292                                              (Expression) $3, l), l);
2293           }
2294         | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2295           {
2296                 Location l = lexer.Location;
2297
2298                 $$ = new Assign ((Expression) $1,
2299                                  new Binary (Binary.Operator.LeftShift, 
2300                                              (Expression) $1,
2301                                              (Expression) $3, l), l);
2302           }
2303         | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2304           {
2305                 Location l = lexer.Location;
2306
2307                 $$ = new Assign ((Expression) $1,
2308                                  new Binary (Binary.Operator.RightShift, 
2309                                              (Expression) $1,
2310                                              (Expression) $3, l), l);
2311           }
2312         | prefixed_unary_expression OP_AND_ASSIGN expression
2313           {
2314                 Location l = lexer.Location;
2315
2316                 $$ = new Assign ((Expression) $1,
2317                                  new Binary (Binary.Operator.BitwiseAnd, 
2318                                              (Expression) $1,
2319                                              (Expression) $3, l), l);
2320           }
2321         | prefixed_unary_expression OP_OR_ASSIGN expression
2322           {
2323                 Location l = lexer.Location;
2324
2325                 $$ = new Assign ((Expression) $1,
2326                                  new Binary (Binary.Operator.BitwiseOr, 
2327                                              (Expression) $1,
2328                                              (Expression) $3, l), l);
2329           }
2330         | prefixed_unary_expression OP_XOR_ASSIGN expression
2331           {
2332                 Location l = lexer.Location;
2333
2334                 $$ = new Assign ((Expression) $1,
2335                                  new Binary (Binary.Operator.ExclusiveOr, 
2336                                              (Expression) $1,
2337                                              (Expression) $3, l), l);
2338           }
2339         ;
2340
2341 expression
2342         : conditional_expression
2343         | assignment_expression
2344         ;
2345
2346 constant_expression
2347         : expression
2348         ;
2349
2350 boolean_expression
2351         : expression
2352         ;
2353
2354 //
2355 // 10 classes
2356 //
2357 class_declaration
2358         : opt_attributes
2359           opt_modifiers
2360           CLASS IDENTIFIER
2361           {
2362                 Class new_class;
2363                 string full_class_name = MakeName ((string) $4);
2364
2365                 new_class = new Class (rc, current_container, full_class_name, (int) $2, 
2366                                        (Attributes) $1, lexer.Location);
2367                 current_container = new_class;
2368                 current_container.Namespace = current_namespace;
2369                 tree.RecordClass (full_class_name, new_class);
2370           }
2371           opt_class_base
2372           class_body 
2373           opt_semicolon 
2374           {
2375                 Class new_class = (Class) current_container;
2376
2377                 if ($6 != null)
2378                         new_class.Bases = (ArrayList) $6;
2379
2380                 current_container = current_container.Parent;
2381                 CheckDef (current_container.AddClass (new_class), new_class.Name);
2382
2383                 $$ = new_class;
2384           }
2385         ;       
2386
2387 opt_modifiers
2388         : /* empty */           { $$ = (int) 0; }
2389         | modifiers
2390         ;
2391
2392 modifiers
2393         : modifier
2394         | modifiers modifier
2395           { 
2396                 int m1 = (int) $1;
2397                 int m2 = (int) $2;
2398
2399                 if ((m1 & m2) != 0) {
2400                         Location l = lexer.Location;
2401                         Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2402                 }
2403                 $$ = (int) (m1 | m2);
2404           }
2405         ;
2406
2407 modifier
2408         : NEW                   { $$ = Modifiers.NEW; }
2409         | PUBLIC                { $$ = Modifiers.PUBLIC; }
2410         | PROTECTED             { $$ = Modifiers.PROTECTED; }
2411         | INTERNAL              { $$ = Modifiers.INTERNAL; }
2412         | PRIVATE               { $$ = Modifiers.PRIVATE; }
2413         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
2414         | SEALED                { $$ = Modifiers.SEALED; }
2415         | STATIC                { $$ = Modifiers.STATIC; }
2416         | READONLY              { $$ = Modifiers.READONLY; }
2417         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
2418         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
2419         | EXTERN                { $$ = Modifiers.EXTERN; }
2420         ;
2421
2422 opt_class_base
2423         : /* empty */           { $$ = null; }
2424         | class_base            { $$ = $1;   }
2425         ;
2426
2427 class_base
2428         : COLON type_list { $$ = $2; }
2429         ;
2430
2431 //
2432 // Statements (8.2)
2433 //
2434
2435 //
2436 // A block is "contained" on the following places:
2437 //      method_body
2438 //      property_declaration as part of the accessor body (get/set)
2439 //      operator_declaration
2440 //      constructor_declaration
2441 //      destructor_declaration
2442 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2443 //      
2444 block
2445         : OPEN_BRACE 
2446           {
2447                 current_block = new Block (current_block);
2448           } 
2449           opt_statement_list CLOSE_BRACE 
2450           { 
2451                 while (current_block.Implicit)
2452                         current_block = current_block.Parent;
2453                 $$ = current_block;
2454                 current_block = current_block.Parent;
2455           }
2456         ;
2457
2458 opt_statement_list
2459         : /* empty */
2460         | statement_list 
2461         ;
2462
2463 statement_list
2464         : statement
2465         | statement_list statement
2466         ;
2467
2468 statement
2469         : declaration_statement
2470           {
2471                 if ((Block) $1 != current_block){
2472                         current_block.AddStatement ((Statement) $1);
2473                         current_block = (Block) $1;
2474                 }
2475           }
2476         | embedded_statement
2477           {
2478                 Statement s = (Statement) $1;
2479
2480
2481                 current_block.AddStatement ((Statement) $1);
2482           }
2483         | labeled_statement 
2484           {
2485                 current_block.AddStatement ((Statement) $1);
2486           }
2487         ;
2488
2489 embedded_statement
2490         : block
2491         | empty_statement
2492         | expression_statement
2493         | selection_statement
2494         | iteration_statement
2495         | jump_statement                  
2496         | try_statement
2497         | checked_statement
2498         | unchecked_statement
2499         | lock_statement
2500         | using_statement
2501         ;
2502
2503 empty_statement
2504         : SEMICOLON
2505           {
2506                   $$ = new EmptyStatement ();
2507           }
2508         ;
2509
2510 labeled_statement
2511         : IDENTIFIER COLON statement
2512           {
2513                 string lab = (String) $1;
2514                 Block block;
2515
2516                 block = new Block (current_block, lab);
2517                 block.AddStatement ((Statement) $3);
2518                 $$ = block;
2519
2520                 if (!current_block.AddLabel (lab, block)){
2521                         Location l = lexer.Location;
2522                         Report.Error (140, l, "The label '" + lab + "' is a duplicate");
2523                         $$ = $3;
2524                 }       
2525           }
2526         ;
2527
2528 declaration_statement
2529         : local_variable_declaration SEMICOLON
2530           {
2531                 DictionaryEntry de = (DictionaryEntry) $1;
2532
2533                 $$ = declare_local_variables ((string) de.Key, (ArrayList) de.Value);
2534           }
2535
2536         | local_constant_declaration SEMICOLON          // finishme
2537         ;
2538
2539 /* 
2540  * The following is from Rhys' grammar:
2541  * > Types in local variable declarations must be recognized as 
2542  * > expressions to prevent reduce/reduce errors in the grammar.
2543  * > The expressions are converted into types during semantic analysis.
2544  */
2545 local_variable_type
2546         : primary_expression opt_rank_specifier
2547           { 
2548                 // FIXME: Do something smart here regarding the composition of the type.
2549
2550                 // Ok, the above "primary_expression" is there to get rid of
2551                 // both reduce/reduce and shift/reduces in the grammar, it should
2552                 // really just be "type_name".  If you use type_name, a reduce/reduce
2553                 // creeps up.  If you use qualified_identifier (which is all we need
2554                 // really) two shift/reduces appear.
2555                 // 
2556
2557                 // So the super-trick is that primary_expression
2558                 // can only be either a SimpleName or a MemberAccess. 
2559                 // The MemberAccess case arises when you have a fully qualified type-name like :
2560                 // Foo.Bar.Blah i;
2561                 // SimpleName is when you have
2562                 // Blah i;
2563                   
2564                 Expression expr = (Expression) $1;  
2565                 if (!(expr is SimpleName || expr is MemberAccess)) {
2566                         Location l = lexer.Location;
2567                         Report.Error (-1, l, "Invalid Type definition");
2568                         $$ = "System.Object";
2569                 }
2570                 
2571                 //
2572                 // So we extract the string corresponding to the SimpleName
2573                 // or MemberAccess
2574                 // 
2575                 $$ = GetQualifiedIdentifier (expr) + (string) $2;
2576           }
2577         | builtin_types opt_rank_specifier
2578           {
2579                   $$ = (string) $1 + (string) $2;
2580           }
2581         ;
2582
2583 // FIXME : How can the type of a local variable be void ? I don't quite see ;-)
2584 //          | VOID 
2585 //        {
2586 //              // FIXME: this is a string that represents the type
2587 //              // Figure out something to make this work.
2588 //              $$ = "void";
2589 //        }
2590 //      ;
2591
2592 local_variable_declaration
2593         : local_variable_type variable_declarators
2594           {
2595                 $$ = new DictionaryEntry ($1, $2);
2596           }
2597         ;
2598
2599 local_constant_declaration
2600         : CONST type constant_declarator
2601                 // finishme     
2602         ;
2603
2604 expression_statement
2605         : statement_expression SEMICOLON
2606           {
2607                 $$ = $1;
2608           }
2609         ;
2610
2611         //
2612         // We have to do the wrapping here and not in the case above,
2613         // because statement_expression is used for example in for_statement
2614         //
2615 statement_expression
2616         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2617         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1); }
2618         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2619         | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2620         | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2621         | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2622         | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2623         ;
2624
2625 object_creation_expression
2626         : object_or_delegate_creation_expression
2627           { note ("complain if this is a delegate maybe?"); } 
2628         ;
2629
2630 selection_statement
2631         : if_statement
2632         | switch_statement
2633         ; 
2634
2635 if_statement
2636         : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
2637           embedded_statement
2638           { 
2639                 $$ = new If ((Expression) $3, (Statement) $5);
2640           }
2641         | IF OPEN_PARENS boolean_expression CLOSE_PARENS
2642           embedded_statement ELSE embedded_statement
2643           {
2644                 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
2645           }
2646         ;
2647
2648 switch_statement
2649         : SWITCH OPEN_PARENS 
2650           { 
2651                 oob_stack.Push (lexer.Location);
2652           }
2653           expression CLOSE_PARENS 
2654           switch_block
2655           {
2656                 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
2657           }
2658         ;
2659
2660 switch_block
2661         : OPEN_BRACE
2662           opt_switch_sections
2663           CLOSE_BRACE
2664           {
2665                 $$ = $2;
2666           }
2667         ;
2668
2669 opt_switch_sections
2670         : /* empty */           { $$ = new ArrayList (); }
2671         | switch_sections
2672         ;
2673
2674 switch_sections
2675         : switch_section 
2676           {
2677                 ArrayList sections = new ArrayList ();
2678
2679                 sections.Add ($1);
2680                 $$ = sections;
2681           }
2682         | switch_sections switch_section
2683           {
2684                 ArrayList sections = (ArrayList) $1;
2685
2686                 sections.Add ($2);
2687                 $$ = sections;
2688           }
2689         ;
2690
2691 switch_section
2692         : switch_labels
2693           {
2694                 current_block = new Block (current_block);
2695           }
2696           statement_list 
2697           {
2698                 while (current_block.Implicit)
2699                         current_block = current_block.Parent;
2700                 $$ = new SwitchSection ((ArrayList) $1, current_block);
2701                 current_block = current_block.Parent;
2702           }
2703         ;
2704
2705 switch_labels
2706         : switch_label 
2707           {
2708                 ArrayList labels = new ArrayList ();
2709
2710                 labels.Add ($1);
2711                 $$ = labels;
2712           }
2713         | switch_labels switch_label 
2714           {
2715                 ArrayList labels = (ArrayList) ($1);
2716                 labels.Add ($2);
2717
2718                 $$ = labels;
2719           }
2720         ;
2721
2722 switch_label
2723         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
2724         | DEFAULT COLON                         { $$ = new SwitchLabel (null, lexer.Location); }
2725         ;
2726
2727 iteration_statement
2728         : while_statement
2729         | do_statement
2730         | for_statement
2731         | foreach_statement
2732         ;
2733
2734 while_statement
2735         : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
2736         {
2737                 $$ = new While ((Expression) $3, (Statement) $5);
2738         }
2739         ;
2740
2741 do_statement
2742         : DO embedded_statement 
2743           WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
2744           {
2745                 $$ = new Do ((Statement) $2, (Expression) $5);
2746           }
2747         ;
2748
2749 for_statement
2750         : FOR OPEN_PARENS 
2751           opt_for_initializer SEMICOLON
2752           {
2753                 Block assign_block = new Block (current_block);
2754                 current_block = assign_block;
2755
2756                 if ($3 is DictionaryEntry){
2757                         DictionaryEntry de = (DictionaryEntry) $3;
2758                         $3 = null;
2759                         
2760                         string type = (string) de.Key;
2761                         ArrayList var_declarators = (ArrayList) de.Value;
2762
2763                         foreach (VariableDeclaration decl in var_declarators){
2764                                 if (!current_block.AddVariable (type, decl.identifier, decl.Location)){
2765                                         Report.Error (128, decl.Location, 
2766                                         "A local variable `" + decl.identifier + "' is already" +
2767                                         "defined in this scope");
2768                                 }
2769                         }
2770
2771                         foreach (VariableDeclaration decl in var_declarators){
2772
2773                                 Expression expr;
2774                                 if (decl.expression_or_array_initializer is Expression){
2775                                         expr = (Expression) decl.expression_or_array_initializer;
2776                                         
2777                                 } else {
2778
2779                                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
2780                                         
2781                                         string base_type = type.Substring (0, type.IndexOf ("["));
2782                                         string rank = type.Substring (type.IndexOf ("["));
2783                                         
2784                                         expr = new ArrayCreation (base_type, rank, init, decl.Location);
2785                                 }
2786
2787                                 Assign a = new Assign (new LocalVariableReference (assign_block, decl.identifier),
2788                                                        expr, decl.Location);
2789                                 
2790                                 assign_block.AddStatement (new StatementExpression (a));
2791                         }
2792                         $3 = null;
2793                 } 
2794           } 
2795           opt_for_condition SEMICOLON
2796           opt_for_iterator CLOSE_PARENS 
2797           embedded_statement
2798           {
2799                 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10);
2800
2801                 current_block.AddStatement (f);
2802                 while (current_block.Implicit)
2803                         current_block = current_block.Parent;
2804                 $$ = current_block;
2805                 current_block = current_block.Parent;
2806           }
2807         ;
2808
2809 opt_for_initializer
2810         : /* empty */           { $$ = new EmptyStatement (); }
2811         | for_initializer       
2812         ;
2813
2814 for_initializer
2815         : local_variable_declaration
2816         | statement_expression_list
2817         ;
2818
2819 opt_for_condition
2820         : /* empty */           { $$ = new BoolLiteral (true); }
2821         | boolean_expression
2822         ;
2823
2824 opt_for_iterator
2825         : /* empty */           { $$ = new EmptyStatement (); }
2826         | for_iterator
2827         ;
2828
2829 for_iterator
2830         : statement_expression_list
2831         ;
2832
2833 statement_expression_list
2834         : statement_expression  
2835           {
2836                 Block b = new Block (null, true);
2837
2838                 b.AddStatement ((Statement) $1);
2839                 $$ = b;
2840           }
2841         | statement_expression_list COMMA statement_expression
2842           {
2843                 Block b = (Block) $1;
2844
2845                 b.AddStatement ((Statement) $3);
2846                 $$ = $1;
2847           }
2848         ;
2849
2850 foreach_statement
2851         : FOREACH OPEN_PARENS type IDENTIFIER IN 
2852           {
2853                 oob_stack.Push (lexer.Location);
2854           }
2855           expression CLOSE_PARENS 
2856           {
2857                 Block foreach_block = new Block (current_block, true);
2858                 LocalVariableReference v;
2859
2860                 foreach_block.AddVariable ((string) $3, (string) $4, lexer.Location);
2861                 v = new LocalVariableReference (foreach_block, (string) $4);
2862
2863                 current_block.AddStatement (foreach_block);
2864                 current_block = foreach_block;
2865
2866                 oob_stack.Push (foreach_block);
2867                 oob_stack.Push (v);
2868           } 
2869           embedded_statement 
2870           {
2871                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2872                 Block foreach_block = (Block) oob_stack.Pop ();
2873                 Location l = (Location) oob_stack.Pop ();
2874
2875                 $$ = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
2876           }
2877         ;
2878
2879 jump_statement
2880         : break_statement
2881         | continue_statement
2882         | goto_statement
2883         | return_statement
2884         | throw_statement
2885         ;
2886
2887 break_statement
2888         : BREAK SEMICOLON
2889           {
2890                 $$ = new Break (lexer.Location);
2891           }
2892         ;
2893
2894 continue_statement
2895         : CONTINUE SEMICOLON
2896           {
2897                 $$ = new Continue (lexer.Location);
2898           }
2899         ;
2900
2901 goto_statement
2902         : GOTO IDENTIFIER SEMICOLON 
2903           {
2904                 $$ = new Goto ((string) $2, lexer.Location);
2905           }
2906         | GOTO CASE constant_expression SEMICOLON
2907           {
2908                 // FIXME
2909           }
2910         | GOTO DEFAULT SEMICOLON 
2911           {
2912                 // FIXME
2913           }
2914         ; 
2915
2916 return_statement
2917         : RETURN opt_expression SEMICOLON
2918           {
2919                 $$ = new Return ((Expression) $2, lexer.Location);
2920           }
2921         ;
2922
2923 throw_statement
2924         : THROW opt_expression SEMICOLON
2925           {
2926                 $$ = new Throw ((Expression) $2);
2927           }
2928         ;
2929
2930 opt_expression
2931         : /* empty */
2932         | expression
2933         ;
2934
2935 try_statement
2936         : TRY block catch_clauses 
2937         {
2938                 Catch g = null;
2939                 ArrayList s = new ArrayList ();
2940                 
2941                 foreach (Catch cc in (ArrayList) $3) {
2942                         if (cc.Type == null)
2943                                 g = cc;
2944                         else
2945                                 s.Add (cc);
2946                 }
2947
2948                 // Now s contains the list of specific catch clauses
2949                 // and g contains the general one.
2950                 
2951                 $$ = new Try ((Block) $2, s, g, null);
2952         }
2953         | TRY block opt_catch_clauses FINALLY block
2954           {
2955                 Catch g = null;
2956                 ArrayList s = new ArrayList ();
2957                 
2958                 foreach (Catch cc in (ArrayList) $3) {
2959                         if (cc.Type == null)
2960                                 g = cc;
2961                         else
2962                                 s.Add (cc);
2963                 }
2964
2965                 $$ = new Try ((Block) $2, s, g, (Block) $5);
2966           }
2967         ;
2968
2969 opt_catch_clauses
2970         : /* empty */  { $$ = null; }
2971         | catch_clauses
2972         ;
2973
2974 catch_clauses
2975         : catch_clause 
2976           {
2977                 ArrayList l = new ArrayList ();
2978
2979                 l.Add ($1);
2980                 $$ = l;
2981           }
2982         | catch_clauses catch_clause
2983           {
2984                 ArrayList l = (ArrayList) $1;
2985
2986                 l.Add ($2);
2987                 $$ = l;
2988           }
2989         ;
2990
2991 opt_identifier
2992         : /* empty */   { $$ = null; }
2993         | IDENTIFIER
2994         ;
2995
2996 catch_clause 
2997         : CATCH opt_catch_args 
2998         {
2999                 string type = null, id = null;
3000                 
3001                 if ($2 != null) {
3002                         DictionaryEntry cc = (DictionaryEntry) $2;
3003                         type = (string) cc.Key;
3004                         id   = (string) cc.Value;
3005
3006                         if (id != null){
3007                                 ArrayList one = new ArrayList ();
3008                                 one.Add (new VariableDeclaration (id, null, lexer.Location));
3009
3010                                 $1 = current_block;
3011                                 current_block = new Block (current_block);
3012                                 Block b = declare_local_variables (type, one);
3013                                 current_block = b;
3014
3015                                 
3016                         }
3017                 }
3018         } block {
3019                 string type = null, id = null;
3020
3021                 if ($2 != null){
3022                         DictionaryEntry cc = (DictionaryEntry) $2;
3023                         type = (string) cc.Key;
3024                         id   = (string) cc.Value;
3025
3026                         if ($1 != null){
3027                                 while (current_block != (Block) $1)
3028                                         current_block = current_block.Parent;
3029                         }
3030                 }
3031
3032
3033                 $$ = new Catch (type, id , (Block) $4);
3034         }
3035         ;
3036
3037 opt_catch_args
3038         : /* empty */ { $$ = null; }
3039         | catch_args
3040         ;         
3041
3042 catch_args 
3043         : OPEN_PARENS type opt_identifier CLOSE_PARENS 
3044         {
3045                 $$ = new DictionaryEntry ($2, $3);
3046         }
3047         ;
3048
3049 checked_statement
3050         : CHECKED block
3051           {
3052                 $$ = new Checked ((Block) $2);
3053           }
3054         ;
3055
3056 unchecked_statement
3057         : UNCHECKED block
3058           {
3059                 $$ = new Unchecked ((Block) $2);
3060           }
3061         ;
3062
3063 lock_statement
3064         : LOCK OPEN_PARENS expression CLOSE_PARENS 
3065           {
3066                 //
3067           } 
3068           embedded_statement
3069           {
3070                 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3071           }
3072         ;
3073
3074 using_statement
3075         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
3076           {
3077           } 
3078           embedded_statement
3079           {
3080                 $$ = new Using ($3, (Statement) $6, lexer.Location);
3081           }
3082         ; 
3083
3084 resource_acquisition
3085         : local_variable_declaration
3086           {
3087                 if ((Block) $1 != current_block){
3088                         current_block.AddStatement ((Statement) $1);
3089                         current_block = (Block) $1;
3090                 }
3091           }
3092         | expression
3093         ;
3094
3095 %%
3096
3097 // <summary>
3098 //   A class used to pass around variable declarations and constants
3099 // </summary>
3100 public class VariableDeclaration {
3101         public string identifier;
3102         public object expression_or_array_initializer;
3103         public Location Location;
3104
3105         public VariableDeclaration (string id, object eoai, Location l){
3106                 this.identifier = id;
3107                 this.expression_or_array_initializer = eoai;
3108                 this.Location = l;
3109         }
3110 }
3111
3112 // <summary>
3113 //   A class used to hold info about an indexer declarator
3114 // </summary>
3115
3116 public class IndexerDeclaration {
3117         public string type;
3118         public string interface_type;
3119         public Parameters param_list;
3120
3121         public IndexerDeclaration (string type, string interface_type, Parameters param_list)
3122         {
3123                 this.type = type;
3124                 this.interface_type = interface_type;
3125                 this.param_list = param_list;
3126         }
3127 }
3128
3129 // <summary>
3130 //  A class used to hold info about an operator declarator
3131 // </summary>
3132
3133 public class OperatorDeclaration {
3134         public Operator.OpType optype;
3135         public string ret_type;
3136         public string arg1type;
3137         public string arg1name;
3138         public string arg2type;
3139         public string arg2name;
3140         public Location location;
3141
3142         public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
3143                                     string arg2type, string arg2name, Location location)
3144         {
3145                 optype = op;
3146                 this.ret_type = ret_type;
3147                 this.arg1type = arg1type;
3148                 this.arg1name = arg1name;
3149                 this.arg2type = arg2type;
3150                 this.arg2name = arg2name;
3151                 this.location = location;
3152         }
3153
3154 }
3155
3156 // <summary>
3157 //   Given the @class_name name, it creates a fully qualified name
3158 //   based on the containing declaration space
3159 // </summary>
3160 string 
3161 MakeName (string class_name)
3162 {
3163         string ns = current_namespace.Name;
3164         string container_name = current_container.Name;
3165
3166         if (container_name == ""){
3167                 if (ns != "")
3168                         return ns + "." + class_name;
3169                 else
3170                         return class_name;
3171         } else
3172                 return container_name + "." + class_name;
3173 }
3174
3175 // <summary>
3176 //   Used to report back to the user the result of a declaration
3177 //   in the current declaration space
3178 // </summary>
3179 void 
3180 CheckDef (DeclSpace.AdditionResult result, string name)
3181 {
3182         if (result == DeclSpace.AdditionResult.Success)
3183                 return;
3184
3185         Location l = lexer.Location;
3186         
3187         switch (result){
3188         case DeclSpace.AdditionResult.NameExists:
3189                 Report.Error (102, l, "The namespace `" + current_container.Name + 
3190                                  "' already contains a definition for `"+
3191                                  name + "'");
3192                 break;
3193
3194
3195 //      NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
3196 //
3197 //      case DeclSpace.AdditionResult.MethodDuplicated:
3198 //              error (111, "Class `"+current_container.Name+
3199 //                          "' already defines a member called '" + 
3200 //                          name + "' with the same parameter types");
3201 //              break;
3202
3203         case DeclSpace.AdditionResult.EnclosingClash:
3204                 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
3205                 break;
3206                 
3207         case DeclSpace.AdditionResult.NotAConstructor:
3208                 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
3209                 break;
3210         }
3211 }
3212
3213 void 
3214 CheckDef (bool result, string name)
3215 {
3216         if (result)
3217                 return;
3218         CheckDef (DeclSpace.AdditionResult.NameExists, name);
3219 }
3220
3221 Expression
3222 SimpleLookup (string name)
3223 {
3224         //
3225         // we need to check against current_block not being null
3226         // as `expression' is allowed in argument_lists, which 
3227         // do not exist inside a block.  
3228         //
3229         if (current_block != null){
3230                 if (current_block.IsVariableDefined (name))
3231                         return new LocalVariableReference (current_block, name);
3232         }
3233
3234         if (current_local_parameters != null){
3235                 int idx;
3236                 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
3237                 if (par != null)
3238                         return new ParameterReference (current_local_parameters, idx, name);
3239         }
3240
3241         return null;
3242 }
3243
3244 Expression DecomposeQI (string name, Location l)
3245 {
3246         Expression o;
3247
3248         if (name.IndexOf ('.') == -1){
3249                 o = SimpleLookup (name);
3250                 if (o == null)
3251                         return new SimpleName (name, l);
3252                 return o;
3253         } else {
3254                 int pos = name.LastIndexOf (".");
3255                 string left = name.Substring (0, pos);
3256                 string right = name.Substring (pos + 1);
3257
3258                 o = DecomposeQI (left, l);
3259                 return new MemberAccess (o, right, l);
3260         }
3261 }
3262
3263 // <summary>
3264 //  This method is used to get at the complete string representation of
3265 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
3266 //  This is necessary because local_variable_type admits primary_expression
3267 //  as the type of the variable. So we do some extra checking
3268 // </summary>
3269 string GetQualifiedIdentifier (Expression expr)
3270 {
3271         if (expr is SimpleName)
3272                 return ((SimpleName)expr).Name;
3273         else if (expr is MemberAccess)
3274                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3275         else 
3276                 throw new Exception ("Expr has to be either SimpleName or MemberAccess !");
3277         
3278 }
3279
3280 Block declare_local_variables (string type, ArrayList variable_declarators)
3281 {
3282         Block implicit_block;
3283         ArrayList inits = null;
3284
3285         //
3286         // We use the `Used' property to check whether statements
3287         // have been added to the current block.  If so, we need
3288         // to create another block to contain the new declaration
3289         // otherwise, as an optimization, we use the same block to
3290         // add the declaration.
3291         //
3292         // FIXME: A further optimization is to check if the statements
3293         // that were added were added as part of the initialization
3294         // below.  In which case, no other statements have been executed
3295         // and we might be able to reduce the number of blocks for
3296         // situations like this:
3297         //
3298         // int j = 1;  int k = j + 1;
3299         //
3300         if (current_block.Used)
3301                 implicit_block = new Block (current_block, true);
3302         else
3303                 implicit_block = current_block;
3304
3305         foreach (VariableDeclaration decl in variable_declarators){
3306                 if (implicit_block.AddVariable (type, decl.identifier, decl.Location)){
3307                         if (decl.expression_or_array_initializer != null){
3308                                 if (inits == null)
3309                                         inits = new ArrayList ();
3310                                 inits.Add (decl);
3311                         }
3312                 } else {
3313                         Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3314                                          "' is already defined in this scope");
3315                 }
3316         }
3317
3318         if (inits == null)
3319                 return implicit_block;
3320
3321         foreach (VariableDeclaration decl in inits){
3322                 Assign assign;
3323                 Expression expr;
3324                 
3325                 if (decl.expression_or_array_initializer is Expression){
3326                         expr = (Expression) decl.expression_or_array_initializer;
3327
3328                 } else {
3329                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3330                         
3331                         string base_type = type.Substring (0, type.IndexOf ("["));
3332                         string rank = type.Substring (type.IndexOf ("["));
3333
3334                         expr = new ArrayCreation (base_type, rank, init, decl.Location);
3335                         
3336                 }
3337
3338                 assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr, decl.Location);
3339                 implicit_block.AddStatement (new StatementExpression (assign));
3340         }
3341         
3342         return implicit_block;
3343 }
3344
3345 void CheckAttributeTarget (string a)
3346 {
3347         switch (a) {
3348
3349         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3350                 return;
3351                 
3352         default :
3353                 Location l = lexer.Location;
3354                 Report.Error (658, l, "Invalid attribute target");
3355                 break;
3356         }
3357
3358 }
3359
3360 void CheckUnaryOperator (Operator.OpType op)
3361 {
3362         switch (op) {
3363                 
3364         case Operator.OpType.LogicalNot: 
3365         case Operator.OpType.OnesComplement: 
3366         case Operator.OpType.Increment:
3367         case Operator.OpType.Decrement:
3368         case Operator.OpType.True: 
3369         case Operator.OpType.False: 
3370         case Operator.OpType.Addition: 
3371         case Operator.OpType.Subtraction:
3372                 
3373                 break;
3374                 
3375         default :
3376                 Location l = lexer.Location;
3377                 Report.Error (1019, l, "Overloadable unary operator expected"); 
3378                 break;
3379                 
3380         }
3381 }
3382
3383 void CheckBinaryOperator (Operator.OpType op)
3384 {
3385         switch (op) {
3386                 
3387         case Operator.OpType.Addition: 
3388         case Operator.OpType.Subtraction: 
3389         case Operator.OpType.Multiply:
3390         case Operator.OpType.Division:
3391         case Operator.OpType.Modulus: 
3392         case Operator.OpType.BitwiseAnd: 
3393         case Operator.OpType.BitwiseOr:
3394         case Operator.OpType.ExclusiveOr: 
3395         case Operator.OpType.LeftShift: 
3396         case Operator.OpType.RightShift:
3397         case Operator.OpType.Equality: 
3398         case Operator.OpType.Inequality:
3399         case Operator.OpType.GreaterThan: 
3400         case Operator.OpType.LessThan: 
3401         case Operator.OpType.GreaterThanOrEqual:
3402         case Operator.OpType.LessThanOrEqual:
3403                 break;
3404                 
3405         default :
3406                 Location l = lexer.Location;
3407                 Report.Error (1020, l, "Overloadable binary operator expected");
3408                 break;
3409         }
3410         
3411 }
3412
3413 void syntax_error (Location l, string msg)
3414 {
3415         Report.Error (1003, l, "Syntax error, " + msg);
3416 }
3417
3418 void output (string s)
3419 {
3420         Console.WriteLine (s);
3421 }
3422
3423 void note (string s)
3424 {
3425         // Used to put annotations
3426 }
3427
3428 Tokenizer lexer;
3429
3430 public Tokenizer Lexer {
3431         get {
3432                 return lexer;
3433         }
3434 }                  
3435
3436 public CSharpParser(RootContext rc, string name, System.IO.Stream input)
3437 {
3438         current_namespace = new Namespace (null, "");
3439         this.rc = rc;
3440         this.tree = rc.Tree;
3441         this.name = name;
3442         this.input = input;
3443         current_container = tree.Types;
3444         current_container.Namespace = current_namespace;
3445         oob_stack = new Stack ();
3446
3447         lexer = new Tokenizer (input, name);
3448 }
3449
3450 public override int parse ()
3451 {
3452         StringBuilder value = new StringBuilder ();
3453
3454         global_errors = 0;
3455         try {
3456                 if (yacc_verbose_flag)
3457                         yyparse (lexer, new yydebug.yyDebugSimple ());
3458                 else
3459                         yyparse (lexer);
3460         } catch (Exception e){
3461                 // Console.WriteLine ("Fatal error: " + name);
3462                 // Console.WriteLine (lexer.location);
3463
3464                 // 
3465                 // Please do not remove this, it is used during debugging
3466                 // of the grammar
3467                 //
3468                 Console.WriteLine (lexer.location + "  : Parsing error ");
3469                 Console.WriteLine (e);
3470                 global_errors++;
3471         }
3472         
3473         return global_errors;
3474 }
3475
3476
3477 /* end end end */
3478 }