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