2002-01-24 Miguel de Icaza <miguel@ximian.com>
[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         ;
1826
1827 literal
1828         : boolean_literal
1829         | integer_literal
1830         | real_literal
1831         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
1832         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
1833         | NULL                  { $$ = NullLiteral.Null; }
1834         ;
1835
1836 real_literal
1837         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
1838         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
1839         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1840         ;
1841
1842 integer_literal
1843         : LITERAL_INTEGER       { 
1844                 object v = lexer.Value;
1845
1846                 // 
1847                 // FIXME: Possible optimization would be to 
1848                 // compute the *Literal objects directly in the scanner
1849                 //
1850                 if (v is int)
1851                         $$ = new IntLiteral ((Int32) v); 
1852                 else if (v is uint)
1853                         $$ = new UIntLiteral ((UInt32) v);
1854                 else if (v is long)
1855                         $$ = new LongLiteral ((Int64) v);
1856                 else if (v is ulong)
1857                         $$ = new ULongLiteral ((UInt64) v);
1858                 else
1859                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
1860           }
1861         ;
1862
1863 boolean_literal
1864         : TRUE                  { $$ = new BoolLiteral (true); }
1865         | FALSE                 { $$ = new BoolLiteral (false); }
1866         ;
1867
1868 parenthesized_expression
1869         : OPEN_PARENS expression CLOSE_PARENS
1870           { $$ = $2; }
1871         ;
1872
1873 member_access
1874         : primary_expression DOT IDENTIFIER
1875           {
1876                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1877           }
1878         | predefined_type DOT IDENTIFIER
1879           {
1880                 $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
1881           }
1882         ;
1883
1884 predefined_type
1885         : builtin_types
1886         ;
1887
1888 invocation_expression
1889         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
1890           {
1891                 if ($1 == null) {
1892                         Location l = lexer.Location;
1893                         Report.Error (1, l, "THIS IS CRAZY");
1894                 }
1895                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
1896           }
1897         ; 
1898
1899 opt_argument_list
1900         : /* empty */           { $$ = null; }
1901         | argument_list
1902         ;
1903
1904 argument_list
1905         : argument              
1906           { 
1907                 ArrayList list = new ArrayList ();
1908                 list.Add ($1);
1909                 $$ = list;
1910           }
1911         | argument_list COMMA argument
1912           {
1913                 ArrayList list = (ArrayList) $1;
1914                 list.Add ($3);
1915                 $$ = list;
1916           }
1917         ;
1918
1919 argument
1920         : expression
1921           {
1922                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
1923           }
1924         | REF variable_reference 
1925           { 
1926                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
1927           }
1928         | OUT variable_reference 
1929           { 
1930                 $$ = new Argument ((Expression) $2, Argument.AType.Out);
1931           }
1932         ;
1933
1934 variable_reference
1935         : expression { note ("section 5.4"); $$ = $1; }
1936         ;
1937
1938 element_access
1939         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
1940           {
1941                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
1942           }
1943         | primary_expression rank_specifiers
1944           {
1945                 // So the super-trick is that primary_expression
1946                 // can only be either a SimpleName or a MemberAccess. 
1947                 // The MemberAccess case arises when you have a fully qualified type-name like :
1948                 // Foo.Bar.Blah i;
1949                 // SimpleName is when you have
1950                 // Blah i;
1951                   
1952                 Expression expr = (Expression) $1;  
1953                 if (!(expr is SimpleName || expr is MemberAccess)) {
1954                         Location l = lexer.Location;
1955                         Report.Error (-1, l, "Invalid Type definition");
1956                         $$ = "System.Object";
1957                 }
1958                 
1959                 //
1960                 // So we extract the string corresponding to the SimpleName
1961                 // or MemberAccess
1962                 // 
1963                 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
1964           }
1965         ;
1966
1967 expression_list
1968         : expression
1969           {
1970                 ArrayList list = new ArrayList ();
1971                 list.Add ($1);
1972                 $$ = list;
1973           }
1974         | expression_list COMMA expression
1975           {
1976                 ArrayList list = (ArrayList) $1;
1977                 list.Add ($3);
1978                 $$ = list;
1979           }
1980         ;
1981
1982 this_access
1983         : THIS
1984           {
1985                 $$ = new This (lexer.Location);
1986           }
1987         ;
1988
1989 base_access
1990         : BASE DOT IDENTIFIER
1991           {
1992                 $$ = new BaseAccess ((string) $3, lexer.Location);
1993           }
1994         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
1995           {
1996                 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
1997           }
1998         ;
1999
2000 post_increment_expression
2001         : primary_expression OP_INC
2002           {
2003                 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2004                                        (Expression) $1, lexer.Location);
2005           }
2006         ;
2007
2008 post_decrement_expression
2009         : primary_expression OP_DEC
2010           {
2011                 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
2012                                        (Expression) $1, lexer.Location);
2013           }
2014         ;
2015
2016 new_expression
2017         : object_or_delegate_creation_expression
2018         | array_creation_expression
2019         ;
2020
2021 object_or_delegate_creation_expression
2022         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2023           {
2024                 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
2025           }
2026         ;
2027
2028 array_creation_expression
2029         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
2030           opt_rank_specifier
2031           opt_array_initializer
2032           {
2033                 $$ = new ArrayCreation ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, 
2034                                         lexer.Location);
2035           }
2036         | NEW type rank_specifiers array_initializer
2037           {
2038                 $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
2039           }
2040         | NEW type error 
2041           {
2042                 Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
2043           }
2044         ;
2045
2046 opt_rank_specifier
2047         : /* empty */
2048           {
2049                   $$ = "";
2050           }
2051         | rank_specifiers
2052           {
2053                         $$ = $1;
2054           }
2055         ;
2056
2057 rank_specifiers
2058         : rank_specifier
2059           {
2060                   $$ = $1;
2061           }
2062         | rank_specifiers rank_specifier
2063           {
2064                   $$ = (string) $2 + (string) $1;
2065           }             
2066         ;
2067
2068 rank_specifier
2069         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2070           {
2071                 $$ = "[" + (string) $2 + "]";
2072           }
2073         ;
2074
2075 opt_dim_separators
2076         : /* empty */
2077           {
2078                 $$ = "";
2079           }
2080         | dim_separators
2081           {
2082                   $$ = $1;
2083           }               
2084         ;
2085
2086 dim_separators
2087         : COMMA
2088           {
2089                 $$ = ",";
2090           }
2091         | dim_separators COMMA
2092           {
2093                 $$ = (string) $1 + ",";
2094           }
2095         ;
2096
2097 opt_array_initializer
2098         : /* empty */
2099           {
2100                 $$ = null;
2101           }
2102         | array_initializer
2103           {
2104                 $$ = $1;
2105           }
2106         ;
2107
2108 array_initializer
2109         : OPEN_BRACE CLOSE_BRACE
2110           {
2111                 ArrayList list = new ArrayList ();
2112                 $$ = list;
2113           }
2114         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
2115           {
2116                 $$ = (ArrayList) $2;
2117           }
2118         ;
2119
2120 variable_initializer_list
2121         : variable_initializer
2122           {
2123                 ArrayList list = new ArrayList ();
2124                 list.Add ($1);
2125                 $$ = list;
2126           }
2127         | variable_initializer_list COMMA variable_initializer
2128           {
2129                 ArrayList list = (ArrayList) $1;
2130                 list.Add ($3);
2131                 $$ = list;
2132           }
2133         ;
2134
2135 typeof_expression
2136         : TYPEOF OPEN_PARENS type CLOSE_PARENS
2137           {
2138                 $$ = new TypeOf ((string) $3, lexer.Location);
2139           }
2140         ;
2141
2142 sizeof_expression
2143         : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
2144                 $$ = new SizeOf ((string) $3);
2145
2146                 note ("Verify type is unmanaged"); 
2147                 note ("if (5.8) builtin, yield constant expression");
2148           }
2149         ;
2150
2151 checked_expression
2152         : CHECKED OPEN_PARENS expression CLOSE_PARENS
2153           {
2154                 $$ = new CheckedExpr ((Expression) $3);
2155           }
2156         ;
2157
2158 unchecked_expression
2159         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2160           {
2161                 $$ = new UnCheckedExpr ((Expression) $3);
2162           }
2163         ;
2164
2165 unary_expression
2166         : primary_expression
2167         | BANG prefixed_unary_expression
2168           {
2169                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2170           }
2171         | TILDE prefixed_unary_expression
2172           {
2173                 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2174           }
2175         | OPEN_PARENS expression CLOSE_PARENS unary_expression
2176           {
2177                   $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2178           }
2179         | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2180           {
2181                   $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2182           }
2183         ;
2184
2185         //
2186         // The idea to split this out is from Rhys' grammar
2187         // to solve the problem with casts.
2188         //
2189 prefixed_unary_expression
2190         : unary_expression
2191         | PLUS prefixed_unary_expression
2192           { 
2193                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2194           } 
2195         | MINUS prefixed_unary_expression 
2196           { 
2197                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2198           }
2199         | OP_INC prefixed_unary_expression 
2200           {
2201                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2202                                        (Expression) $2, lexer.Location);
2203           }
2204         | OP_DEC prefixed_unary_expression 
2205           {
2206                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2207                                        (Expression) $2, lexer.Location);
2208           }
2209         | STAR prefixed_unary_expression
2210           {
2211                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2212           }
2213         | BITWISE_AND prefixed_unary_expression
2214           {
2215                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2216           }
2217         ;
2218
2219 pre_increment_expression
2220         : OP_INC prefixed_unary_expression 
2221           {
2222                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2223                                        (Expression) $2, lexer.Location);
2224           }
2225         ;
2226
2227 pre_decrement_expression
2228         : OP_DEC prefixed_unary_expression 
2229           {
2230                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2231                                        (Expression) $2, lexer.Location);
2232           }
2233         ;
2234
2235 multiplicative_expression
2236         : prefixed_unary_expression
2237         | multiplicative_expression STAR prefixed_unary_expression
2238           {
2239                 $$ = new Binary (Binary.Operator.Multiply, 
2240                                  (Expression) $1, (Expression) $3, lexer.Location);
2241           }
2242         | multiplicative_expression DIV prefixed_unary_expression
2243           {
2244                 $$ = new Binary (Binary.Operator.Division, 
2245                                  (Expression) $1, (Expression) $3, lexer.Location);
2246           }
2247         | multiplicative_expression PERCENT prefixed_unary_expression 
2248           {
2249                 $$ = new Binary (Binary.Operator.Modulus, 
2250                                  (Expression) $1, (Expression) $3, lexer.Location);
2251           }
2252         ;
2253
2254 additive_expression
2255         : multiplicative_expression
2256         | additive_expression PLUS multiplicative_expression 
2257           {
2258                 $$ = new Binary (Binary.Operator.Addition, 
2259                                  (Expression) $1, (Expression) $3, lexer.Location);
2260           }
2261         | additive_expression MINUS multiplicative_expression
2262           {
2263                 $$ = new Binary (Binary.Operator.Subtraction, 
2264                                  (Expression) $1, (Expression) $3, lexer.Location);
2265           }
2266         ;
2267
2268 shift_expression
2269         : additive_expression
2270         | shift_expression OP_SHIFT_LEFT additive_expression
2271           {
2272                 $$ = new Binary (Binary.Operator.LeftShift, 
2273                                  (Expression) $1, (Expression) $3, lexer.Location);
2274           }
2275         | shift_expression OP_SHIFT_RIGHT additive_expression
2276           {
2277                 $$ = new Binary (Binary.Operator.RightShift, 
2278                                  (Expression) $1, (Expression) $3, lexer.Location);
2279           }
2280         ; 
2281
2282 relational_expression
2283         : shift_expression
2284         | relational_expression OP_LT shift_expression
2285           {
2286                 $$ = new Binary (Binary.Operator.LessThan, 
2287                                  (Expression) $1, (Expression) $3, lexer.Location);
2288           }
2289         | relational_expression OP_GT shift_expression
2290           {
2291                 $$ = new Binary (Binary.Operator.GreaterThan, 
2292                                  (Expression) $1, (Expression) $3, lexer.Location);
2293           }
2294         | relational_expression OP_LE shift_expression
2295           {
2296                 $$ = new Binary (Binary.Operator.LessThanOrEqual, 
2297                                  (Expression) $1, (Expression) $3, lexer.Location);
2298           }
2299         | relational_expression OP_GE shift_expression
2300           {
2301                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
2302                                  (Expression) $1, (Expression) $3, lexer.Location);
2303           }
2304         | relational_expression IS type
2305           {
2306                 $$ = new Is ((Expression) $1, (string) $3, lexer.Location);
2307           }
2308         | relational_expression AS type
2309           {
2310                 $$ = new As ((Expression) $1, (string) $3, lexer.Location);
2311           }
2312         ;
2313
2314 equality_expression
2315         : relational_expression
2316         | equality_expression OP_EQ relational_expression
2317           {
2318                 $$ = new Binary (Binary.Operator.Equality, 
2319                                  (Expression) $1, (Expression) $3, lexer.Location);
2320           }
2321         | equality_expression OP_NE relational_expression
2322           {
2323                 $$ = new Binary (Binary.Operator.Inequality, 
2324                                  (Expression) $1, (Expression) $3, lexer.Location);
2325           }
2326         ; 
2327
2328 and_expression
2329         : equality_expression
2330         | and_expression BITWISE_AND equality_expression
2331           {
2332                 $$ = new Binary (Binary.Operator.BitwiseAnd, 
2333                                  (Expression) $1, (Expression) $3, lexer.Location);
2334           }
2335         ;
2336
2337 exclusive_or_expression
2338         : and_expression
2339         | exclusive_or_expression CARRET and_expression
2340           {
2341                 $$ = new Binary (Binary.Operator.ExclusiveOr, 
2342                                  (Expression) $1, (Expression) $3, lexer.Location);
2343           }
2344         ;
2345
2346 inclusive_or_expression
2347         : exclusive_or_expression
2348         | inclusive_or_expression BITWISE_OR exclusive_or_expression
2349           {
2350                 $$ = new Binary (Binary.Operator.BitwiseOr, 
2351                                  (Expression) $1, (Expression) $3, lexer.Location);
2352           }
2353         ;
2354
2355 conditional_and_expression
2356         : inclusive_or_expression
2357         | conditional_and_expression OP_AND inclusive_or_expression
2358           {
2359                 $$ = new Binary (Binary.Operator.LogicalAnd, 
2360                                  (Expression) $1, (Expression) $3, lexer.Location);
2361           }
2362         ;
2363
2364 conditional_or_expression
2365         : conditional_and_expression
2366         | conditional_or_expression OP_OR conditional_and_expression
2367           {
2368                 $$ = new Binary (Binary.Operator.LogicalOr, 
2369                                  (Expression) $1, (Expression) $3, lexer.Location);
2370           }
2371         ;
2372
2373 conditional_expression
2374         : conditional_or_expression
2375         | conditional_or_expression INTERR expression COLON expression 
2376           {
2377                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2378           }
2379         ;
2380
2381 assignment_expression
2382         : prefixed_unary_expression ASSIGN expression
2383           {
2384                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2385           }
2386         | prefixed_unary_expression OP_MULT_ASSIGN expression
2387           {
2388                 Location l = lexer.Location;
2389
2390                 $$ = new Assign ((Expression) $1,
2391                                  new Binary (Binary.Operator.Multiply, 
2392                                              (Expression) $1,
2393                                              (Expression) $3, l), l);
2394           }
2395         | prefixed_unary_expression OP_DIV_ASSIGN expression
2396           {
2397                 Location l = lexer.Location;
2398
2399                 $$ = new Assign ((Expression) $1,
2400                                  new Binary (Binary.Operator.Division, 
2401                                              (Expression) $1,
2402                                              (Expression) $3, l), l);
2403           }
2404         | prefixed_unary_expression OP_MOD_ASSIGN expression
2405           {
2406                 Location l = lexer.Location;
2407
2408                 $$ = new Assign ((Expression) $1,
2409                                  new Binary (Binary.Operator.Modulus, 
2410                                              (Expression) $1,
2411                                              (Expression) $3, l), l);
2412           }
2413         | prefixed_unary_expression OP_ADD_ASSIGN expression
2414           {
2415                 Location l = lexer.Location;
2416
2417                 $$ = new Assign ((Expression) $1,
2418                                  new Binary (Binary.Operator.Addition, 
2419                                              (Expression) $1,
2420                                              (Expression) $3, l), l);
2421           }
2422         | prefixed_unary_expression OP_SUB_ASSIGN expression
2423           {
2424                 Location l = lexer.Location;
2425
2426                 $$ = new Assign ((Expression) $1,
2427                                  new Binary (Binary.Operator.Subtraction, 
2428                                              (Expression) $1,
2429                                              (Expression) $3, l), l);
2430           }
2431         | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2432           {
2433                 Location l = lexer.Location;
2434
2435                 $$ = new Assign ((Expression) $1,
2436                                  new Binary (Binary.Operator.LeftShift, 
2437                                              (Expression) $1,
2438                                              (Expression) $3, l), l);
2439           }
2440         | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2441           {
2442                 Location l = lexer.Location;
2443
2444                 $$ = new Assign ((Expression) $1,
2445                                  new Binary (Binary.Operator.RightShift, 
2446                                              (Expression) $1,
2447                                              (Expression) $3, l), l);
2448           }
2449         | prefixed_unary_expression OP_AND_ASSIGN expression
2450           {
2451                 Location l = lexer.Location;
2452
2453                 $$ = new Assign ((Expression) $1,
2454                                  new Binary (Binary.Operator.BitwiseAnd, 
2455                                              (Expression) $1,
2456                                              (Expression) $3, l), l);
2457           }
2458         | prefixed_unary_expression OP_OR_ASSIGN expression
2459           {
2460                 Location l = lexer.Location;
2461
2462                 $$ = new Assign ((Expression) $1,
2463                                  new Binary (Binary.Operator.BitwiseOr, 
2464                                              (Expression) $1,
2465                                              (Expression) $3, l), l);
2466           }
2467         | prefixed_unary_expression OP_XOR_ASSIGN expression
2468           {
2469                 Location l = lexer.Location;
2470
2471                 $$ = new Assign ((Expression) $1,
2472                                  new Binary (Binary.Operator.ExclusiveOr, 
2473                                              (Expression) $1,
2474                                              (Expression) $3, l), l);
2475           }
2476         ;
2477
2478 expression
2479         : conditional_expression
2480         | assignment_expression
2481         ;
2482
2483 constant_expression
2484         : expression
2485         ;
2486
2487 boolean_expression
2488         : expression
2489         ;
2490
2491 //
2492 // 10 classes
2493 //
2494 class_declaration
2495         : opt_attributes
2496           opt_modifiers
2497           CLASS IDENTIFIER
2498           {
2499                 Class new_class;
2500                 string name;
2501
2502                 name = MakeName ((string) $4);
2503
2504                 new_class = new Class (current_container, name, (int) $2, 
2505                                        (Attributes) $1, lexer.Location);
2506                 current_container = new_class;
2507                 current_container.Namespace = current_namespace;
2508                 RootContext.Tree.RecordClass (name, new_class);
2509           }
2510           opt_class_base
2511           class_body 
2512           opt_semicolon 
2513           {
2514                 Class new_class = (Class) current_container;
2515
2516                 if ($6 != null)
2517                         new_class.Bases = (ArrayList) $6;
2518
2519                 current_container = current_container.Parent;
2520                 CheckDef (current_container.AddClass (new_class), new_class.Name);
2521
2522                 $$ = new_class;
2523           }
2524         ;       
2525
2526 opt_modifiers
2527         : /* empty */           { $$ = (int) 0; }
2528         | modifiers
2529         ;
2530
2531 modifiers
2532         : modifier
2533         | modifiers modifier
2534           { 
2535                 int m1 = (int) $1;
2536                 int m2 = (int) $2;
2537
2538                 if ((m1 & m2) != 0) {
2539                         Location l = lexer.Location;
2540                         Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2541                 }
2542                 $$ = (int) (m1 | m2);
2543           }
2544         ;
2545
2546 modifier
2547         : NEW                   { $$ = Modifiers.NEW; }
2548         | PUBLIC                { $$ = Modifiers.PUBLIC; }
2549         | PROTECTED             { $$ = Modifiers.PROTECTED; }
2550         | INTERNAL              { $$ = Modifiers.INTERNAL; }
2551         | PRIVATE               { $$ = Modifiers.PRIVATE; }
2552         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
2553         | SEALED                { $$ = Modifiers.SEALED; }
2554         | STATIC                { $$ = Modifiers.STATIC; }
2555         | READONLY              { $$ = Modifiers.READONLY; }
2556         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
2557         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
2558         | EXTERN                { $$ = Modifiers.EXTERN; }
2559         | VOLATILE              { $$ = Modifiers.VOLATILE; }
2560         | UNSAFE                { $$ = Modifiers.UNSAFE; }
2561         ;
2562
2563 opt_class_base
2564         : /* empty */           { $$ = null; }
2565         | class_base            { $$ = $1;   }
2566         ;
2567
2568 class_base
2569         : COLON type_list { $$ = $2; }
2570         ;
2571
2572 //
2573 // Statements (8.2)
2574 //
2575
2576 //
2577 // A block is "contained" on the following places:
2578 //      method_body
2579 //      property_declaration as part of the accessor body (get/set)
2580 //      operator_declaration
2581 //      constructor_declaration
2582 //      destructor_declaration
2583 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2584 //      
2585 block
2586         : OPEN_BRACE 
2587           {
2588                 current_block = new Block (current_block);
2589           } 
2590           opt_statement_list CLOSE_BRACE 
2591           { 
2592                 while (current_block.Implicit)
2593                         current_block = current_block.Parent;
2594                 $$ = current_block;
2595                 current_block = current_block.Parent;
2596           }
2597         ;
2598
2599 opt_statement_list
2600         : /* empty */
2601         | statement_list 
2602         ;
2603
2604 statement_list
2605         : statement
2606         | statement_list statement
2607         ;
2608
2609 statement
2610         : declaration_statement
2611           {
2612                 if ((Block) $1 != current_block){
2613                         current_block.AddStatement ((Statement) $1);
2614                         current_block = (Block) $1;
2615                 }
2616           }
2617         | embedded_statement
2618           {
2619                 Statement s = (Statement) $1;
2620
2621
2622                 current_block.AddStatement ((Statement) $1);
2623           }
2624         | labeled_statement
2625         ;
2626
2627 embedded_statement
2628         : block
2629         | empty_statement
2630         | expression_statement
2631         | selection_statement
2632         | iteration_statement
2633         | jump_statement                  
2634         | try_statement
2635         | checked_statement
2636         | unchecked_statement
2637         | lock_statement
2638         | using_statement
2639         | unsafe_statement
2640         ;
2641
2642 empty_statement
2643         : SEMICOLON
2644           {
2645                   $$ = new EmptyStatement ();
2646           }
2647         ;
2648
2649 labeled_statement
2650         : IDENTIFIER COLON 
2651           {
2652                 LabeledStatement labeled = new LabeledStatement ((string) $1);
2653
2654                 if (!current_block.AddLabel ((string) $1, labeled)){
2655                         Location l = lexer.Location;
2656                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2657                 }       
2658                 current_block.AddStatement (labeled);
2659           }
2660           statement
2661         ;
2662
2663 declaration_statement
2664         : local_variable_declaration SEMICOLON
2665           {
2666                 DictionaryEntry de = (DictionaryEntry) $1;
2667
2668                 $$ = declare_local_variables ((string) de.Key, (ArrayList) de.Value, lexer.Location);
2669           }
2670
2671         | local_constant_declaration SEMICOLON
2672           {
2673                 DictionaryEntry de = (DictionaryEntry) $1;
2674
2675                 $$ = declare_local_constant ((string) de.Key, (VariableDeclaration) de.Value);
2676           }
2677         ;
2678
2679 /* 
2680  * The following is from Rhys' grammar:
2681  * > Types in local variable declarations must be recognized as 
2682  * > expressions to prevent reduce/reduce errors in the grammar.
2683  * > The expressions are converted into types during semantic analysis.
2684  */
2685 local_variable_type
2686         : primary_expression opt_rank_specifier
2687           { 
2688                 // FIXME: Do something smart here regarding the composition of the type.
2689
2690                 // Ok, the above "primary_expression" is there to get rid of
2691                 // both reduce/reduce and shift/reduces in the grammar, it should
2692                 // really just be "type_name".  If you use type_name, a reduce/reduce
2693                 // creeps up.  If you use qualified_identifier (which is all we need
2694                 // really) two shift/reduces appear.
2695                 // 
2696
2697                 // So the super-trick is that primary_expression
2698                 // can only be either a SimpleName or a MemberAccess. 
2699                 // The MemberAccess case arises when you have a fully qualified type-name like :
2700                 // Foo.Bar.Blah i;
2701                 // SimpleName is when you have
2702                 // Blah i;
2703                   
2704                 Expression expr = (Expression) $1;  
2705                 if (!(expr is SimpleName || expr is MemberAccess)) {
2706                         Location l = lexer.Location;
2707                         Report.Error (-1, l, "Invalid Type definition");
2708                         $$ = "System.Object";
2709                 }
2710                 
2711                 //
2712                 // So we extract the string corresponding to the SimpleName
2713                 // or MemberAccess
2714                 // 
2715                 $$ = GetQualifiedIdentifier (expr) + (string) $2;
2716           }
2717         | builtin_types opt_rank_specifier
2718           {
2719                   $$ = (string) $1 + (string) $2;
2720           }
2721         ;
2722
2723 local_variable_pointer_type
2724         : primary_expression STAR
2725           {
2726                 Expression expr = (Expression) $1;  
2727                 if (!(expr is SimpleName || expr is MemberAccess)) {
2728                         Location l = lexer.Location;
2729                         Report.Error (-1, l, "Invalid Type definition");
2730                         $$ = "System.Object";
2731                 }
2732                 
2733                 $$ = GetQualifiedIdentifier (expr) + "*";
2734           }
2735         | builtin_types STAR
2736           {
2737                 $$ = (string) $1 + "*";
2738           }
2739         | VOID STAR
2740           {
2741                 $$ = "System.Void*";
2742           }
2743         | local_variable_pointer_type STAR
2744           {
2745                 $$ = (string) $1 + "*";
2746           }
2747         ;
2748
2749 local_variable_declaration
2750         : local_variable_type variable_declarators
2751           {
2752                 $$ = new DictionaryEntry ($1, $2);
2753           }
2754         | local_variable_pointer_type opt_rank_specifier variable_declarators
2755         {
2756                 $$ = new DictionaryEntry ((string) $1 + (string) $2, $3);
2757         }
2758         ;
2759
2760 local_constant_declaration
2761         : CONST local_variable_type constant_declarator
2762           {
2763                 $$ = new DictionaryEntry ($2, $3);
2764           }
2765         ;
2766
2767 expression_statement
2768         : statement_expression SEMICOLON
2769           {
2770                 $$ = $1;
2771           }
2772         ;
2773
2774         //
2775         // We have to do the wrapping here and not in the case above,
2776         // because statement_expression is used for example in for_statement
2777         //
2778 statement_expression
2779         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2780         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1); }
2781         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2782         | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2783         | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2784         | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2785         | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2786         | error {
2787                 Report.Error (1002, lexer.Location, "Expecting `;'");
2788           }
2789         ;
2790
2791 object_creation_expression
2792         : object_or_delegate_creation_expression
2793           { note ("complain if this is a delegate maybe?"); } 
2794         ;
2795
2796 selection_statement
2797         : if_statement
2798         | switch_statement
2799         ; 
2800
2801 if_statement
2802         : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
2803           embedded_statement
2804           { 
2805                 $$ = new If ((Expression) $3, (Statement) $5);
2806
2807                 if (RootContext.WarningLevel >= 3){
2808                         if ($5 is EmptyStatement)
2809                                 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
2810                 }
2811
2812           }
2813         | IF OPEN_PARENS boolean_expression CLOSE_PARENS
2814           embedded_statement ELSE embedded_statement
2815           {
2816                 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
2817           }
2818         ;
2819
2820 switch_statement
2821         : SWITCH OPEN_PARENS 
2822           { 
2823                 oob_stack.Push (lexer.Location);
2824           }
2825           expression CLOSE_PARENS 
2826           switch_block
2827           {
2828                 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
2829           }
2830         ;
2831
2832 switch_block
2833         : OPEN_BRACE
2834           opt_switch_sections
2835           CLOSE_BRACE
2836           {
2837                 $$ = $2;
2838           }
2839         ;
2840
2841 opt_switch_sections
2842         : /* empty */           
2843           {
2844                 Report.Error (1522, lexer.Location, "Empty switch block"); 
2845           }
2846         | switch_sections
2847         ;
2848
2849 switch_sections
2850         : switch_section 
2851           {
2852                 ArrayList sections = new ArrayList ();
2853
2854                 sections.Add ($1);
2855                 $$ = sections;
2856           }
2857         | switch_sections switch_section
2858           {
2859                 ArrayList sections = (ArrayList) $1;
2860
2861                 sections.Add ($2);
2862                 $$ = sections;
2863           }
2864         ;
2865
2866 switch_section
2867         : switch_labels
2868           {
2869                 current_block = new Block (current_block);
2870           }
2871           statement_list 
2872           {
2873                 while (current_block.Implicit)
2874                         current_block = current_block.Parent;
2875                 $$ = new SwitchSection ((ArrayList) $1, current_block);
2876                 current_block = current_block.Parent;
2877           }
2878         ;
2879
2880 switch_labels
2881         : switch_label 
2882           {
2883                 ArrayList labels = new ArrayList ();
2884
2885                 labels.Add ($1);
2886                 $$ = labels;
2887           }
2888         | switch_labels switch_label 
2889           {
2890                 ArrayList labels = (ArrayList) ($1);
2891                 labels.Add ($2);
2892
2893                 $$ = labels;
2894           }
2895         ;
2896
2897 switch_label
2898         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
2899         | DEFAULT COLON                         { $$ = new SwitchLabel (null, lexer.Location); }
2900         | error {
2901                 Report.Error (
2902                         1523, lexer.Location, 
2903                         "The keyword case or default must precede code in switch block");
2904           }
2905         ;
2906
2907 iteration_statement
2908         : while_statement
2909         | do_statement
2910         | for_statement
2911         | foreach_statement
2912         ;
2913
2914 while_statement
2915         : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
2916         {
2917                 $$ = new While ((Expression) $3, (Statement) $5);
2918         
2919                 if (RootContext.WarningLevel >= 3){
2920                         if ($5 is EmptyStatement)
2921                                 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
2922                 }
2923         }
2924         ;
2925
2926 do_statement
2927         : DO embedded_statement 
2928           WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
2929           {
2930                 $$ = new Do ((Statement) $2, (Expression) $5);
2931           }
2932         ;
2933
2934 for_statement
2935         : FOR OPEN_PARENS 
2936           opt_for_initializer SEMICOLON
2937           {
2938                 Block assign_block = new Block (current_block);
2939                 current_block = assign_block;
2940
2941                 if ($3 is DictionaryEntry){
2942                         DictionaryEntry de = (DictionaryEntry) $3;
2943                         
2944                         string type = (string) de.Key;
2945                         ArrayList var_declarators = (ArrayList) de.Value;
2946
2947                         foreach (VariableDeclaration decl in var_declarators){
2948
2949                                 if (!current_block.AddVariable (type, decl.identifier, current_local_parameters,
2950                                                                 decl.Location)) {
2951                                         Report.Error (128, decl.Location, 
2952                                                       "A local variable `" + decl.identifier + "' is already" +
2953                                                       "defined in this scope");
2954                                 } else {
2955
2956                                         Location l = lexer.Location;
2957                                         Expression expr;
2958                                         if (decl.expression_or_array_initializer is Expression){
2959                                                 expr = (Expression) decl.expression_or_array_initializer;
2960                                                 
2961                                         } else {
2962                                                 
2963                                                 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
2964                                                 
2965                                                 string base_type = type.Substring (0, type.IndexOf ("["));
2966                                                 string rank = type.Substring (type.IndexOf ("["));
2967                                                 
2968                                                 expr = new ArrayCreation (base_type, rank, init, decl.Location);
2969                                         }
2970                                         
2971                                         LocalVariableReference var;
2972                                         var = new LocalVariableReference (
2973                                                                           assign_block, decl.identifier, l);
2974                                         
2975                                         Assign a = new Assign (var, expr, decl.Location);
2976                                         
2977                                         assign_block.AddStatement (new StatementExpression (a));
2978                                 }
2979                         }
2980                         
2981                         $3 = null;
2982                 } 
2983           } 
2984           opt_for_condition SEMICOLON
2985           opt_for_iterator CLOSE_PARENS 
2986           embedded_statement
2987           {
2988                 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10);
2989
2990                 if (RootContext.WarningLevel >= 3){
2991                         if ($10 is EmptyStatement)
2992                                 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
2993                 }
2994
2995                 current_block.AddStatement (f);
2996                 while (current_block.Implicit)
2997                         current_block = current_block.Parent;
2998                 $$ = current_block;
2999                 current_block = current_block.Parent;
3000           }
3001         ;
3002
3003 opt_for_initializer
3004         : /* empty */           { $$ = new EmptyStatement (); }
3005         | for_initializer       
3006         ;
3007
3008 for_initializer
3009         : local_variable_declaration
3010         | statement_expression_list
3011         ;
3012
3013 opt_for_condition
3014         : /* empty */           { $$ = null; }
3015         | boolean_expression
3016         ;
3017
3018 opt_for_iterator
3019         : /* empty */           { $$ = new EmptyStatement (); }
3020         | for_iterator
3021         ;
3022
3023 for_iterator
3024         : statement_expression_list
3025         ;
3026
3027 statement_expression_list
3028         : statement_expression  
3029           {
3030                 Block b = new Block (null, true);
3031
3032                 b.AddStatement ((Statement) $1);
3033                 $$ = b;
3034           }
3035         | statement_expression_list COMMA statement_expression
3036           {
3037                 Block b = (Block) $1;
3038
3039                 b.AddStatement ((Statement) $3);
3040                 $$ = $1;
3041           }
3042         ;
3043
3044 foreach_statement
3045         : FOREACH OPEN_PARENS type IDENTIFIER IN 
3046           {
3047                 oob_stack.Push (lexer.Location);
3048           }
3049           expression CLOSE_PARENS 
3050           {
3051                 Block foreach_block = new Block (current_block, true);
3052                 LocalVariableReference v;
3053                 Location l = lexer.Location;
3054
3055                 foreach_block.AddVariable ((string) $3, (string) $4, current_local_parameters, l);
3056                 v = new LocalVariableReference (foreach_block, (string) $4, l);
3057
3058                 current_block.AddStatement (foreach_block);
3059                 current_block = foreach_block;
3060
3061                 oob_stack.Push (foreach_block);
3062                 oob_stack.Push (v);
3063           } 
3064           embedded_statement 
3065           {
3066                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
3067                 Block foreach_block = (Block) oob_stack.Pop ();
3068                 Location l = (Location) oob_stack.Pop ();
3069
3070                 $$ = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
3071           }
3072         ;
3073
3074 jump_statement
3075         : break_statement
3076         | continue_statement
3077         | goto_statement
3078         | return_statement
3079         | throw_statement
3080         ;
3081
3082 break_statement
3083         : BREAK SEMICOLON
3084           {
3085                 $$ = new Break (lexer.Location);
3086           }
3087         ;
3088
3089 continue_statement
3090         : CONTINUE SEMICOLON
3091           {
3092                 $$ = new Continue (lexer.Location);
3093           }
3094         ;
3095
3096 goto_statement
3097         : GOTO IDENTIFIER SEMICOLON 
3098           {
3099                 $$ = new Goto (current_block, (string) $2, lexer.Location);
3100           }
3101         | GOTO CASE constant_expression SEMICOLON
3102           {
3103                 $$ = new GotoCase ((Expression) $3, lexer.Location);
3104           }
3105         | GOTO DEFAULT SEMICOLON 
3106           {
3107                 $$ = new GotoDefault (lexer.Location);
3108           }
3109         ; 
3110
3111 return_statement
3112         : RETURN opt_expression SEMICOLON
3113           {
3114                 $$ = new Return ((Expression) $2, lexer.Location);
3115           }
3116         ;
3117
3118 throw_statement
3119         : THROW opt_expression SEMICOLON
3120           {
3121                 $$ = new Throw ((Expression) $2, lexer.Location);
3122           }
3123         ;
3124
3125 opt_expression
3126         : /* empty */
3127         | expression
3128         ;
3129
3130 try_statement
3131         : TRY block catch_clauses 
3132         {
3133                 Catch g = null;
3134                 ArrayList s = new ArrayList ();
3135                 
3136                 foreach (Catch cc in (ArrayList) $3) {
3137                         if (cc.Type == null)
3138                                 g = cc;
3139                         else
3140                                 s.Add (cc);
3141                 }
3142
3143                 // Now s contains the list of specific catch clauses
3144                 // and g contains the general one.
3145                 
3146                 $$ = new Try ((Block) $2, s, g, null);
3147         }
3148         | TRY block opt_catch_clauses FINALLY block
3149           {
3150                 Catch g = null;
3151                 ArrayList s = new ArrayList ();
3152                 
3153                 foreach (Catch cc in (ArrayList) $3) {
3154                         if (cc.Type == null)
3155                                 g = cc;
3156                         else
3157                                 s.Add (cc);
3158                 }
3159
3160                 $$ = new Try ((Block) $2, s, g, (Block) $5);
3161           }
3162         | TRY block error 
3163           {
3164                 Report.Error (1524, lexer.Location, "Expected catch or finally");
3165           }
3166         ;
3167
3168 opt_catch_clauses
3169         : /* empty */  { $$ = null; }
3170         | catch_clauses
3171         ;
3172
3173 catch_clauses
3174         : catch_clause 
3175           {
3176                 ArrayList l = new ArrayList ();
3177
3178                 l.Add ($1);
3179                 $$ = l;
3180           }
3181         | catch_clauses catch_clause
3182           {
3183                 ArrayList l = (ArrayList) $1;
3184
3185                 l.Add ($2);
3186                 $$ = l;
3187           }
3188         ;
3189
3190 opt_identifier
3191         : /* empty */   { $$ = null; }
3192         | IDENTIFIER
3193         ;
3194
3195 catch_clause 
3196         : CATCH opt_catch_args 
3197         {
3198                 string type = null, id = null;
3199                 
3200                 if ($2 != null) {
3201                         DictionaryEntry cc = (DictionaryEntry) $2;
3202                         type = (string) cc.Key;
3203                         id   = (string) cc.Value;
3204
3205                         if (id != null){
3206                                 ArrayList one = new ArrayList ();
3207                                 Location loc = lexer.Location;
3208
3209                                 one.Add (new VariableDeclaration (id, null, loc));
3210
3211                                 $1 = current_block;
3212                                 current_block = new Block (current_block);
3213                                 Block b = declare_local_variables (type, one, loc);
3214                                 current_block = b;
3215
3216                                 
3217                         }
3218                 }
3219         } block {
3220                 string type = null, id = null;
3221
3222                 if ($2 != null){
3223                         DictionaryEntry cc = (DictionaryEntry) $2;
3224                         type = (string) cc.Key;
3225                         id   = (string) cc.Value;
3226
3227                         if ($1 != null){
3228                                 while (current_block != (Block) $1)
3229                                         current_block = current_block.Parent;
3230                         }
3231                 }
3232
3233
3234                 $$ = new Catch (type, id , (Block) $4, lexer.Location);
3235         }
3236         ;
3237
3238 opt_catch_args
3239         : /* empty */ { $$ = null; }
3240         | catch_args
3241         ;         
3242
3243 catch_args 
3244         : OPEN_PARENS type opt_identifier CLOSE_PARENS 
3245         {
3246                 $$ = new DictionaryEntry ($2, $3);
3247         }
3248         ;
3249
3250 checked_statement
3251         : CHECKED block
3252           {
3253                 $$ = new Checked ((Block) $2);
3254           }
3255         ;
3256
3257 unchecked_statement
3258         : UNCHECKED block
3259           {
3260                 $$ = new Unchecked ((Block) $2);
3261           }
3262         ;
3263
3264 unsafe_statement
3265         : UNSAFE 
3266         {
3267                 if (!RootContext.Unsafe){
3268                         Report.Error (227, lexer.Location, 
3269                                 "Unsafe code can only be used if --unsafe is used");
3270                 }
3271         } block {
3272                 $$ = new Unsafe ((Block) $3);
3273         }
3274
3275
3276 lock_statement
3277         : LOCK OPEN_PARENS expression CLOSE_PARENS 
3278           {
3279                 //
3280           } 
3281           embedded_statement
3282           {
3283                 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3284           }
3285         ;
3286
3287 using_statement
3288         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
3289           {
3290                 Block assign_block = new Block (current_block);
3291                 current_block = assign_block;
3292
3293                 oob_stack.Push (lexer.Location);
3294                 
3295                 if ($3 is DictionaryEntry){
3296                         DictionaryEntry de = (DictionaryEntry) $3;
3297                         Location l = lexer.Location;
3298
3299                         string type = (string) de.Key;
3300                         ArrayList var_declarators = (ArrayList) de.Value;
3301
3302                         foreach (VariableDeclaration decl in var_declarators){
3303                                 if (!current_block.AddVariable (type, decl.identifier, current_local_parameters,
3304                                                                 decl.Location)){
3305                                         Report.Error (128, decl.Location, 
3306                                         "A local variable `" + decl.identifier + "' is already" +
3307                                         "defined in this scope");
3308                                 }
3309                         }
3310
3311                         ArrayList vars = new ArrayList ();
3312
3313                         foreach (VariableDeclaration decl in var_declarators){
3314
3315                                 Expression expr;
3316                                 if (decl.expression_or_array_initializer is Expression){
3317                                         expr = (Expression) decl.expression_or_array_initializer;
3318                                         
3319                                 } else {
3320
3321                                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3322                                         
3323                                         string base_type = type.Substring (0, type.IndexOf ("["));
3324                                         string rank = type.Substring (type.IndexOf ("["));
3325                                         
3326                                         expr = new ArrayCreation (base_type, rank, init, decl.Location);
3327                                 }
3328
3329                                 LocalVariableReference var;
3330                                 VariableInfo vi;
3331
3332                                 var = new LocalVariableReference (assign_block, decl.identifier, l);
3333                                 vi = var.VariableInfo;
3334                                 vi.ReadOnly = true;
3335
3336                                 // This is so that it is not a warning on using variables
3337                                 vi.Used = true;
3338
3339                                 vars.Add (new DictionaryEntry (var, expr));                             
3340
3341                                 // Assign a = new Assign (var, expr, decl.Location);
3342                                 // assign_block.AddStatement (new StatementExpression (a));
3343                         }
3344                         $3 = new DictionaryEntry (type, vars);
3345                  }
3346           } 
3347           embedded_statement
3348           {
3349                 Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
3350                 current_block.AddStatement (u);
3351                 while (current_block.Implicit)
3352                         current_block = current_block.Parent;
3353                 $$ = current_block;
3354                 current_block = current_block.Parent;
3355           }
3356         ; 
3357
3358 resource_acquisition
3359         : local_variable_declaration
3360         | expression
3361         ;
3362
3363 %%
3364
3365 // <summary>
3366 //   A class used to pass around variable declarations and constants
3367 // </summary>
3368 public class VariableDeclaration {
3369         public string identifier;
3370         public object expression_or_array_initializer;
3371         public Location Location;
3372
3373         public VariableDeclaration (string id, object eoai, Location l){
3374                 this.identifier = id;
3375                 this.expression_or_array_initializer = eoai;
3376                 this.Location = l;
3377         }
3378 }
3379
3380 // <summary>
3381 //   A class used to hold info about an indexer declarator
3382 // </summary>
3383
3384 public class IndexerDeclaration {
3385         public string type;
3386         public string interface_type;
3387         public Parameters param_list;
3388
3389         public IndexerDeclaration (string type, string interface_type, Parameters param_list)
3390         {
3391                 this.type = type;
3392                 this.interface_type = interface_type;
3393                 this.param_list = param_list;
3394         }
3395 }
3396
3397 // <summary>
3398 //  A class used to hold info about an operator declarator
3399 // </summary>
3400
3401 public class OperatorDeclaration {
3402         public Operator.OpType optype;
3403         public string ret_type;
3404         public string arg1type;
3405         public string arg1name;
3406         public string arg2type;
3407         public string arg2name;
3408         public Location location;
3409
3410         public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
3411                                     string arg2type, string arg2name, Location location)
3412         {
3413                 optype = op;
3414                 this.ret_type = ret_type;
3415                 this.arg1type = arg1type;
3416                 this.arg1name = arg1name;
3417                 this.arg2type = arg2type;
3418                 this.arg2name = arg2name;
3419                 this.location = location;
3420         }
3421
3422 }
3423
3424 // <summary>
3425 //   Given the @class_name name, it creates a fully qualified name
3426 //   based on the containing declaration space
3427 // </summary>
3428 string 
3429 MakeName (string class_name)
3430 {
3431         string ns = current_namespace.Name;
3432         string container_name = current_container.Name;
3433
3434         if (container_name == ""){
3435                 if (ns != "")
3436                         return ns + "." + class_name;
3437                 else
3438                         return class_name;
3439         } else
3440                 return container_name + "." + class_name;
3441 }
3442
3443 // <summary>
3444 //   Used to report back to the user the result of a declaration
3445 //   in the current declaration space
3446 // </summary>
3447 void 
3448 CheckDef (AdditionResult result, string name)
3449 {
3450         if (result == AdditionResult.Success)
3451                 return;
3452
3453         Location l = lexer.Location;
3454         
3455         switch (result){
3456         case AdditionResult.NameExists:
3457                 Report.Error (102, l, "The namespace `" + current_container.Name + 
3458                                  "' already contains a definition for `"+
3459                                  name + "'");
3460                 break;
3461
3462
3463                 //
3464                 // This is handled only for static Constructors, because
3465                 // in reality we handle these by the semantic analysis later
3466                 //
3467         case AdditionResult.MethodExists:
3468                 Report.Error (
3469                         111, l, "Class `"+current_container.Name+
3470                         "' already defines a member called '" + 
3471                         name + "' with the same parameter types (more than one default constructor)");
3472                 break;
3473
3474         case AdditionResult.EnclosingClash:
3475                 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
3476                 break;
3477                 
3478         case AdditionResult.NotAConstructor:
3479                 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
3480                 break;
3481         }
3482 }
3483
3484 void 
3485 CheckDef (bool result, string name)
3486 {
3487         if (result)
3488                 return;
3489         CheckDef (AdditionResult.NameExists, name);
3490 }
3491
3492 Expression
3493 SimpleLookup (string name, Location loc)
3494 {
3495         //
3496         // we need to check against current_block not being null
3497         // as `expression' is allowed in argument_lists, which 
3498         // do not exist inside a block.  
3499         //
3500         if (current_block != null){
3501                 if (current_block.IsVariableDefined (name))
3502                         return new LocalVariableReference (current_block, name, loc);
3503         }
3504
3505         if (current_local_parameters != null){
3506                 int idx;
3507                 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
3508                 if (par != null)
3509                         return new ParameterReference (current_local_parameters, idx, name);
3510         }
3511
3512         return null;
3513 }
3514
3515 Expression DecomposeQI (string name, Location loc)
3516 {
3517         Expression o;
3518
3519         if (name.IndexOf ('.') == -1){
3520                 o = SimpleLookup (name, loc);
3521                 if (o == null)
3522                         return new SimpleName (name, loc);
3523                 return o;
3524         } else {
3525                 int pos = name.LastIndexOf (".");
3526                 string left = name.Substring (0, pos);
3527                 string right = name.Substring (pos + 1);
3528
3529                 o = DecomposeQI (left, loc);
3530                 return new MemberAccess (o, right, loc);
3531         }
3532 }
3533
3534 // <summary>
3535 //  This method is used to get at the complete string representation of
3536 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
3537 //  This is necessary because local_variable_type admits primary_expression
3538 //  as the type of the variable. So we do some extra checking
3539 // </summary>
3540 string GetQualifiedIdentifier (Expression expr)
3541 {
3542         if (expr is SimpleName)
3543                 return ((SimpleName)expr).Name;
3544         else if (expr is MemberAccess)
3545                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3546         else 
3547                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3548         
3549 }
3550
3551 Block declare_local_variables (string type, ArrayList variable_declarators, Location loc)
3552 {
3553         Block implicit_block;
3554         ArrayList inits = null;
3555
3556         //
3557         // We use the `Used' property to check whether statements
3558         // have been added to the current block.  If so, we need
3559         // to create another block to contain the new declaration
3560         // otherwise, as an optimization, we use the same block to
3561         // add the declaration.
3562         //
3563         // FIXME: A further optimization is to check if the statements
3564         // that were added were added as part of the initialization
3565         // below.  In which case, no other statements have been executed
3566         // and we might be able to reduce the number of blocks for
3567         // situations like this:
3568         //
3569         // int j = 1;  int k = j + 1;
3570         //
3571         if (current_block.Used)
3572                 implicit_block = new Block (current_block, true);
3573         else
3574                 implicit_block = current_block;
3575
3576         foreach (VariableDeclaration decl in variable_declarators){
3577
3578                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location)) {
3579                         if (decl.expression_or_array_initializer != null){
3580                                 if (inits == null)
3581                                         inits = new ArrayList ();
3582                                 inits.Add (decl);
3583                         }
3584                 } else {
3585                         Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3586                                          "' is already defined in this scope");
3587                 }
3588         }
3589
3590         if (inits == null)
3591                 return implicit_block;
3592
3593         foreach (VariableDeclaration decl in inits){
3594                 Assign assign;
3595                 Expression expr;
3596                 
3597                 if (decl.expression_or_array_initializer is Expression){
3598                         expr = (Expression) decl.expression_or_array_initializer;
3599
3600                 } else {
3601                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3602                         
3603                         string base_type = type.Substring (0, type.IndexOf ("["));
3604                         string rank = type.Substring (type.IndexOf ("["));
3605
3606                         expr = new ArrayCreation (base_type, rank, init, decl.Location);
3607                         
3608                 }
3609
3610                 LocalVariableReference var;
3611                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3612
3613                 assign = new Assign (var, expr, decl.Location);
3614
3615                 implicit_block.AddStatement (new StatementExpression (assign));
3616         }
3617         
3618         return implicit_block;
3619 }
3620
3621 Block declare_local_constant (string type, VariableDeclaration decl)
3622 {
3623         Block implicit_block;
3624
3625         if (current_block.Used)
3626                 implicit_block = new Block (current_block, true);
3627         else
3628                 implicit_block = current_block;
3629
3630         if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3631                                           current_local_parameters, decl.Location))){
3632                 Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3633                               "' is already defined in this scope");
3634         }
3635         
3636         return implicit_block;
3637 }
3638
3639 void CheckAttributeTarget (string a)
3640 {
3641         switch (a) {
3642
3643         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3644                 return;
3645                 
3646         default :
3647                 Location l = lexer.Location;
3648                 Report.Error (658, l, "Invalid attribute target");
3649                 break;
3650         }
3651
3652 }
3653
3654 void CheckUnaryOperator (Operator.OpType op)
3655 {
3656         switch (op) {
3657                 
3658         case Operator.OpType.LogicalNot: 
3659         case Operator.OpType.OnesComplement: 
3660         case Operator.OpType.Increment:
3661         case Operator.OpType.Decrement:
3662         case Operator.OpType.True: 
3663         case Operator.OpType.False: 
3664         case Operator.OpType.Addition: 
3665         case Operator.OpType.Subtraction:
3666                 
3667                 break;
3668                 
3669         default :
3670                 Location l = lexer.Location;
3671                 Report.Error (1019, l, "Overloadable unary operator expected"); 
3672                 break;
3673                 
3674         }
3675 }
3676
3677 void CheckBinaryOperator (Operator.OpType op)
3678 {
3679         switch (op) {
3680                 
3681         case Operator.OpType.Addition: 
3682         case Operator.OpType.Subtraction: 
3683         case Operator.OpType.Multiply:
3684         case Operator.OpType.Division:
3685         case Operator.OpType.Modulus: 
3686         case Operator.OpType.BitwiseAnd: 
3687         case Operator.OpType.BitwiseOr:
3688         case Operator.OpType.ExclusiveOr: 
3689         case Operator.OpType.LeftShift: 
3690         case Operator.OpType.RightShift:
3691         case Operator.OpType.Equality: 
3692         case Operator.OpType.Inequality:
3693         case Operator.OpType.GreaterThan: 
3694         case Operator.OpType.LessThan: 
3695         case Operator.OpType.GreaterThanOrEqual:
3696         case Operator.OpType.LessThanOrEqual:
3697                 break;
3698                 
3699         default :
3700                 Location l = lexer.Location;
3701                 Report.Error (1020, l, "Overloadable binary operator expected");
3702                 break;
3703         }
3704         
3705 }
3706
3707 void syntax_error (Location l, string msg)
3708 {
3709         Report.Error (1003, l, "Syntax error, " + msg);
3710 }
3711
3712 void output (string s)
3713 {
3714         Console.WriteLine (s);
3715 }
3716
3717 void note (string s)
3718 {
3719         // Used to put annotations
3720 }
3721
3722 Tokenizer lexer;
3723
3724 public Tokenizer Lexer {
3725         get {
3726                 return lexer;
3727         }
3728 }                  
3729
3730 public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
3731 {
3732         current_namespace = new Namespace (null, "");
3733         this.name = name;
3734         this.input = input;
3735         current_container = RootContext.Tree.Types;
3736         current_container.Namespace = current_namespace;
3737         oob_stack = new Stack ();
3738
3739         lexer = new Tokenizer (input, name, defines);
3740 }
3741
3742 public override int parse ()
3743 {
3744         StringBuilder value = new StringBuilder ();
3745
3746         global_errors = 0;
3747         try {
3748                 if (yacc_verbose_flag)
3749                         yyparse (lexer, new yydebug.yyDebugSimple ());
3750                 else
3751                         yyparse (lexer);
3752         } catch (Exception e){
3753                 // Console.WriteLine ("Fatal error: " + name);
3754                 // Console.WriteLine (lexer.location);
3755
3756                 // 
3757                 // Please do not remove this, it is used during debugging
3758                 // of the grammar
3759                 //
3760                 Console.WriteLine (lexer.location + "  : Parsing error ");
3761                 Console.WriteLine (e);
3762                 global_errors++;
3763         }
3764         
3765         return global_errors;
3766 }
3767
3768 /* end end end */
3769 }