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