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