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