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