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