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