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