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