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