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