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