2002-01-16 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                 
762                 if (b == null){
763                         if ((method.ModFlags & (Modifiers.EXTERN | Modifiers.ABSTRACT)) == 0){
764                                 Report.Error (
765                                         501, lexer.Location, "`" + 
766                                         current_container.Name + "." + method.Name + "'" +
767                                         "must declare a body because it is not marked abstract or extern");
768                         }
769                 }
770
771                 method.Block = (Block) $2;
772                 CheckDef (current_container.AddMethod (method), method.Name);
773
774                 current_local_parameters = null;
775           }
776         ;
777
778 opt_error_modifier
779         : /* empty */
780         | modifiers 
781           {
782                 int m = (int) $1;
783                 int i = 1;
784
785                 while (m != 0){
786                         if ((i & m) != 0){
787                                 Report.Error (
788                                         1585, lexer.Location, "Member modifier `" + 
789                                         Modifiers.Name (i) + "' must precede member type and name");
790                         }
791                         m &= ~i;
792                         i = i << 1;
793                 }
794           }
795         ;
796
797 method_header
798         : opt_attributes
799           opt_modifiers
800           type
801           member_name
802           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
803           {
804                 Method method = new Method ((string) $3, (int) $2, (string) $4, 
805                                             (Parameters) $6, (Attributes) $1, lexer.Location);
806
807                 current_local_parameters = (Parameters) $6;
808
809                 $$ = method;
810           }
811         | opt_attributes
812           opt_modifiers
813           VOID
814           member_name
815           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
816           {
817                 Method method = new Method ("System.Void", (int) $2, (string) $4, 
818                                             (Parameters) $6, (Attributes) $1, lexer.Location);
819
820                 current_local_parameters = (Parameters) $6;
821                 $$ = method;
822           }
823         ;
824
825 method_body
826         : block
827         | SEMICOLON             { $$ = null; }
828         ;
829
830 opt_formal_parameter_list
831         : /* empty */                   { $$ = Parameters.GetEmptyReadOnlyParameters (); }
832         | formal_parameter_list
833         ;
834
835 formal_parameter_list
836         : fixed_parameters              
837           { 
838                 ArrayList pars_list = (ArrayList) $1;
839
840                 Parameter [] pars = new Parameter [pars_list.Count];
841                 pars_list.CopyTo (pars);
842
843                 $$ = new Parameters (pars, null, lexer.Location); 
844           } 
845         | fixed_parameters COMMA parameter_array
846           {
847                 ArrayList pars_list = (ArrayList) $1;
848
849                 Parameter [] pars = new Parameter [pars_list.Count];
850                 pars_list.CopyTo (pars);
851
852                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
853           }
854         | parameter_array 
855           {
856                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
857           }
858         ;
859
860 fixed_parameters
861         : fixed_parameter       
862           {
863                 ArrayList pars = new ArrayList ();
864
865                 pars.Add ($1);
866                 $$ = pars;
867           }
868         | fixed_parameters COMMA fixed_parameter
869           {
870                 ArrayList pars = (ArrayList) $1;
871
872                 pars.Add ($3);
873                 $$ = $1;
874           }
875         ;
876
877 fixed_parameter
878         : opt_attributes
879           opt_parameter_modifier
880           type
881           IDENTIFIER
882           {
883                 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
884           }
885         ;
886
887 opt_parameter_modifier
888         : /* empty */           { $$ = Parameter.Modifier.NONE; }
889         | parameter_modifier
890         ;
891
892 parameter_modifier
893         : REF                   { $$ = Parameter.Modifier.REF; }
894         | OUT                   { $$ = Parameter.Modifier.OUT; }
895         ;
896
897 parameter_array
898         : opt_attributes PARAMS type IDENTIFIER
899           { 
900                 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
901                 note ("type must be a single-dimension array type"); 
902           }
903         ;
904
905 member_name 
906         : qualified_identifier
907         ;
908
909 property_declaration
910         : opt_attributes
911           opt_modifiers
912           type member_name
913           OPEN_BRACE 
914           {
915                 implicit_value_parameter_type = (string) $3;
916
917                 lexer.PropertyParsing = true;
918
919                 $$ = lexer.Location;
920           }
921           accessor_declarations 
922           {
923                 lexer.PropertyParsing = false;
924           }
925           CLOSE_BRACE
926           { 
927                 Property prop;
928                 Pair pair = (Pair) $7;
929                 Block get_block = null;
930                 Block set_block = null;
931
932                 if (pair.First != null)
933                         get_block = (Block) pair.First;
934                 if (pair.Second != null)
935                         set_block = (Block) pair.Second;
936
937                 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block,
938                                      (Attributes) $1, (Location) $6);
939                 
940                 CheckDef (current_container.AddProperty (prop), prop.Name);
941                 implicit_value_parameter_type = null;
942           }
943         ;
944
945 accessor_declarations
946         : get_accessor_declaration opt_set_accessor_declaration
947           { 
948                 $$ = new Pair ($1, $2);
949           }
950         | set_accessor_declaration opt_get_accessor_declaration
951           {
952                 $$ = new Pair ($2, $1);
953           }
954         ;
955
956 opt_get_accessor_declaration
957         : /* empty */                   { $$ = null; }
958         | get_accessor_declaration
959         ;
960
961 opt_set_accessor_declaration
962         : /* empty */                   { $$ = null; }
963         | set_accessor_declaration
964         ;
965
966 get_accessor_declaration
967         : opt_attributes GET
968           {
969                 // If this is not the case, then current_local_parameters has already
970                 // been set in indexer_declaration
971                 if (parsing_indexer == false)
972                         current_local_parameters = null;
973                 else 
974                         current_local_parameters = indexer_parameters;
975                 lexer.PropertyParsing = false;
976           }
977           accessor_body
978           {
979                 $$ = $4;
980                 current_local_parameters = null;
981                 lexer.PropertyParsing = true;
982           }
983         ;
984
985 set_accessor_declaration
986         : opt_attributes SET 
987           {
988                 Parameter [] args;
989                 Parameter implicit_value_parameter = new Parameter (
990                         implicit_value_parameter_type, "value", 
991                         Parameter.Modifier.NONE, null);
992
993                 if (parsing_indexer == false) {
994                         args  = new Parameter [1];
995                         args [0] = implicit_value_parameter;
996                 } else {
997                         Parameter [] fp = indexer_parameters.FixedParameters;
998                         int count = fp.Length;
999
1000                         args = new Parameter [count + 1];
1001         
1002                         fp.CopyTo (args, 0);
1003                         args [count] = implicit_value_parameter;
1004                 }
1005                 
1006                 current_local_parameters = new Parameters (args, null, lexer.Location);
1007                 lexer.PropertyParsing = false;
1008           }
1009           accessor_body
1010           {
1011                 $$ = $4;
1012                 current_local_parameters = null;
1013                 lexer.PropertyParsing = true;
1014           }
1015         ;
1016
1017 accessor_body
1018         : block 
1019         | SEMICOLON             { $$ = new Block (null); }
1020         ;
1021
1022 interface_declaration
1023         : opt_attributes
1024           opt_modifiers
1025           INTERFACE IDENTIFIER
1026           {
1027                 Interface new_interface;
1028                 string full_interface_name = MakeName ((string) $4);
1029
1030                 new_interface = new Interface (current_container, full_interface_name, (int) $2, 
1031                                                (Attributes) $1, lexer.Location);
1032                 if (current_interface != null) {
1033                         Location l = lexer.Location;
1034                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
1035                 }
1036                 current_interface = new_interface;
1037                 new_interface.Namespace = current_namespace;
1038                 RootContext.Tree.RecordInterface (full_interface_name, new_interface);
1039           }
1040           opt_interface_base
1041           interface_body
1042           { 
1043                 Interface new_interface = (Interface) current_interface;
1044
1045                 if ($6 != null)
1046                         new_interface.Bases = (ArrayList) $6;
1047
1048                 current_interface = null;
1049                 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
1050           }
1051         ;
1052
1053 opt_interface_base
1054         : /* empty */                     { $$ = null; }
1055         | interface_base
1056         ;
1057
1058 interface_base
1059         : COLON interface_type_list       { $$ = $2; }
1060         ;
1061
1062 interface_type_list
1063         : interface_type
1064           {
1065                 ArrayList interfaces = new ArrayList ();
1066
1067                 interfaces.Add ($1);
1068                 $$ = interfaces;
1069           }
1070         | interface_type_list COMMA interface_type
1071           {
1072                 ArrayList interfaces = (ArrayList) $1;
1073                 interfaces.Add ($3);
1074                 $$ = interfaces;
1075           }
1076         ;
1077
1078 interface_body
1079         : OPEN_BRACE
1080           opt_interface_member_declarations
1081           CLOSE_BRACE
1082         ;
1083
1084 opt_interface_member_declarations
1085         : /* empty */
1086         | interface_member_declarations
1087         ;
1088
1089 interface_member_declarations
1090         : interface_member_declaration
1091         | interface_member_declarations interface_member_declaration
1092         ;
1093
1094 interface_member_declaration
1095         : interface_method_declaration          
1096           { 
1097                 InterfaceMethod m = (InterfaceMethod) $1;
1098
1099                 CheckDef (current_interface.AddMethod (m), m.Name);
1100           }
1101         | interface_property_declaration        
1102           { 
1103                 InterfaceProperty p = (InterfaceProperty) $1;
1104
1105                 CheckDef (current_interface.AddProperty (p), p.Name);
1106           }
1107         | interface_event_declaration 
1108           { 
1109                 InterfaceEvent e = (InterfaceEvent) $1;
1110
1111                 CheckDef (current_interface.AddEvent (e), e.Name);
1112           }
1113         | interface_indexer_declaration
1114           { 
1115                 InterfaceIndexer i = (InterfaceIndexer) $1;
1116
1117                 CheckDef (current_interface.AddIndexer (i), "indexer");
1118           }
1119         ;
1120
1121 opt_new
1122         : /* empty */   { $$ = false; }
1123         | NEW           { $$ = true; }
1124         ;
1125
1126 interface_method_declaration
1127         : opt_attributes opt_new type IDENTIFIER 
1128           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1129           SEMICOLON
1130           {
1131                 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, 
1132                                           (Parameters) $6, (Attributes) $1, lexer.Location);
1133           }
1134         | opt_attributes opt_new VOID IDENTIFIER 
1135           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1136           SEMICOLON
1137           {
1138                 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, 
1139                                           (Attributes) $1, lexer.Location);
1140           }
1141         ;
1142
1143 interface_property_declaration
1144         : opt_attributes
1145           opt_new
1146           type IDENTIFIER 
1147           OPEN_BRACE 
1148           { lexer.PropertyParsing = true; }
1149           interface_accesors 
1150           { lexer.PropertyParsing = false; }
1151           CLOSE_BRACE
1152           {
1153                 int gs = (int) $7;
1154
1155                 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2, 
1156                                             (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1,
1157                                             lexer.Location);
1158           }
1159         ;
1160
1161 interface_accesors
1162         : opt_attributes GET SEMICOLON          { $$ = 1; }
1163         | opt_attributes SET SEMICOLON          { $$ = 2; }
1164         | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON 
1165           { $$ = 3; }
1166         | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
1167           { $$ = 3; }
1168         ;
1169
1170 interface_event_declaration
1171         : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
1172           {
1173                 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
1174           }
1175         ;
1176
1177 interface_indexer_declaration 
1178         : opt_attributes opt_new type THIS 
1179           OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1180           OPEN_BRACE 
1181           { lexer.PropertyParsing = true; }
1182           interface_accesors 
1183           { lexer.PropertyParsing = false; }
1184           CLOSE_BRACE
1185           {
1186                 int a_flags = (int) $10;
1187
1188                 bool do_get = (a_flags & 1) == 1;
1189                 bool do_set = (a_flags & 2) == 2;
1190
1191                 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set,
1192                                            (bool) $2, (Attributes) $1, lexer.Location);
1193           }
1194         ;
1195
1196 operator_declaration
1197         : opt_attributes opt_modifiers operator_declarator block
1198           {
1199                 OperatorDeclaration decl = (OperatorDeclaration) $3;
1200                 
1201                 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
1202                                             decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
1203
1204                 // Note again, checking is done in semantic analysis
1205                 current_container.AddOperator (op);
1206
1207                 current_local_parameters = null;
1208           }
1209         ;
1210
1211 operator_declarator
1212         : type OPERATOR overloadable_operator 
1213           OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1214         {
1215                 Operator.OpType op = (Operator.OpType) $3;
1216                 CheckUnaryOperator (op);
1217
1218                 if (op == Operator.OpType.Addition)
1219                         op = Operator.OpType.UnaryPlus;
1220
1221                 if (op == Operator.OpType.Subtraction)
1222                         op = Operator.OpType.UnaryNegation;
1223
1224                 Parameter [] pars = new Parameter [1];
1225
1226                 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1227
1228                 current_local_parameters = new Parameters (pars, null, lexer.Location);
1229
1230                 $$ = new OperatorDeclaration (op, (string) $1, (string) $5, (string) $6,
1231                                               null, null, lexer.Location);
1232         }
1233         | type OPERATOR overloadable_operator
1234           OPEN_PARENS 
1235                 type IDENTIFIER COMMA
1236                 type IDENTIFIER 
1237           CLOSE_PARENS
1238         {
1239                CheckBinaryOperator ((Operator.OpType) $3);
1240
1241                Parameter [] pars = new Parameter [2];
1242
1243                pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1244                pars [1] = new Parameter ((string) $8, (string) $9, Parameter.Modifier.NONE, null);
1245
1246                current_local_parameters = new Parameters (pars, null, lexer.Location);
1247                
1248                $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
1249                                              (string) $8, (string) $9, lexer.Location);
1250         }
1251         | conversion_operator_declarator
1252         ;
1253
1254 overloadable_operator
1255 // Unary operators:
1256         : BANG   { $$ = Operator.OpType.LogicalNot; }
1257         | TILDE  { $$ = Operator.OpType.OnesComplement; }  
1258         | OP_INC { $$ = Operator.OpType.Increment; }
1259         | OP_DEC { $$ = Operator.OpType.Decrement; }
1260         | TRUE   { $$ = Operator.OpType.True; }
1261         | FALSE  { $$ = Operator.OpType.False; }
1262 // Unary and binary:
1263         | PLUS { $$ = Operator.OpType.Addition; }
1264         | MINUS { $$ = Operator.OpType.Subtraction; }
1265 // Binary:
1266         | STAR { $$ = Operator.OpType.Multiply; }
1267         | DIV {  $$ = Operator.OpType.Division; }
1268         | PERCENT { $$ = Operator.OpType.Modulus; }
1269         | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
1270         | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
1271         | CARRET { $$ = Operator.OpType.ExclusiveOr; }
1272         | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
1273         | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
1274         | OP_EQ { $$ = Operator.OpType.Equality; }
1275         | OP_NE { $$ = Operator.OpType.Inequality; }
1276         | OP_GT { $$ = Operator.OpType.GreaterThan; }
1277         | OP_LT { $$ = Operator.OpType.LessThan; }
1278         | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
1279         | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
1280         ;
1281
1282 conversion_operator_declarator
1283         : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1284           {
1285                 Parameter [] pars = new Parameter [1];
1286
1287                 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1288
1289                 current_local_parameters = new Parameters (pars, null, lexer.Location);  
1290                   
1291                 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
1292                                               null, null, lexer.Location);
1293           }
1294         | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1295           {
1296                 Parameter [] pars = new Parameter [1];
1297
1298                 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1299
1300                 current_local_parameters = new Parameters (pars, null, lexer.Location);  
1301                   
1302                 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
1303                                               null, null, lexer.Location);
1304           }
1305         | IMPLICIT error 
1306           {
1307                 syntax_error (lexer.Location, "'operator' expected");
1308           }
1309         | EXPLICIT error 
1310           {
1311                 syntax_error (lexer.Location, "'operator' expected");
1312           }
1313         ;
1314
1315 constructor_declaration
1316         : opt_attributes
1317           opt_modifiers
1318           constructor_declarator
1319           block
1320           { 
1321                 Constructor c = (Constructor) $3;
1322                 c.Block = (Block) $4;
1323                 c.ModFlags = (int) $2;
1324                 c.OptAttributes = (Attributes) $1;
1325
1326                 if ((c.ModFlags & Modifiers.STATIC) != 0){
1327                         if ((c.ModFlags & Modifiers.Accessibility) != 0) {
1328                                 Location l = lexer.Location;
1329                                 Report.Error (515, l, "Access modifiers are not allowed on static constructors");
1330                         }
1331
1332                         if (c.Initializer != null){
1333                                 Location l = lexer.Location;
1334                                 Report.Error (514, l, "Static constructors can not have an explicit this or base constructor invocations");
1335                         }
1336
1337                         if (!c.Parameters.Empty){
1338                                 Location l = lexer.Location;
1339                                 Report.Error (132, l, "Static constructors should not have parameters");
1340                         }
1341                 } 
1342                 
1343                 CheckDef (current_container.AddConstructor (c), c.Name);
1344
1345                 current_local_parameters = null;
1346           }
1347         ;
1348
1349 constructor_declarator
1350         : IDENTIFIER 
1351           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
1352           {
1353                 oob_stack.Push (lexer.Location);
1354
1355                 current_local_parameters = (Parameters) $3;
1356           }
1357           opt_constructor_initializer
1358           {
1359                 Location l = (Location) oob_stack.Pop ();
1360                 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $6, l);
1361           }
1362         ;
1363
1364 opt_constructor_initializer
1365         : /* empty */                   { $$ = null; }
1366         | constructor_initializer
1367         ;
1368
1369 constructor_initializer
1370         : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1371           {
1372                 $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
1373           }
1374         | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1375           {
1376                 $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
1377           }
1378         ;
1379
1380 destructor_declaration
1381         : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1382           {
1383                 if ((string) $3 != current_container.Basename){
1384                         Report.Error (574, lexer.Location, "Name of destructor must match name of class");
1385                 } else if (!(current_container is Class)){
1386                         Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
1387                 } else {
1388                         Location l = lexer.Location;
1389
1390                         Method d = new Method (
1391                                 "System.Void", 0, "Finalize", 
1392                                 new Parameters (null, null, l), (Attributes) $1, l);
1393                   
1394                         d.Block = (Block) $6;
1395                         CheckDef (current_container.AddMethod (d), d.Name);
1396                 }
1397           }
1398         ;
1399
1400 event_declaration
1401         : opt_attributes
1402           opt_modifiers
1403           EVENT type variable_declarators SEMICOLON
1404           {
1405                 foreach (VariableDeclaration var in (ArrayList) $5) {
1406
1407                         Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
1408                                              (int) $2, null, null, (Attributes) $1, lexer.Location);
1409
1410                         CheckDef (current_container.AddEvent (e), e.Name);
1411                                        
1412                 }
1413           }
1414         | opt_attributes
1415           opt_modifiers
1416           EVENT type member_name
1417           OPEN_BRACE
1418           {
1419                 implicit_value_parameter_type = (string) $4;  
1420                 lexer.EventParsing = true;
1421           }
1422           event_accessor_declarations
1423           {
1424                 lexer.EventParsing = false;  
1425           }
1426           CLOSE_BRACE
1427           {
1428                 Pair pair = (Pair) $8;
1429                 Block add_block = null;
1430                 Block rem_block = null;
1431
1432                 if (pair.First != null)
1433                         add_block = (Block) pair.First;
1434                 if (pair.Second != null)
1435                         rem_block = (Block) pair.Second;
1436                 
1437                 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block,
1438                                      (Attributes) $1, lexer.Location);
1439                 
1440                 CheckDef (current_container.AddEvent (e), e.Name);
1441                 implicit_value_parameter_type = null;
1442           }
1443         ;
1444
1445 event_accessor_declarations
1446         : add_accessor_declaration remove_accessor_declaration
1447         {
1448                 $$ = new Pair ($1, $2);
1449         }
1450         | remove_accessor_declaration add_accessor_declaration
1451         {
1452                 $$ = new Pair ($2, $1);
1453         }       
1454         ;
1455
1456 add_accessor_declaration
1457         : opt_attributes ADD
1458           {
1459                 Parameter [] args = new Parameter [1];
1460                 Parameter implicit_value_parameter = new Parameter (
1461                         implicit_value_parameter_type, "value", 
1462                         Parameter.Modifier.NONE, null);
1463
1464                 args [0] = implicit_value_parameter;
1465                 
1466                 current_local_parameters = new Parameters (args, null, lexer.Location);  
1467                 lexer.EventParsing = false;
1468           }
1469           block
1470           {
1471                 $$ = $4;
1472                 lexer.EventParsing = true;
1473           }
1474         ;
1475
1476 remove_accessor_declaration
1477         : opt_attributes REMOVE
1478           {
1479                 Parameter [] args = new Parameter [1];
1480                 Parameter implicit_value_parameter = new Parameter (
1481                         implicit_value_parameter_type, "value", 
1482                         Parameter.Modifier.NONE, null);
1483
1484                 args [0] = implicit_value_parameter;
1485                 
1486                 current_local_parameters = new Parameters (args, null, lexer.Location);  
1487                 lexer.EventParsing = false;
1488           }
1489           block
1490           {
1491                 $$ = $4;
1492                 lexer.EventParsing = true;
1493           }
1494         ;
1495
1496 indexer_declaration
1497         : opt_attributes opt_modifiers indexer_declarator 
1498           OPEN_BRACE 
1499           {
1500                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1501
1502                 implicit_value_parameter_type = decl.type;
1503                 
1504                 lexer.PropertyParsing = true;
1505                 parsing_indexer  = true;
1506                 
1507                 indexer_parameters = decl.param_list;
1508                 $$ = lexer.Location;
1509           }
1510           accessor_declarations 
1511           {
1512                   lexer.PropertyParsing = false;
1513                   parsing_indexer  = false;
1514           }
1515           CLOSE_BRACE
1516           { 
1517                 // The signature is computed from the signature of the indexer.  Look
1518                 // at section 3.6 on the spec
1519
1520                 Indexer indexer;
1521                 IndexerDeclaration decl = (IndexerDeclaration) $3;
1522                 Pair pair = (Pair) $6;
1523                 Block get_block = null;
1524                 Block set_block = null;
1525
1526                 if (pair.First != null)
1527                         get_block = (Block) pair.First;
1528                 if (pair.Second != null)
1529                         set_block = (Block) pair.Second;
1530
1531                 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
1532                                        get_block, set_block, (Attributes) $1, (Location) $5);
1533
1534                 // Note that there is no equivalent of CheckDef for this case
1535                 // We shall handle this in semantic analysis
1536                 
1537                 current_container.AddIndexer (indexer);
1538                 
1539                 current_local_parameters = null;
1540                 implicit_value_parameter_type = null;
1541                 indexer_parameters = null;
1542           }
1543         ;
1544
1545 indexer_declarator
1546         : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1547           {
1548                 Parameters pars = (Parameters) $4;
1549
1550                 if (pars.FixedParameters == null){
1551                         Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1552                 }
1553
1554                 $$ = new IndexerDeclaration ((string) $1, null, pars);
1555           }
1556         | type qualified_identifier DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1557           {
1558                 Parameters pars = (Parameters) $6;
1559
1560                 if (pars.FixedParameters == null){
1561                         Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1562                 }
1563                 $$ = new IndexerDeclaration ((string) $1, (string) $2, pars);
1564           }
1565         ;
1566
1567 enum_declaration
1568         : opt_attributes
1569           opt_modifiers
1570           ENUM IDENTIFIER
1571           opt_enum_base
1572           enum_body
1573           opt_semicolon
1574           { 
1575                 string full_name = MakeName ((string) $4);
1576                 Enum e = new Enum (current_container, (string) $5, (int) $2, full_name, (Attributes) $1, lexer.Location);
1577
1578                 foreach (VariableDeclaration ev in (ArrayList) $6){
1579                         CheckDef (e.AddEnumMember (ev.identifier, 
1580                                                    (Expression) ev.expression_or_array_initializer,
1581                                                    (Location) ev.Location),
1582                                   ev.identifier);
1583                 }
1584
1585                 CheckDef (current_container.AddEnum (e), name);
1586           }
1587         ;
1588
1589 opt_enum_base
1590         : /* empty */           { $$ = "System.Int32"; }
1591         | COLON type            { $$ = $2;   }
1592         ;
1593
1594 enum_body
1595         : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1596           {
1597                 $$ = $2;
1598           }
1599         ;
1600
1601 opt_enum_member_declarations
1602         : /* empty */                   { $$ = new ArrayList (); }
1603         | enum_member_declarations opt_comma { $$ = $1; }
1604         ;
1605
1606 enum_member_declarations
1607         : enum_member_declaration 
1608           {
1609                 ArrayList l = new ArrayList ();
1610
1611                 l.Add ($1);
1612                 $$ = l;
1613           }
1614         | enum_member_declarations COMMA enum_member_declaration
1615           {
1616                 ArrayList l = (ArrayList) $1;
1617
1618                 l.Add ($3);
1619
1620                 $$ = l;
1621           }
1622         ;
1623
1624 enum_member_declaration
1625         : opt_attributes IDENTIFIER 
1626           {
1627                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
1628           }
1629         | opt_attributes IDENTIFIER
1630           {
1631                   $$ = lexer.Location;
1632           }
1633           ASSIGN expression
1634           { 
1635                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location);
1636           }
1637         ;
1638
1639 delegate_declaration
1640         : opt_attributes
1641           opt_modifiers
1642           DELEGATE type   
1643           IDENTIFIER OPEN_PARENS 
1644           opt_formal_parameter_list
1645           CLOSE_PARENS 
1646           SEMICOLON
1647           {
1648                 Delegate del = new Delegate ((string) $4, (int) $2, 
1649                                              MakeName ((string) $5), (Parameters) $7, 
1650                                              (Attributes) $1, lexer.Location);
1651                   
1652                 CheckDef (current_container.AddDelegate (del), del.Name);
1653           }     
1654         | opt_attributes
1655           opt_modifiers
1656           DELEGATE VOID   
1657           IDENTIFIER OPEN_PARENS 
1658           opt_formal_parameter_list
1659           CLOSE_PARENS 
1660           SEMICOLON
1661           {
1662                 Delegate del = new Delegate ("System.Void", (int) $2, (string) $5, (Parameters) $7, 
1663                                              (Attributes) $1, lexer.Location);
1664
1665                 CheckDef (current_container.AddDelegate (del), del.Name);
1666           }
1667         ;
1668
1669 type_name
1670         : namespace_or_type_name
1671         ;
1672
1673 namespace_or_type_name
1674         : qualified_identifier
1675         ;
1676
1677 /* 
1678  * Before you think of adding a return_type, notice that we have been
1679  * using two rules in the places where it matters (one rule using type
1680  * and another identical one that uses VOID as the return type).  This
1681  * gets rid of a shift/reduce couple
1682  */
1683 type
1684         : type_name {   /* class_type */
1685                 /* 
1686                    This does interfaces, delegates, struct_types, class_types, 
1687                    parent classes, and more! 4.2 
1688                  */
1689                 $$ = $1; 
1690           }
1691         | builtin_types
1692         | array_type
1693         | pointer_type    
1694         ;
1695
1696
1697 pointer_type
1698         : type STAR
1699           {
1700                 //
1701                 // Note that here only unmanaged types are allowed but we
1702                 // can't perform checks during this phase - we do it during
1703                 // semantic analysis.
1704                 //
1705                 $$ = (string) $1 + "*";
1706           }
1707         | VOID STAR
1708           {
1709                 $$ = "System.Void*";
1710           }
1711         ;
1712
1713 non_expression_type
1714         : builtin_types 
1715           {
1716                 $$ = new SimpleName ((string) $1, lexer.Location);
1717           }
1718         | non_expression_type rank_specifier
1719           {
1720                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1721           }
1722         | expression rank_specifiers 
1723           {
1724                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1725           }
1726         ;
1727
1728 type_list
1729         : type
1730           {
1731                 ArrayList types = new ArrayList ();
1732
1733                 types.Add ($1);
1734                 $$ = types;
1735           }
1736         | type_list COMMA type
1737           {
1738                 ArrayList types = (ArrayList) $1;
1739
1740                 types.Add ($3);
1741                 $$ = types;
1742           }
1743         ;
1744
1745 /*
1746  * replaces all the productions for isolating the various
1747  * simple types, but we need this to reuse it easily in local_variable_type
1748  */
1749 builtin_types
1750         : OBJECT        { $$ = "System.Object"; }
1751         | STRING        { $$ = "System.String"; }
1752         | BOOL          { $$ = "System.Boolean"; }
1753         | DECIMAL       { $$ = "System.Decimal"; }
1754         | FLOAT         { $$ = "System.Single"; }
1755         | DOUBLE        { $$ = "System.Double"; }
1756         | integral_type
1757         ;
1758
1759 integral_type
1760         : SBYTE         { $$ = "System.SByte"; }
1761         | BYTE          { $$ = "System.Byte"; }
1762         | SHORT         { $$ = "System.Int16"; }
1763         | USHORT        { $$ = "System.UInt16"; }
1764         | INT           { $$ = "System.Int32"; }
1765         | UINT          { $$ = "System.UInt32"; }
1766         | LONG          { $$ = "System.Int64"; }
1767         | ULONG         { $$ = "System.UInt64"; }
1768         | CHAR          { $$ = "System.Char"; }
1769         ;
1770
1771 interface_type
1772         : type_name
1773         ;
1774
1775 array_type
1776         : type rank_specifiers
1777           {
1778                   $$ = (string) $1 + (string) $2;
1779           }
1780         ;
1781
1782 //
1783 // Expressions, section 7.5
1784 //
1785 primary_expression
1786         : literal
1787           {
1788                 // 7.5.1: Literals
1789           }
1790  
1791         | qualified_identifier
1792           {
1793                 string name = (string) $1;
1794
1795                 $$ = null;
1796                 $$ = DecomposeQI (name, lexer.Location);
1797           }
1798         | parenthesized_expression
1799         | member_access
1800         | invocation_expression
1801         | element_access
1802         | this_access
1803         | base_access
1804         | post_increment_expression
1805         | post_decrement_expression
1806         | new_expression
1807         | typeof_expression
1808         | sizeof_expression
1809         | checked_expression
1810         | unchecked_expression
1811         ;
1812
1813 literal
1814         : boolean_literal
1815         | integer_literal
1816         | real_literal
1817         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
1818         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
1819         | NULL                  { $$ = NullLiteral.Null; }
1820         ;
1821
1822 real_literal
1823         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
1824         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
1825         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1826         ;
1827
1828 integer_literal
1829         : LITERAL_INTEGER       { 
1830                 object v = lexer.Value;
1831
1832                 // 
1833                 // FIXME: Possible optimization would be to 
1834                 // compute the *Literal objects directly in the scanner
1835                 //
1836                 if (v is int)
1837                         $$ = new IntLiteral ((Int32) v); 
1838                 else if (v is uint)
1839                         $$ = new UIntLiteral ((UInt32) v);
1840                 else if (v is long)
1841                         $$ = new LongLiteral ((Int64) v);
1842                 else if (v is ulong)
1843                         $$ = new ULongLiteral ((UInt64) v);
1844                 else
1845                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
1846           }
1847         ;
1848
1849 boolean_literal
1850         : TRUE                  { $$ = new BoolLiteral (true); }
1851         | FALSE                 { $$ = new BoolLiteral (false); }
1852         ;
1853
1854 parenthesized_expression
1855         : OPEN_PARENS expression CLOSE_PARENS
1856           { $$ = $2; }
1857         ;
1858
1859 member_access
1860         : primary_expression DOT IDENTIFIER
1861           {
1862                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1863           }
1864         | predefined_type DOT IDENTIFIER
1865           {
1866                 $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
1867           }
1868         ;
1869
1870 predefined_type
1871         : builtin_types
1872         ;
1873
1874 invocation_expression
1875         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
1876           {
1877                 if ($1 == null) {
1878                         Location l = lexer.Location;
1879                         Report.Error (1, l, "THIS IS CRAZY");
1880                 }
1881                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
1882           }
1883         ; 
1884
1885 opt_argument_list
1886         : /* empty */           { $$ = null; }
1887         | argument_list
1888         ;
1889
1890 argument_list
1891         : argument              
1892           { 
1893                 ArrayList list = new ArrayList ();
1894                 list.Add ($1);
1895                 $$ = list;
1896           }
1897         | argument_list COMMA argument
1898           {
1899                 ArrayList list = (ArrayList) $1;
1900                 list.Add ($3);
1901                 $$ = list;
1902           }
1903         ;
1904
1905 argument
1906         : expression
1907           {
1908                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
1909           }
1910         | REF variable_reference 
1911           { 
1912                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
1913           }
1914         | OUT variable_reference 
1915           { 
1916                 $$ = new Argument ((Expression) $2, Argument.AType.Out);
1917           }
1918         ;
1919
1920 variable_reference
1921         : expression { note ("section 5.4"); $$ = $1; }
1922         ;
1923
1924 element_access
1925         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
1926           {
1927                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
1928           }
1929         | primary_expression rank_specifiers
1930           {
1931                 // So the super-trick is that primary_expression
1932                 // can only be either a SimpleName or a MemberAccess. 
1933                 // The MemberAccess case arises when you have a fully qualified type-name like :
1934                 // Foo.Bar.Blah i;
1935                 // SimpleName is when you have
1936                 // Blah i;
1937                   
1938                 Expression expr = (Expression) $1;  
1939                 if (!(expr is SimpleName || expr is MemberAccess)) {
1940                         Location l = lexer.Location;
1941                         Report.Error (-1, l, "Invalid Type definition");
1942                         $$ = "System.Object";
1943                 }
1944                 
1945                 //
1946                 // So we extract the string corresponding to the SimpleName
1947                 // or MemberAccess
1948                 // 
1949                 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
1950           }
1951         ;
1952
1953 expression_list
1954         : expression
1955           {
1956                 ArrayList list = new ArrayList ();
1957                 list.Add ($1);
1958                 $$ = list;
1959           }
1960         | expression_list COMMA expression
1961           {
1962                 ArrayList list = (ArrayList) $1;
1963                 list.Add ($3);
1964                 $$ = list;
1965           }
1966         ;
1967
1968 this_access
1969         : THIS
1970           {
1971                 $$ = new This (lexer.Location);
1972           }
1973         ;
1974
1975 base_access
1976         : BASE DOT IDENTIFIER
1977           {
1978                 $$ = new BaseAccess ((string) $3, lexer.Location);
1979           }
1980         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
1981           {
1982                 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
1983           }
1984         ;
1985
1986 post_increment_expression
1987         : primary_expression OP_INC
1988           {
1989                 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
1990                                        (Expression) $1, lexer.Location);
1991           }
1992         ;
1993
1994 post_decrement_expression
1995         : primary_expression OP_DEC
1996           {
1997                 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
1998                                        (Expression) $1, lexer.Location);
1999           }
2000         ;
2001
2002 new_expression
2003         : object_or_delegate_creation_expression
2004         | array_creation_expression
2005         ;
2006
2007 object_or_delegate_creation_expression
2008         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2009           {
2010                 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
2011           }
2012         ;
2013
2014 array_creation_expression
2015         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
2016           opt_rank_specifier
2017           opt_array_initializer
2018           {
2019                 $$ = new ArrayCreation ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, 
2020                                         lexer.Location);
2021           }
2022         | NEW type rank_specifiers array_initializer
2023           {
2024                 $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
2025           }
2026         | NEW type error 
2027           {
2028                 Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
2029           }
2030         ;
2031
2032 opt_rank_specifier
2033         : /* empty */
2034           {
2035                   $$ = "";
2036           }
2037         | rank_specifiers
2038           {
2039                         $$ = $1;
2040           }
2041         ;
2042
2043 rank_specifiers
2044         : rank_specifier
2045           {
2046                   $$ = $1;
2047           }
2048         | rank_specifiers rank_specifier
2049           {
2050                   $$ = (string) $2 + (string) $1;
2051           }             
2052         ;
2053
2054 rank_specifier
2055         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2056           {
2057                 $$ = "[" + (string) $2 + "]";
2058           }
2059         ;
2060
2061 opt_dim_separators
2062         : /* empty */
2063           {
2064                 $$ = "";
2065           }
2066         | dim_separators
2067           {
2068                   $$ = $1;
2069           }               
2070         ;
2071
2072 dim_separators
2073         : COMMA
2074           {
2075                 $$ = ",";
2076           }
2077         | dim_separators COMMA
2078           {
2079                 $$ = (string) $1 + ",";
2080           }
2081         ;
2082
2083 opt_array_initializer
2084         : /* empty */
2085           {
2086                 $$ = null;
2087           }
2088         | array_initializer
2089           {
2090                 $$ = $1;
2091           }
2092         ;
2093
2094 array_initializer
2095         : OPEN_BRACE CLOSE_BRACE
2096           {
2097                 ArrayList list = new ArrayList ();
2098                 $$ = list;
2099           }
2100         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
2101           {
2102                 $$ = (ArrayList) $2;
2103           }
2104         ;
2105
2106 variable_initializer_list
2107         : variable_initializer
2108           {
2109                 ArrayList list = new ArrayList ();
2110                 list.Add ($1);
2111                 $$ = list;
2112           }
2113         | variable_initializer_list COMMA variable_initializer
2114           {
2115                 ArrayList list = (ArrayList) $1;
2116                 list.Add ($3);
2117                 $$ = list;
2118           }
2119         ;
2120
2121 typeof_expression
2122         : TYPEOF OPEN_PARENS type CLOSE_PARENS
2123           {
2124                 $$ = new TypeOf ((string) $3, lexer.Location);
2125           }
2126         ;
2127
2128 sizeof_expression
2129         : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
2130                 $$ = new SizeOf ((string) $3);
2131
2132                 note ("Verify type is unmanaged"); 
2133                 note ("if (5.8) builtin, yield constant expression");
2134           }
2135         ;
2136
2137 checked_expression
2138         : CHECKED OPEN_PARENS expression CLOSE_PARENS
2139           {
2140                 $$ = new CheckedExpr ((Expression) $3);
2141           }
2142         ;
2143
2144 unchecked_expression
2145         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2146           {
2147                 $$ = new UnCheckedExpr ((Expression) $3);
2148           }
2149         ;
2150
2151 unary_expression
2152         : primary_expression
2153         | BANG prefixed_unary_expression
2154           {
2155                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2156           }
2157         | TILDE prefixed_unary_expression
2158           {
2159                 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2160           }
2161         | OPEN_PARENS expression CLOSE_PARENS unary_expression
2162           {
2163                   $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2164           }
2165         | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2166           {
2167                   $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2168           }
2169         ;
2170
2171         //
2172         // The idea to split this out is from Rhys' grammar
2173         // to solve the problem with casts.
2174         //
2175 prefixed_unary_expression
2176         : unary_expression
2177         | PLUS prefixed_unary_expression
2178           { 
2179                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2180           } 
2181         | MINUS prefixed_unary_expression 
2182           { 
2183                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2184           }
2185         | OP_INC prefixed_unary_expression 
2186           {
2187                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2188                                        (Expression) $2, lexer.Location);
2189           }
2190         | OP_DEC prefixed_unary_expression 
2191           {
2192                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2193                                        (Expression) $2, lexer.Location);
2194           }
2195         | STAR prefixed_unary_expression
2196           {
2197                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2198           }
2199         | BITWISE_AND prefixed_unary_expression
2200           {
2201                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2202           }
2203         ;
2204
2205 pre_increment_expression
2206         : OP_INC prefixed_unary_expression 
2207           {
2208                 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2209                                        (Expression) $2, lexer.Location);
2210           }
2211         ;
2212
2213 pre_decrement_expression
2214         : OP_DEC prefixed_unary_expression 
2215           {
2216                 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2217                                        (Expression) $2, lexer.Location);
2218           }
2219         ;
2220
2221 multiplicative_expression
2222         : prefixed_unary_expression
2223         | multiplicative_expression STAR prefixed_unary_expression
2224           {
2225                 $$ = new Binary (Binary.Operator.Multiply, 
2226                                  (Expression) $1, (Expression) $3, lexer.Location);
2227           }
2228         | multiplicative_expression DIV prefixed_unary_expression
2229           {
2230                 $$ = new Binary (Binary.Operator.Division, 
2231                                  (Expression) $1, (Expression) $3, lexer.Location);
2232           }
2233         | multiplicative_expression PERCENT prefixed_unary_expression 
2234           {
2235                 $$ = new Binary (Binary.Operator.Modulus, 
2236                                  (Expression) $1, (Expression) $3, lexer.Location);
2237           }
2238         ;
2239
2240 additive_expression
2241         : multiplicative_expression
2242         | additive_expression PLUS multiplicative_expression 
2243           {
2244                 $$ = new Binary (Binary.Operator.Addition, 
2245                                  (Expression) $1, (Expression) $3, lexer.Location);
2246           }
2247         | additive_expression MINUS multiplicative_expression
2248           {
2249                 $$ = new Binary (Binary.Operator.Subtraction, 
2250                                  (Expression) $1, (Expression) $3, lexer.Location);
2251           }
2252         ;
2253
2254 shift_expression
2255         : additive_expression
2256         | shift_expression OP_SHIFT_LEFT additive_expression
2257           {
2258                 $$ = new Binary (Binary.Operator.LeftShift, 
2259                                  (Expression) $1, (Expression) $3, lexer.Location);
2260           }
2261         | shift_expression OP_SHIFT_RIGHT additive_expression
2262           {
2263                 $$ = new Binary (Binary.Operator.RightShift, 
2264                                  (Expression) $1, (Expression) $3, lexer.Location);
2265           }
2266         ; 
2267
2268 relational_expression
2269         : shift_expression
2270         | relational_expression OP_LT shift_expression
2271           {
2272                 $$ = new Binary (Binary.Operator.LessThan, 
2273                                  (Expression) $1, (Expression) $3, lexer.Location);
2274           }
2275         | relational_expression OP_GT shift_expression
2276           {
2277                 $$ = new Binary (Binary.Operator.GreaterThan, 
2278                                  (Expression) $1, (Expression) $3, lexer.Location);
2279           }
2280         | relational_expression OP_LE shift_expression
2281           {
2282                 $$ = new Binary (Binary.Operator.LessThanOrEqual, 
2283                                  (Expression) $1, (Expression) $3, lexer.Location);
2284           }
2285         | relational_expression OP_GE shift_expression
2286           {
2287                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
2288                                  (Expression) $1, (Expression) $3, lexer.Location);
2289           }
2290         | relational_expression IS type
2291           {
2292                 $$ = new Is ((Expression) $1, (string) $3, lexer.Location);
2293           }
2294         | relational_expression AS type
2295           {
2296                 $$ = new As ((Expression) $1, (string) $3, lexer.Location);
2297           }
2298         ;
2299
2300 equality_expression
2301         : relational_expression
2302         | equality_expression OP_EQ relational_expression
2303           {
2304                 $$ = new Binary (Binary.Operator.Equality, 
2305                                  (Expression) $1, (Expression) $3, lexer.Location);
2306           }
2307         | equality_expression OP_NE relational_expression
2308           {
2309                 $$ = new Binary (Binary.Operator.Inequality, 
2310                                  (Expression) $1, (Expression) $3, lexer.Location);
2311           }
2312         ; 
2313
2314 and_expression
2315         : equality_expression
2316         | and_expression BITWISE_AND equality_expression
2317           {
2318                 $$ = new Binary (Binary.Operator.BitwiseAnd, 
2319                                  (Expression) $1, (Expression) $3, lexer.Location);
2320           }
2321         ;
2322
2323 exclusive_or_expression
2324         : and_expression
2325         | exclusive_or_expression CARRET and_expression
2326           {
2327                 $$ = new Binary (Binary.Operator.ExclusiveOr, 
2328                                  (Expression) $1, (Expression) $3, lexer.Location);
2329           }
2330         ;
2331
2332 inclusive_or_expression
2333         : exclusive_or_expression
2334         | inclusive_or_expression BITWISE_OR exclusive_or_expression
2335           {
2336                 $$ = new Binary (Binary.Operator.BitwiseOr, 
2337                                  (Expression) $1, (Expression) $3, lexer.Location);
2338           }
2339         ;
2340
2341 conditional_and_expression
2342         : inclusive_or_expression
2343         | conditional_and_expression OP_AND inclusive_or_expression
2344           {
2345                 $$ = new Binary (Binary.Operator.LogicalAnd, 
2346                                  (Expression) $1, (Expression) $3, lexer.Location);
2347           }
2348         ;
2349
2350 conditional_or_expression
2351         : conditional_and_expression
2352         | conditional_or_expression OP_OR conditional_and_expression
2353           {
2354                 $$ = new Binary (Binary.Operator.LogicalOr, 
2355                                  (Expression) $1, (Expression) $3, lexer.Location);
2356           }
2357         ;
2358
2359 conditional_expression
2360         : conditional_or_expression
2361         | conditional_or_expression INTERR expression COLON expression 
2362           {
2363                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2364           }
2365         ;
2366
2367 assignment_expression
2368         : prefixed_unary_expression ASSIGN expression
2369           {
2370                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2371           }
2372         | prefixed_unary_expression OP_MULT_ASSIGN expression
2373           {
2374                 Location l = lexer.Location;
2375
2376                 $$ = new Assign ((Expression) $1,
2377                                  new Binary (Binary.Operator.Multiply, 
2378                                              (Expression) $1,
2379                                              (Expression) $3, l), l);
2380           }
2381         | prefixed_unary_expression OP_DIV_ASSIGN expression
2382           {
2383                 Location l = lexer.Location;
2384
2385                 $$ = new Assign ((Expression) $1,
2386                                  new Binary (Binary.Operator.Division, 
2387                                              (Expression) $1,
2388                                              (Expression) $3, l), l);
2389           }
2390         | prefixed_unary_expression OP_MOD_ASSIGN expression
2391           {
2392                 Location l = lexer.Location;
2393
2394                 $$ = new Assign ((Expression) $1,
2395                                  new Binary (Binary.Operator.Modulus, 
2396                                              (Expression) $1,
2397                                              (Expression) $3, l), l);
2398           }
2399         | prefixed_unary_expression OP_ADD_ASSIGN expression
2400           {
2401                 Location l = lexer.Location;
2402
2403                 $$ = new Assign ((Expression) $1,
2404                                  new Binary (Binary.Operator.Addition, 
2405                                              (Expression) $1,
2406                                              (Expression) $3, l), l);
2407           }
2408         | prefixed_unary_expression OP_SUB_ASSIGN expression
2409           {
2410                 Location l = lexer.Location;
2411
2412                 $$ = new Assign ((Expression) $1,
2413                                  new Binary (Binary.Operator.Subtraction, 
2414                                              (Expression) $1,
2415                                              (Expression) $3, l), l);
2416           }
2417         | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2418           {
2419                 Location l = lexer.Location;
2420
2421                 $$ = new Assign ((Expression) $1,
2422                                  new Binary (Binary.Operator.LeftShift, 
2423                                              (Expression) $1,
2424                                              (Expression) $3, l), l);
2425           }
2426         | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2427           {
2428                 Location l = lexer.Location;
2429
2430                 $$ = new Assign ((Expression) $1,
2431                                  new Binary (Binary.Operator.RightShift, 
2432                                              (Expression) $1,
2433                                              (Expression) $3, l), l);
2434           }
2435         | prefixed_unary_expression OP_AND_ASSIGN expression
2436           {
2437                 Location l = lexer.Location;
2438
2439                 $$ = new Assign ((Expression) $1,
2440                                  new Binary (Binary.Operator.BitwiseAnd, 
2441                                              (Expression) $1,
2442                                              (Expression) $3, l), l);
2443           }
2444         | prefixed_unary_expression OP_OR_ASSIGN expression
2445           {
2446                 Location l = lexer.Location;
2447
2448                 $$ = new Assign ((Expression) $1,
2449                                  new Binary (Binary.Operator.BitwiseOr, 
2450                                              (Expression) $1,
2451                                              (Expression) $3, l), l);
2452           }
2453         | prefixed_unary_expression OP_XOR_ASSIGN expression
2454           {
2455                 Location l = lexer.Location;
2456
2457                 $$ = new Assign ((Expression) $1,
2458                                  new Binary (Binary.Operator.ExclusiveOr, 
2459                                              (Expression) $1,
2460                                              (Expression) $3, l), l);
2461           }
2462         ;
2463
2464 expression
2465         : conditional_expression
2466         | assignment_expression
2467         ;
2468
2469 constant_expression
2470         : expression
2471         ;
2472
2473 boolean_expression
2474         : expression
2475         ;
2476
2477 //
2478 // 10 classes
2479 //
2480 class_declaration
2481         : opt_attributes
2482           opt_modifiers
2483           CLASS IDENTIFIER
2484           {
2485                 Class new_class;
2486                 string name;
2487
2488                 name = MakeName ((string) $4);
2489
2490                 new_class = new Class (current_container, name, (int) $2, 
2491                                        (Attributes) $1, lexer.Location);
2492                 current_container = new_class;
2493                 current_container.Namespace = current_namespace;
2494                 RootContext.Tree.RecordClass (name, new_class);
2495           }
2496           opt_class_base
2497           class_body 
2498           opt_semicolon 
2499           {
2500                 Class new_class = (Class) current_container;
2501
2502                 if ($6 != null)
2503                         new_class.Bases = (ArrayList) $6;
2504
2505                 current_container = current_container.Parent;
2506                 CheckDef (current_container.AddClass (new_class), new_class.Name);
2507
2508                 $$ = new_class;
2509           }
2510         ;       
2511
2512 opt_modifiers
2513         : /* empty */           { $$ = (int) 0; }
2514         | modifiers
2515         ;
2516
2517 modifiers
2518         : modifier
2519         | modifiers modifier
2520           { 
2521                 int m1 = (int) $1;
2522                 int m2 = (int) $2;
2523
2524                 if ((m1 & m2) != 0) {
2525                         Location l = lexer.Location;
2526                         Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2527                 }
2528                 $$ = (int) (m1 | m2);
2529           }
2530         ;
2531
2532 modifier
2533         : NEW                   { $$ = Modifiers.NEW; }
2534         | PUBLIC                { $$ = Modifiers.PUBLIC; }
2535         | PROTECTED             { $$ = Modifiers.PROTECTED; }
2536         | INTERNAL              { $$ = Modifiers.INTERNAL; }
2537         | PRIVATE               { $$ = Modifiers.PRIVATE; }
2538         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
2539         | SEALED                { $$ = Modifiers.SEALED; }
2540         | STATIC                { $$ = Modifiers.STATIC; }
2541         | READONLY              { $$ = Modifiers.READONLY; }
2542         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
2543         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
2544         | EXTERN                { $$ = Modifiers.EXTERN; }
2545         | VOLATILE              { $$ = Modifiers.VOLATILE; }
2546         ;
2547
2548 opt_class_base
2549         : /* empty */           { $$ = null; }
2550         | class_base            { $$ = $1;   }
2551         ;
2552
2553 class_base
2554         : COLON type_list { $$ = $2; }
2555         ;
2556
2557 //
2558 // Statements (8.2)
2559 //
2560
2561 //
2562 // A block is "contained" on the following places:
2563 //      method_body
2564 //      property_declaration as part of the accessor body (get/set)
2565 //      operator_declaration
2566 //      constructor_declaration
2567 //      destructor_declaration
2568 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2569 //      
2570 block
2571         : OPEN_BRACE 
2572           {
2573                 current_block = new Block (current_block);
2574           } 
2575           opt_statement_list CLOSE_BRACE 
2576           { 
2577                 while (current_block.Implicit)
2578                         current_block = current_block.Parent;
2579                 $$ = current_block;
2580                 current_block = current_block.Parent;
2581           }
2582         ;
2583
2584 opt_statement_list
2585         : /* empty */
2586         | statement_list 
2587         ;
2588
2589 statement_list
2590         : statement
2591         | statement_list statement
2592         ;
2593
2594 statement
2595         : declaration_statement
2596           {
2597                 if ((Block) $1 != current_block){
2598                         current_block.AddStatement ((Statement) $1);
2599                         current_block = (Block) $1;
2600                 }
2601           }
2602         | embedded_statement
2603           {
2604                 Statement s = (Statement) $1;
2605
2606
2607                 current_block.AddStatement ((Statement) $1);
2608           }
2609         | labeled_statement
2610         ;
2611
2612 embedded_statement
2613         : block
2614         | empty_statement
2615         | expression_statement
2616         | selection_statement
2617         | iteration_statement
2618         | jump_statement                  
2619         | try_statement
2620         | checked_statement
2621         | unchecked_statement
2622         | lock_statement
2623         | using_statement
2624         | unsafe_statement
2625         ;
2626
2627 empty_statement
2628         : SEMICOLON
2629           {
2630                   $$ = new EmptyStatement ();
2631           }
2632         ;
2633
2634 labeled_statement
2635         : IDENTIFIER COLON 
2636           {
2637                 LabeledStatement labeled = new LabeledStatement ((string) $1);
2638
2639                 if (!current_block.AddLabel ((string) $1, labeled)){
2640                         Location l = lexer.Location;
2641                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2642                 }       
2643                 current_block.AddStatement (labeled);
2644           }
2645           statement
2646         ;
2647
2648 declaration_statement
2649         : local_variable_declaration SEMICOLON
2650           {
2651                 DictionaryEntry de = (DictionaryEntry) $1;
2652
2653                 $$ = declare_local_variables ((string) de.Key, (ArrayList) de.Value, lexer.Location);
2654           }
2655
2656         | local_constant_declaration SEMICOLON
2657           {
2658                 DictionaryEntry de = (DictionaryEntry) $1;
2659
2660                 $$ = declare_local_constant ((string) de.Key, (VariableDeclaration) de.Value);
2661           }
2662         ;
2663
2664 /* 
2665  * The following is from Rhys' grammar:
2666  * > Types in local variable declarations must be recognized as 
2667  * > expressions to prevent reduce/reduce errors in the grammar.
2668  * > The expressions are converted into types during semantic analysis.
2669  */
2670 local_variable_type
2671         : primary_expression opt_rank_specifier
2672           { 
2673                 // FIXME: Do something smart here regarding the composition of the type.
2674
2675                 // Ok, the above "primary_expression" is there to get rid of
2676                 // both reduce/reduce and shift/reduces in the grammar, it should
2677                 // really just be "type_name".  If you use type_name, a reduce/reduce
2678                 // creeps up.  If you use qualified_identifier (which is all we need
2679                 // really) two shift/reduces appear.
2680                 // 
2681
2682                 // So the super-trick is that primary_expression
2683                 // can only be either a SimpleName or a MemberAccess. 
2684                 // The MemberAccess case arises when you have a fully qualified type-name like :
2685                 // Foo.Bar.Blah i;
2686                 // SimpleName is when you have
2687                 // Blah i;
2688                   
2689                 Expression expr = (Expression) $1;  
2690                 if (!(expr is SimpleName || expr is MemberAccess)) {
2691                         Location l = lexer.Location;
2692                         Report.Error (-1, l, "Invalid Type definition");
2693                         $$ = "System.Object";
2694                 }
2695                 
2696                 //
2697                 // So we extract the string corresponding to the SimpleName
2698                 // or MemberAccess
2699                 // 
2700                 $$ = GetQualifiedIdentifier (expr) + (string) $2;
2701           }
2702         | builtin_types opt_rank_specifier
2703           {
2704                   $$ = (string) $1 + (string) $2;
2705           }
2706         ;
2707
2708 local_variable_pointer_type
2709         : primary_expression STAR
2710           {
2711                 Expression expr = (Expression) $1;  
2712                 if (!(expr is SimpleName || expr is MemberAccess)) {
2713                         Location l = lexer.Location;
2714                         Report.Error (-1, l, "Invalid Type definition");
2715                         $$ = "System.Object";
2716                 }
2717                 
2718                 $$ = GetQualifiedIdentifier (expr) + "*";
2719           }
2720         | builtin_types STAR
2721           {
2722                 $$ = (string) $1 + "*";
2723           }
2724         | VOID STAR
2725           {
2726                 $$ = "System.Void*";
2727           }
2728         | local_variable_pointer_type STAR
2729           {
2730                 $$ = (string) $1 + "*";
2731           }
2732         ;
2733
2734 local_variable_declaration
2735         : local_variable_type variable_declarators
2736           {
2737                 $$ = new DictionaryEntry ($1, $2);
2738           }
2739         | local_variable_pointer_type opt_rank_specifier variable_declarators
2740         {
2741                 $$ = new DictionaryEntry ((string) $1 + (string) $2, $3);
2742         }
2743         ;
2744
2745 local_constant_declaration
2746         : CONST local_variable_type constant_declarator
2747           {
2748                 $$ = new DictionaryEntry ($2, $3);
2749           }
2750         ;
2751
2752 expression_statement
2753         : statement_expression SEMICOLON
2754           {
2755                 $$ = $1;
2756           }
2757         ;
2758
2759         //
2760         // We have to do the wrapping here and not in the case above,
2761         // because statement_expression is used for example in for_statement
2762         //
2763 statement_expression
2764         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2765         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1); }
2766         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }
2767         | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2768         | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }
2769         | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2770         | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }
2771         | error {
2772                 Report.Error (1002, lexer.Location, "Expecting `;'");
2773           }
2774         ;
2775
2776 object_creation_expression
2777         : object_or_delegate_creation_expression
2778           { note ("complain if this is a delegate maybe?"); } 
2779         ;
2780
2781 selection_statement
2782         : if_statement
2783         | switch_statement
2784         ; 
2785
2786 if_statement
2787         : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
2788           embedded_statement
2789           { 
2790                 $$ = new If ((Expression) $3, (Statement) $5);
2791           }
2792         | IF OPEN_PARENS boolean_expression CLOSE_PARENS
2793           embedded_statement ELSE embedded_statement
2794           {
2795                 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
2796           }
2797         ;
2798
2799 switch_statement
2800         : SWITCH OPEN_PARENS 
2801           { 
2802                 oob_stack.Push (lexer.Location);
2803           }
2804           expression CLOSE_PARENS 
2805           switch_block
2806           {
2807                 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
2808           }
2809         ;
2810
2811 switch_block
2812         : OPEN_BRACE
2813           opt_switch_sections
2814           CLOSE_BRACE
2815           {
2816                 $$ = $2;
2817           }
2818         ;
2819
2820 opt_switch_sections
2821         : /* empty */           
2822           {
2823                 Report.Error (1522, lexer.Location, "Empty switch block"); 
2824           }
2825         | switch_sections
2826         ;
2827
2828 switch_sections
2829         : switch_section 
2830           {
2831                 ArrayList sections = new ArrayList ();
2832
2833                 sections.Add ($1);
2834                 $$ = sections;
2835           }
2836         | switch_sections switch_section
2837           {
2838                 ArrayList sections = (ArrayList) $1;
2839
2840                 sections.Add ($2);
2841                 $$ = sections;
2842           }
2843         ;
2844
2845 switch_section
2846         : switch_labels
2847           {
2848                 current_block = new Block (current_block);
2849           }
2850           statement_list 
2851           {
2852                 while (current_block.Implicit)
2853                         current_block = current_block.Parent;
2854                 $$ = new SwitchSection ((ArrayList) $1, current_block);
2855                 current_block = current_block.Parent;
2856           }
2857         ;
2858
2859 switch_labels
2860         : switch_label 
2861           {
2862                 ArrayList labels = new ArrayList ();
2863
2864                 labels.Add ($1);
2865                 $$ = labels;
2866           }
2867         | switch_labels switch_label 
2868           {
2869                 ArrayList labels = (ArrayList) ($1);
2870                 labels.Add ($2);
2871
2872                 $$ = labels;
2873           }
2874         ;
2875
2876 switch_label
2877         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
2878         | DEFAULT COLON                         { $$ = new SwitchLabel (null, lexer.Location); }
2879         | error {
2880                 Report.Error (
2881                         1523, lexer.Location, 
2882                         "The keyword case or default must precede code in switch block");
2883           }
2884         ;
2885
2886 iteration_statement
2887         : while_statement
2888         | do_statement
2889         | for_statement
2890         | foreach_statement
2891         ;
2892
2893 while_statement
2894         : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
2895         {
2896                 $$ = new While ((Expression) $3, (Statement) $5);
2897         }
2898         ;
2899
2900 do_statement
2901         : DO embedded_statement 
2902           WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
2903           {
2904                 $$ = new Do ((Statement) $2, (Expression) $5);
2905           }
2906         ;
2907
2908 for_statement
2909         : FOR OPEN_PARENS 
2910           opt_for_initializer SEMICOLON
2911           {
2912                 Block assign_block = new Block (current_block);
2913                 current_block = assign_block;
2914
2915                 if ($3 is DictionaryEntry){
2916                         DictionaryEntry de = (DictionaryEntry) $3;
2917                         
2918                         string type = (string) de.Key;
2919                         ArrayList var_declarators = (ArrayList) de.Value;
2920
2921                         foreach (VariableDeclaration decl in var_declarators){
2922
2923                                 if (!current_block.AddVariable (type, decl.identifier, current_local_parameters,
2924                                                                 decl.Location)) {
2925                                         Report.Error (128, decl.Location, 
2926                                                       "A local variable `" + decl.identifier + "' is already" +
2927                                                       "defined in this scope");
2928                                 } else {
2929
2930                                         Location l = lexer.Location;
2931                                         Expression expr;
2932                                         if (decl.expression_or_array_initializer is Expression){
2933                                                 expr = (Expression) decl.expression_or_array_initializer;
2934                                                 
2935                                         } else {
2936                                                 
2937                                                 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
2938                                                 
2939                                                 string base_type = type.Substring (0, type.IndexOf ("["));
2940                                                 string rank = type.Substring (type.IndexOf ("["));
2941                                                 
2942                                                 expr = new ArrayCreation (base_type, rank, init, decl.Location);
2943                                         }
2944                                         
2945                                         LocalVariableReference var;
2946                                         var = new LocalVariableReference (
2947                                                                           assign_block, decl.identifier, l);
2948                                         
2949                                         Assign a = new Assign (var, expr, decl.Location);
2950                                         
2951                                         assign_block.AddStatement (new StatementExpression (a));
2952                                 }
2953                         }
2954                         
2955                         $3 = null;
2956                 } 
2957           } 
2958           opt_for_condition SEMICOLON
2959           opt_for_iterator CLOSE_PARENS 
2960           embedded_statement
2961           {
2962                 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10);
2963
2964                 current_block.AddStatement (f);
2965                 while (current_block.Implicit)
2966                         current_block = current_block.Parent;
2967                 $$ = current_block;
2968                 current_block = current_block.Parent;
2969           }
2970         ;
2971
2972 opt_for_initializer
2973         : /* empty */           { $$ = new EmptyStatement (); }
2974         | for_initializer       
2975         ;
2976
2977 for_initializer
2978         : local_variable_declaration
2979         | statement_expression_list
2980         ;
2981
2982 opt_for_condition
2983         : /* empty */           { $$ = null; }
2984         | boolean_expression
2985         ;
2986
2987 opt_for_iterator
2988         : /* empty */           { $$ = new EmptyStatement (); }
2989         | for_iterator
2990         ;
2991
2992 for_iterator
2993         : statement_expression_list
2994         ;
2995
2996 statement_expression_list
2997         : statement_expression  
2998           {
2999                 Block b = new Block (null, true);
3000
3001                 b.AddStatement ((Statement) $1);
3002                 $$ = b;
3003           }
3004         | statement_expression_list COMMA statement_expression
3005           {
3006                 Block b = (Block) $1;
3007
3008                 b.AddStatement ((Statement) $3);
3009                 $$ = $1;
3010           }
3011         ;
3012
3013 foreach_statement
3014         : FOREACH OPEN_PARENS type IDENTIFIER IN 
3015           {
3016                 oob_stack.Push (lexer.Location);
3017           }
3018           expression CLOSE_PARENS 
3019           {
3020                 Block foreach_block = new Block (current_block, true);
3021                 LocalVariableReference v;
3022                 Location l = lexer.Location;
3023
3024                 foreach_block.AddVariable ((string) $3, (string) $4, current_local_parameters, l);
3025                 v = new LocalVariableReference (foreach_block, (string) $4, l);
3026
3027                 current_block.AddStatement (foreach_block);
3028                 current_block = foreach_block;
3029
3030                 oob_stack.Push (foreach_block);
3031                 oob_stack.Push (v);
3032           } 
3033           embedded_statement 
3034           {
3035                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
3036                 Block foreach_block = (Block) oob_stack.Pop ();
3037                 Location l = (Location) oob_stack.Pop ();
3038
3039                 $$ = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
3040           }
3041         ;
3042
3043 jump_statement
3044         : break_statement
3045         | continue_statement
3046         | goto_statement
3047         | return_statement
3048         | throw_statement
3049         ;
3050
3051 break_statement
3052         : BREAK SEMICOLON
3053           {
3054                 $$ = new Break (lexer.Location);
3055           }
3056         ;
3057
3058 continue_statement
3059         : CONTINUE SEMICOLON
3060           {
3061                 $$ = new Continue (lexer.Location);
3062           }
3063         ;
3064
3065 goto_statement
3066         : GOTO IDENTIFIER SEMICOLON 
3067           {
3068                 $$ = new Goto (current_block, (string) $2, lexer.Location);
3069           }
3070         | GOTO CASE constant_expression SEMICOLON
3071           {
3072                 $$ = new GotoCase ((Expression) $3, lexer.Location);
3073           }
3074         | GOTO DEFAULT SEMICOLON 
3075           {
3076                 $$ = new GotoDefault (lexer.Location);
3077           }
3078         ; 
3079
3080 return_statement
3081         : RETURN opt_expression SEMICOLON
3082           {
3083                 $$ = new Return ((Expression) $2, lexer.Location);
3084           }
3085         ;
3086
3087 throw_statement
3088         : THROW opt_expression SEMICOLON
3089           {
3090                 $$ = new Throw ((Expression) $2, lexer.Location);
3091           }
3092         ;
3093
3094 opt_expression
3095         : /* empty */
3096         | expression
3097         ;
3098
3099 try_statement
3100         : TRY block catch_clauses 
3101         {
3102                 Catch g = null;
3103                 ArrayList s = new ArrayList ();
3104                 
3105                 foreach (Catch cc in (ArrayList) $3) {
3106                         if (cc.Type == null)
3107                                 g = cc;
3108                         else
3109                                 s.Add (cc);
3110                 }
3111
3112                 // Now s contains the list of specific catch clauses
3113                 // and g contains the general one.
3114                 
3115                 $$ = new Try ((Block) $2, s, g, null);
3116         }
3117         | TRY block opt_catch_clauses FINALLY block
3118           {
3119                 Catch g = null;
3120                 ArrayList s = new ArrayList ();
3121                 
3122                 foreach (Catch cc in (ArrayList) $3) {
3123                         if (cc.Type == null)
3124                                 g = cc;
3125                         else
3126                                 s.Add (cc);
3127                 }
3128
3129                 $$ = new Try ((Block) $2, s, g, (Block) $5);
3130           }
3131         | TRY block error 
3132           {
3133                 Report.Error (1524, lexer.Location, "Expected catch or finally");
3134           }
3135         ;
3136
3137 opt_catch_clauses
3138         : /* empty */  { $$ = null; }
3139         | catch_clauses
3140         ;
3141
3142 catch_clauses
3143         : catch_clause 
3144           {
3145                 ArrayList l = new ArrayList ();
3146
3147                 l.Add ($1);
3148                 $$ = l;
3149           }
3150         | catch_clauses catch_clause
3151           {
3152                 ArrayList l = (ArrayList) $1;
3153
3154                 l.Add ($2);
3155                 $$ = l;
3156           }
3157         ;
3158
3159 opt_identifier
3160         : /* empty */   { $$ = null; }
3161         | IDENTIFIER
3162         ;
3163
3164 catch_clause 
3165         : CATCH opt_catch_args 
3166         {
3167                 string type = null, id = null;
3168                 
3169                 if ($2 != null) {
3170                         DictionaryEntry cc = (DictionaryEntry) $2;
3171                         type = (string) cc.Key;
3172                         id   = (string) cc.Value;
3173
3174                         if (id != null){
3175                                 ArrayList one = new ArrayList ();
3176                                 Location loc = lexer.Location;
3177
3178                                 one.Add (new VariableDeclaration (id, null, loc));
3179
3180                                 $1 = current_block;
3181                                 current_block = new Block (current_block);
3182                                 Block b = declare_local_variables (type, one, loc);
3183                                 current_block = b;
3184
3185                                 
3186                         }
3187                 }
3188         } block {
3189                 string type = null, id = null;
3190
3191                 if ($2 != null){
3192                         DictionaryEntry cc = (DictionaryEntry) $2;
3193                         type = (string) cc.Key;
3194                         id   = (string) cc.Value;
3195
3196                         if ($1 != null){
3197                                 while (current_block != (Block) $1)
3198                                         current_block = current_block.Parent;
3199                         }
3200                 }
3201
3202
3203                 $$ = new Catch (type, id , (Block) $4, lexer.Location);
3204         }
3205         ;
3206
3207 opt_catch_args
3208         : /* empty */ { $$ = null; }
3209         | catch_args
3210         ;         
3211
3212 catch_args 
3213         : OPEN_PARENS type opt_identifier CLOSE_PARENS 
3214         {
3215                 $$ = new DictionaryEntry ($2, $3);
3216         }
3217         ;
3218
3219 checked_statement
3220         : CHECKED block
3221           {
3222                 $$ = new Checked ((Block) $2);
3223           }
3224         ;
3225
3226 unchecked_statement
3227         : UNCHECKED block
3228           {
3229                 $$ = new Unchecked ((Block) $2);
3230           }
3231         ;
3232
3233 unsafe_statement
3234         : UNSAFE block
3235         {
3236                 $$ = new Unsafe ((Block) $2);
3237         }
3238
3239
3240 lock_statement
3241         : LOCK OPEN_PARENS expression CLOSE_PARENS 
3242           {
3243                 //
3244           } 
3245           embedded_statement
3246           {
3247                 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3248           }
3249         ;
3250
3251 using_statement
3252         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
3253           {
3254                 Block assign_block = new Block (current_block);
3255                 current_block = assign_block;
3256
3257                 oob_stack.Push (lexer.Location);
3258                 
3259                 if ($3 is DictionaryEntry){
3260                         DictionaryEntry de = (DictionaryEntry) $3;
3261                         Location l = lexer.Location;
3262
3263                         string type = (string) de.Key;
3264                         ArrayList var_declarators = (ArrayList) de.Value;
3265
3266                         foreach (VariableDeclaration decl in var_declarators){
3267                                 if (!current_block.AddVariable (type, decl.identifier, current_local_parameters,
3268                                                                 decl.Location)){
3269                                         Report.Error (128, decl.Location, 
3270                                         "A local variable `" + decl.identifier + "' is already" +
3271                                         "defined in this scope");
3272                                 }
3273                         }
3274
3275                         ArrayList vars = new ArrayList ();
3276
3277                         foreach (VariableDeclaration decl in var_declarators){
3278
3279                                 Expression expr;
3280                                 if (decl.expression_or_array_initializer is Expression){
3281                                         expr = (Expression) decl.expression_or_array_initializer;
3282                                         
3283                                 } else {
3284
3285                                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3286                                         
3287                                         string base_type = type.Substring (0, type.IndexOf ("["));
3288                                         string rank = type.Substring (type.IndexOf ("["));
3289                                         
3290                                         expr = new ArrayCreation (base_type, rank, init, decl.Location);
3291                                 }
3292
3293                                 LocalVariableReference var;
3294                                 VariableInfo vi;
3295
3296                                 var = new LocalVariableReference (assign_block, decl.identifier, l);
3297                                 vi = var.VariableInfo;
3298                                 vi.ReadOnly = true;
3299
3300                                 // This is so that it is not a warning on using variables
3301                                 vi.Used = true;
3302
3303                                 vars.Add (new DictionaryEntry (var, expr));                             
3304
3305                                 // Assign a = new Assign (var, expr, decl.Location);
3306                                 // assign_block.AddStatement (new StatementExpression (a));
3307                         }
3308                         $3 = new DictionaryEntry (type, vars);
3309                  }
3310           } 
3311           embedded_statement
3312           {
3313                 Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
3314                 current_block.AddStatement (u);
3315                 while (current_block.Implicit)
3316                         current_block = current_block.Parent;
3317                 $$ = current_block;
3318                 current_block = current_block.Parent;
3319           }
3320         ; 
3321
3322 resource_acquisition
3323         : local_variable_declaration
3324         | expression
3325         ;
3326
3327 %%
3328
3329 // <summary>
3330 //   A class used to pass around variable declarations and constants
3331 // </summary>
3332 public class VariableDeclaration {
3333         public string identifier;
3334         public object expression_or_array_initializer;
3335         public Location Location;
3336
3337         public VariableDeclaration (string id, object eoai, Location l){
3338                 this.identifier = id;
3339                 this.expression_or_array_initializer = eoai;
3340                 this.Location = l;
3341         }
3342 }
3343
3344 // <summary>
3345 //   A class used to hold info about an indexer declarator
3346 // </summary>
3347
3348 public class IndexerDeclaration {
3349         public string type;
3350         public string interface_type;
3351         public Parameters param_list;
3352
3353         public IndexerDeclaration (string type, string interface_type, Parameters param_list)
3354         {
3355                 this.type = type;
3356                 this.interface_type = interface_type;
3357                 this.param_list = param_list;
3358         }
3359 }
3360
3361 // <summary>
3362 //  A class used to hold info about an operator declarator
3363 // </summary>
3364
3365 public class OperatorDeclaration {
3366         public Operator.OpType optype;
3367         public string ret_type;
3368         public string arg1type;
3369         public string arg1name;
3370         public string arg2type;
3371         public string arg2name;
3372         public Location location;
3373
3374         public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
3375                                     string arg2type, string arg2name, Location location)
3376         {
3377                 optype = op;
3378                 this.ret_type = ret_type;
3379                 this.arg1type = arg1type;
3380                 this.arg1name = arg1name;
3381                 this.arg2type = arg2type;
3382                 this.arg2name = arg2name;
3383                 this.location = location;
3384         }
3385
3386 }
3387
3388 // <summary>
3389 //   Given the @class_name name, it creates a fully qualified name
3390 //   based on the containing declaration space
3391 // </summary>
3392 string 
3393 MakeName (string class_name)
3394 {
3395         string ns = current_namespace.Name;
3396         string container_name = current_container.Name;
3397
3398         if (container_name == ""){
3399                 if (ns != "")
3400                         return ns + "." + class_name;
3401                 else
3402                         return class_name;
3403         } else
3404                 return container_name + "." + class_name;
3405 }
3406
3407 // <summary>
3408 //   Used to report back to the user the result of a declaration
3409 //   in the current declaration space
3410 // </summary>
3411 void 
3412 CheckDef (AdditionResult result, string name)
3413 {
3414         if (result == AdditionResult.Success)
3415                 return;
3416
3417         Location l = lexer.Location;
3418         
3419         switch (result){
3420         case AdditionResult.NameExists:
3421                 Report.Error (102, l, "The namespace `" + current_container.Name + 
3422                                  "' already contains a definition for `"+
3423                                  name + "'");
3424                 break;
3425
3426
3427                 //
3428                 // This is handled only for static Constructors, because
3429                 // in reality we handle these by the semantic analysis later
3430                 //
3431         case AdditionResult.MethodExists:
3432                 Report.Error (
3433                         111, l, "Class `"+current_container.Name+
3434                         "' already defines a member called '" + 
3435                         name + "' with the same parameter types (more than one default constructor)");
3436                 break;
3437
3438         case AdditionResult.EnclosingClash:
3439                 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
3440                 break;
3441                 
3442         case AdditionResult.NotAConstructor:
3443                 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
3444                 break;
3445         }
3446 }
3447
3448 void 
3449 CheckDef (bool result, string name)
3450 {
3451         if (result)
3452                 return;
3453         CheckDef (AdditionResult.NameExists, name);
3454 }
3455
3456 Expression
3457 SimpleLookup (string name, Location loc)
3458 {
3459         //
3460         // we need to check against current_block not being null
3461         // as `expression' is allowed in argument_lists, which 
3462         // do not exist inside a block.  
3463         //
3464         if (current_block != null){
3465                 if (current_block.IsVariableDefined (name))
3466                         return new LocalVariableReference (current_block, name, loc);
3467         }
3468
3469         if (current_local_parameters != null){
3470                 int idx;
3471                 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
3472                 if (par != null)
3473                         return new ParameterReference (current_local_parameters, idx, name);
3474         }
3475
3476         return null;
3477 }
3478
3479 Expression DecomposeQI (string name, Location loc)
3480 {
3481         Expression o;
3482
3483         if (name.IndexOf ('.') == -1){
3484                 o = SimpleLookup (name, loc);
3485                 if (o == null)
3486                         return new SimpleName (name, loc);
3487                 return o;
3488         } else {
3489                 int pos = name.LastIndexOf (".");
3490                 string left = name.Substring (0, pos);
3491                 string right = name.Substring (pos + 1);
3492
3493                 o = DecomposeQI (left, loc);
3494                 return new MemberAccess (o, right, loc);
3495         }
3496 }
3497
3498 // <summary>
3499 //  This method is used to get at the complete string representation of
3500 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
3501 //  This is necessary because local_variable_type admits primary_expression
3502 //  as the type of the variable. So we do some extra checking
3503 // </summary>
3504 string GetQualifiedIdentifier (Expression expr)
3505 {
3506         if (expr is SimpleName)
3507                 return ((SimpleName)expr).Name;
3508         else if (expr is MemberAccess)
3509                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3510         else 
3511                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3512         
3513 }
3514
3515 Block declare_local_variables (string type, ArrayList variable_declarators, Location loc)
3516 {
3517         Block implicit_block;
3518         ArrayList inits = null;
3519
3520         //
3521         // We use the `Used' property to check whether statements
3522         // have been added to the current block.  If so, we need
3523         // to create another block to contain the new declaration
3524         // otherwise, as an optimization, we use the same block to
3525         // add the declaration.
3526         //
3527         // FIXME: A further optimization is to check if the statements
3528         // that were added were added as part of the initialization
3529         // below.  In which case, no other statements have been executed
3530         // and we might be able to reduce the number of blocks for
3531         // situations like this:
3532         //
3533         // int j = 1;  int k = j + 1;
3534         //
3535         if (current_block.Used)
3536                 implicit_block = new Block (current_block, true);
3537         else
3538                 implicit_block = current_block;
3539
3540         foreach (VariableDeclaration decl in variable_declarators){
3541
3542                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location)) {
3543                         if (decl.expression_or_array_initializer != null){
3544                                 if (inits == null)
3545                                         inits = new ArrayList ();
3546                                 inits.Add (decl);
3547                         }
3548                 } else {
3549                         Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3550                                          "' is already defined in this scope");
3551                 }
3552         }
3553
3554         if (inits == null)
3555                 return implicit_block;
3556
3557         foreach (VariableDeclaration decl in inits){
3558                 Assign assign;
3559                 Expression expr;
3560                 
3561                 if (decl.expression_or_array_initializer is Expression){
3562                         expr = (Expression) decl.expression_or_array_initializer;
3563
3564                 } else {
3565                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3566                         
3567                         string base_type = type.Substring (0, type.IndexOf ("["));
3568                         string rank = type.Substring (type.IndexOf ("["));
3569
3570                         expr = new ArrayCreation (base_type, rank, init, decl.Location);
3571                         
3572                 }
3573
3574                 LocalVariableReference var;
3575                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3576
3577                 assign = new Assign (var, expr, decl.Location);
3578
3579                 implicit_block.AddStatement (new StatementExpression (assign));
3580         }
3581         
3582         return implicit_block;
3583 }
3584
3585 Block declare_local_constant (string type, VariableDeclaration decl)
3586 {
3587         Block implicit_block;
3588
3589         if (current_block.Used)
3590                 implicit_block = new Block (current_block, true);
3591         else
3592                 implicit_block = current_block;
3593
3594         if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3595                                           current_local_parameters, decl.Location))){
3596                 Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3597                               "' is already defined in this scope");
3598         }
3599         
3600         return implicit_block;
3601 }
3602
3603 void CheckAttributeTarget (string a)
3604 {
3605         switch (a) {
3606
3607         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3608                 return;
3609                 
3610         default :
3611                 Location l = lexer.Location;
3612                 Report.Error (658, l, "Invalid attribute target");
3613                 break;
3614         }
3615
3616 }
3617
3618 void CheckUnaryOperator (Operator.OpType op)
3619 {
3620         switch (op) {
3621                 
3622         case Operator.OpType.LogicalNot: 
3623         case Operator.OpType.OnesComplement: 
3624         case Operator.OpType.Increment:
3625         case Operator.OpType.Decrement:
3626         case Operator.OpType.True: 
3627         case Operator.OpType.False: 
3628         case Operator.OpType.Addition: 
3629         case Operator.OpType.Subtraction:
3630                 
3631                 break;
3632                 
3633         default :
3634                 Location l = lexer.Location;
3635                 Report.Error (1019, l, "Overloadable unary operator expected"); 
3636                 break;
3637                 
3638         }
3639 }
3640
3641 void CheckBinaryOperator (Operator.OpType op)
3642 {
3643         switch (op) {
3644                 
3645         case Operator.OpType.Addition: 
3646         case Operator.OpType.Subtraction: 
3647         case Operator.OpType.Multiply:
3648         case Operator.OpType.Division:
3649         case Operator.OpType.Modulus: 
3650         case Operator.OpType.BitwiseAnd: 
3651         case Operator.OpType.BitwiseOr:
3652         case Operator.OpType.ExclusiveOr: 
3653         case Operator.OpType.LeftShift: 
3654         case Operator.OpType.RightShift:
3655         case Operator.OpType.Equality: 
3656         case Operator.OpType.Inequality:
3657         case Operator.OpType.GreaterThan: 
3658         case Operator.OpType.LessThan: 
3659         case Operator.OpType.GreaterThanOrEqual:
3660         case Operator.OpType.LessThanOrEqual:
3661                 break;
3662                 
3663         default :
3664                 Location l = lexer.Location;
3665                 Report.Error (1020, l, "Overloadable binary operator expected");
3666                 break;
3667         }
3668         
3669 }
3670
3671 void syntax_error (Location l, string msg)
3672 {
3673         Report.Error (1003, l, "Syntax error, " + msg);
3674 }
3675
3676 void output (string s)
3677 {
3678         Console.WriteLine (s);
3679 }
3680
3681 void note (string s)
3682 {
3683         // Used to put annotations
3684 }
3685
3686 Tokenizer lexer;
3687
3688 public Tokenizer Lexer {
3689         get {
3690                 return lexer;
3691         }
3692 }                  
3693
3694 public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
3695 {
3696         current_namespace = new Namespace (null, "");
3697         this.name = name;
3698         this.input = input;
3699         current_container = RootContext.Tree.Types;
3700         current_container.Namespace = current_namespace;
3701         oob_stack = new Stack ();
3702
3703         lexer = new Tokenizer (input, name, defines);
3704 }
3705
3706 public override int parse ()
3707 {
3708         StringBuilder value = new StringBuilder ();
3709
3710         global_errors = 0;
3711         try {
3712                 if (yacc_verbose_flag)
3713                         yyparse (lexer, new yydebug.yyDebugSimple ());
3714                 else
3715                         yyparse (lexer);
3716         } catch (Exception e){
3717                 // Console.WriteLine ("Fatal error: " + name);
3718                 // Console.WriteLine (lexer.location);
3719
3720                 // 
3721                 // Please do not remove this, it is used during debugging
3722                 // of the grammar
3723                 //
3724                 Console.WriteLine (lexer.location + "  : Parsing error ");
3725                 Console.WriteLine (e);
3726                 global_errors++;
3727         }
3728         
3729         return global_errors;
3730 }
3731
3732 /* end end end */
3733 }