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