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