This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / mbas / mb-parser.jay
1 %{
2 //
3 // Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler
4 //
5 // Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // Copyright (C) 2001 A Rafael D Teixeira
10 //
11 // TODO:
12 //      Nearly everything
13 //
14
15 namespace Mono.MonoBASIC
16 {
17         using System.Text;
18         using System;
19         using System.Reflection;
20         using System.Collections;
21         using Mono.Languages;
22         using Mono.MonoBASIC;
23
24         /// <summary>
25         ///    The MonoBASIC Parser
26         /// </summary>
27         [DefaultParser]
28         public class Parser : GenericParser
29         {
30         
31
32                 /// <summary>
33                 ///   Current block is used to add statements as we find
34                 ///   them.  
35                 /// </summary>
36                 Block      current_block;
37                 
38                 /// <summary>
39                 ///   Tmp block is used to store block endings in if/select's
40                 /// </summary>
41                 Block      tmp_block;           
42
43                 /// <summary>
44                 ///   Tmp block is used to store tmp copies of expressions
45                 /// </summary>
46                 Expression      tmp_expr;       
47                 
48                 /// <summary>
49                 ///   Tmp catch is used to store catch clauses in try..catch..finally
50                 /// </summary>
51                 ArrayList      tmp_catch_clauses;                       
52                 
53                 /// <summary>
54                 ///   Current interface is used by the various declaration
55                 ///   productions in the interface declaration to "add"
56                 ///   the interfaces as we find them.
57                 /// </summary>
58                 Interface  current_interface;
59
60                 /// <summary>
61                 ///   This is used by the unary_expression code to resolve
62                 ///   a name against a parameter.  
63                 /// </summary>
64                 Parameters current_local_parameters;
65                 
66                 /// <summary>
67                 ///   This are used when parsing parameters in property
68                 ///   declarations.
69                 /// </summary>          
70                 Parameters set_parameters;
71                 Parameters get_parameters;
72                 
73                 /// <summary>
74                 ///   This is used by the sub_header parser to store modifiers
75                 ///   to be passed to sub/constructor  
76                 /// </summary>
77                 int current_modifiers;          
78                         
79                 /// <summary>
80                 ///   This is used by the sub_header parser to store attributes
81                 ///   to be passed to sub/constructor  
82                 /// </summary>
83                 Attributes current_attributes;                          
84
85                 /// <summary>
86                 ///   Using during property parsing to describe the implicit
87                 ///   value parameter that is passed to the "set" accessor
88                 ///   method
89                 /// </summary>
90                 string get_implicit_value_parameter_name;
91                 
92                 // <summary>
93                 //   Using during property parsing to describe the implicit
94                 //   value parameter that is passed to the "set" and "get"accesor
95                 //   methods (properties and indexers).
96                 // </summary>
97                 Expression get_implicit_value_parameter_type;
98                 
99                 /// <summary>
100                 ///   Using during property parsing to describe the implicit
101                 ///   value parameter that is passed to the "set" accessor
102                 ///   method
103                 /// </summary>
104                 string set_implicit_value_parameter_name;
105                 
106                 // <summary>
107                 //   Using during property parsing to describe the implicit
108                 //   value parameter that is passed to the "set" and "get"accesor
109                 //   methods (properties and indexers).
110                 // </summary>
111                 Expression set_implicit_value_parameter_type;           
112                 
113                 Location member_location;
114                 
115                 // An out-of-band stack.
116                 //
117                 Stack oob_stack;
118                 
119                 ArrayList current_rank_specifiers;
120
121                 DoOptions do_type;
122                 //
123                 // Switch stack.
124                 //
125                 Stack switch_stack;
126                 
127                 // Expression stack for nested ifs
128                 Stack expr_stack; 
129                 
130                 Stack tmp_blocks;
131             Stack statement_stack;
132
133                 // A stack for With expressions.
134                 //
135                 Stack with_stack;
136         
137                 
138                 static public bool InitialOptionExplicit = false;
139                 static public bool InitialOptionStrict = false;
140                 static public bool InitialOptionCompareBinary = true;
141                 static public ArrayList ImportsList = null;
142
143                 bool OptionExplicit;
144                 bool OptionStrict;
145                 bool OptionCompareBinary;
146
147                 static public bool UseExtendedSyntax; // for ".mbs" files
148
149                 bool implicit_modifiers;
150                 
151                 public override string[] extensions()
152                 {
153                         string [] list = { ".vb", ".mbs" };
154                         return list;
155                 }
156
157 %}
158
159 %token EOF
160 %token NONE   /* This token is never returned by our lexer */
161 %token ERROR  // This is used not by the parser, but by the tokenizer.
162               // do not remove.
163
164 /*
165  *These are the MonoBASIC keywords
166  */
167 %token ADDHANDLER
168 %token ADDRESSOF
169 %token ALIAS
170 %token AND
171 %token ANDALSO
172 %token ANSI
173 %token AS
174 %token ASSEMBLY
175 %token AUTO
176 %token BINARY
177 %token BOOLEAN  
178 %token BYREF
179 %token BYTE
180 %token BYVAL    
181 %token CALL
182 %token CASE     
183 %token CATCH    
184 %token CBOOL
185 %token CBYTE
186 %token CCHAR    
187 %token CDATE
188 %token CDEC
189 %token CDBL
190 %token CHAR     
191 %token CINT
192 %token CLASS
193 %token CLNG
194 %token COBJ
195 %token COMPARE  
196 %token CONST    
197 %token CSHORT   
198 %token CSNG
199 %token CSTR
200 %token CTYPE
201 %token DATE
202 %token DECIMAL  
203 %token DECLARE
204 %token DEFAULT  
205 %token DELEGATE 
206 %token DIM
207 %token DO       
208 %token DOUBLE   
209 %token EACH     
210 %token ELSE
211 %token ELSEIF
212 %token END      
213 %token ENUM     
214 %token EOL
215 %token ERASE
216 %token ERROR
217 %token EVENT
218 %token EXIT     
219 %token EXPLICIT 
220 %token FALSE    
221 %token FINALLY  
222 %token FOR      
223 %token FRIEND
224 %token FUNCTION
225 %token GET
226 //%token GETTYPE
227 %token GOTO     
228 %token HANDLES
229 %token IF       
230 %token IMPLEMENTS
231 %token IMPORTS  
232 %token IN       
233 %token INHERITS
234 %token INTEGER  
235 %token INTERFACE
236 %token IS
237 %token LET
238 %token LIB      
239 %token LIKE     
240 %token LONG     
241 %token LOOP
242 %token ME
243 %token MOD
244 %token MODULE
245 %token MUSTINHERIT      
246 %token MUSTOVERRIDE
247 %token MYBASE
248 %token MYCLASS
249 %token NAMESPACE
250 %token NEW
251 %token NEXT     
252 %token NOT
253 %token NOTHING
254 %token NOTINHERITABLE
255 %token NOTOVERRIDABLE
256 %token OBJECT   
257 %token OFF
258 %token ON
259 %token OPTION   
260 %token OPTIONAL 
261 %token OR
262 %token ORELSE
263 %token OVERLOADS
264 %token OVERRIDABLE      
265 %token OVERRIDES        
266 %token PARAM_ARRAY
267 %token PRESERVE
268 %token PRIVATE  
269 %token PROPERTY
270 %token PROTECTED
271 %token PUBLIC
272 %token RAISEEVENT
273 %token READONLY 
274 %token REDIM
275 %token REM
276 %token REMOVEHANDLER
277 %token RESUME   
278 %token RETURN
279 %token SELECT
280 %token SET
281 %token SHADOWS
282 %token SHARED
283 %token SHORT    
284 %token SINGLE
285 %token SIZEOF   
286 %token STATIC   
287 %token STEP
288 %token STOP
289 %token STRICT   
290 %token STRING
291 %token STRUCTURE
292 %token SUB
293 %token SYNCLOCK
294 %token TEXT
295 %token THEN
296 %token THROW
297 %token TO
298 %token TRUE     
299 %token TRY      
300 %token TYPEOF   
301 %token UNICODE
302 %token UNTIL
303 %token VARIANT  
304 %token WHEN     
305 %token WHILE    
306 %token WITH
307 %token WITHEVENTS
308 %token WRITEONLY
309 %token XOR
310 %token YIELD // MonoBASIC extension
311
312 /* MonoBASIC single character operators/punctuation. */
313
314 %token OPEN_BRACKET  "["
315 %token CLOSE_BRACKET "]"
316 %token OPEN_PARENS   "("
317 %token OPEN_BRACE    "{"
318 %token CLOSE_BRACE   "}"
319 %token CLOSE_PARENS  ")"
320 %token DOT           "."
321 %token COMMA         ","
322 %token COLON         ":"
323
324 %token PLUS           "+"
325 %token MINUS          "-"
326 %token ASSIGN         "="
327 %token OP_LT          "<"
328 %token OP_GT          ">"
329 %token STAR           "*"
330 %token DIV            "/"
331 %token OP_EXP         "^"
332 %token INTERR         "?"
333 %token OP_IDIV        "\\"
334 %token OP_CONCAT      "&"
335 %token EXCLAMATION    "!"
336
337 %token PERCENT        "%"
338 %token LONGTYPECHAR   "&"
339 %token AT_SIGN            "@"
340 %token SINGLETYPECHAR "!"
341 %token NUMBER_SIGN    "#"
342 %token DOLAR_SIGN     "$"
343
344 %token ATTR_ASSIGN        ":="
345
346 /* MonoBASIC multi-character operators. */
347 %token OP_LE                  "<="
348 %token OP_GE                  ">="
349 %token OP_NE                  "<>"
350 %token OP_XOR                 "xor"
351 //%token OP_MODULUS             //"mod"
352 %token OP_MULT_ASSIGN         "*="
353 %token OP_DIV_ASSIGN          "/="
354 %token OP_IDIV_ASSIGN         "\\="
355 %token OP_ADD_ASSIGN          "+="
356 %token OP_SUB_ASSIGN          "-="
357 %token OP_CONCAT_ASSIGN       "&="
358 %token OP_EXP_ASSIGN          "^="
359
360 /* VB.NET 2003 new bit-shift operators */
361 %token OP_SHIFT_LEFT              "<<"
362 %token OP_SHIFT_RIGHT         ">>"
363
364 /* Numbers */
365 %token LITERAL_INTEGER           "int literal"
366 %token LITERAL_SINGLE            "float literal"
367 %token LITERAL_DOUBLE            "double literal"
368 %token LITERAL_DECIMAL           "decimal literal"
369 %token LITERAL_CHARACTER         "character literal"
370 %token LITERAL_STRING            "string literal"
371 %token LITERAL_DATE              "datetime literal"
372
373 %token IDENTIFIER
374
375 /* Add precedence rules to solve dangling else s/r conflict */
376 %nonassoc LOWPREC
377 %nonassoc IF
378 %nonassoc ELSE
379 %right ASSIGN
380 %left OP_OR
381 %left OP_AND
382 %left BITWISE_OR
383 %left BITWISE_AND
384 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
385 %left PLUS MINUS
386 %left STAR DIV PERCENT
387 %right BITWISE_NOT CARRET UMINUS
388 %nonassoc OP_INC OP_DEC
389 %left OPEN_PARENS
390 %left OPEN_BRACKET OPEN_BRACE
391 %left DOT
392 %right NOT
393 %nonassoc HIGHPREC
394
395 %start compilation_unit
396 %%
397
398 compilation_unit
399         : opt_option_directives
400           opt_imports_directives 
401           opt_attributes
402           opt_declarations 
403           EOF
404           {
405                 $$ = $4;
406           }
407         ;
408           
409 opt_option_directives
410         : /* empty */
411         | option_directives
412         ;
413         
414 option_directives
415         : option_directive
416         | option_directives option_directive
417         ;
418         
419 option_directive
420         : option_explicit_directive
421         | option_strict_directive
422         | option_compare_directive
423         ;
424         
425 on_off
426         : /* empty */
427           {
428                   $$ = (object)true;
429           }
430         | ON
431           {
432                   $$ = (object)true;
433           }
434         | OFF
435           {
436                   $$ = (object)false;
437           }
438         ;
439           
440 text_or_binary
441         : BINARY
442           {
443                   $$ = (object)true;
444           }
445         | TEXT
446           {
447                   $$ = (object)false;
448           }
449         ;
450           
451 option_explicit_directive
452         : OPTION EXPLICIT on_off EOL
453           {
454                 if (!UseExtendedSyntax)
455                         OptionExplicit = (bool)$3;
456                 else
457                         Report.Warning (
458                                 9999, lexer.Location, 
459                                 "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");
460           }
461         ;
462           
463                         
464 option_strict_directive
465         : OPTION STRICT on_off EOL
466           {
467                 if (!UseExtendedSyntax)
468                         OptionStrict = (bool)$3;
469                 else
470                         Report.Warning (
471                                 9999, lexer.Location, 
472                                 "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");
473           }
474         ;
475           
476 option_compare_directive
477         : OPTION COMPARE text_or_binary EOL
478           {
479                 OptionCompareBinary = (bool)$3;
480           }
481         ;
482
483 opt_declarations
484         : /* empty */
485         | declarations
486         ;
487
488 declarations
489         : declaration
490         | declarations declaration
491         ;
492         
493 declaration
494         : namespace_declaration
495         | type_declaration
496           {
497                 string name = "";
498                 int mod_flags;
499
500                 if ($1 is Class || $1 is Struct || $1 is Module ){
501                         TypeContainer c = (TypeContainer) $1;
502                         mod_flags = c.ModFlags;
503                         name = c.Name;
504                 } else
505                         break;
506
507                 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
508                         Report.Error (
509                                 1527, lexer.Location, 
510                                 "Namespace elements cannot be explicitly " +
511                                 "declared private or protected in '" + name + "'");
512                 }
513           }
514         ;
515
516 identifier
517         : IDENTIFIER
518         | BINARY
519         | TEXT
520         | COMPARE
521         | EXPLICIT
522         | OFF
523         ;
524
525 type_character
526         : PERCENT                       { $$ = TypeManager.system_int32_expr; }
527         | LONGTYPECHAR                  { $$ = TypeManager.system_int64_expr; }
528         | AT_SIGN                       { $$ = TypeManager.system_decimal_expr; }
529         | SINGLETYPECHAR                { $$ = TypeManager.system_single_expr; }
530         | NUMBER_SIGN                   { $$ = TypeManager.system_double_expr; }
531         | DOLAR_SIGN                    { $$ = TypeManager.system_string_expr; }
532         ;       
533         
534 opt_type_character
535         : /* empty */                   { $$ = null; }
536         | type_character                { $$ = $1; }
537         ;
538         
539
540 qualified_identifier
541         : identifier
542         | qualified_identifier DOT identifier 
543           { 
544             $$ = (($1).ToString ()) + "." + ($3.ToString ()); 
545           }
546         ;
547         
548 opt_imports_directives
549         : /* empty */
550         | imports_directives
551         ;
552
553 imports_directives
554         : imports_directive 
555         | imports_directives imports_directive 
556         ;
557
558 imports_directive
559         : IMPORTS imports_terms EOL
560         ;
561
562 imports_terms
563         : imports_term
564         | imports_terms COMMA imports_terms
565         ;
566         
567 imports_term
568         : qualified_identifier
569           {
570                 RootContext.SourceBeingCompiled.Imports ((string) $1, lexer.Location);
571           }
572         | qualified_identifier ASSIGN qualified_identifier
573           {
574                 RootContext.SourceBeingCompiled.ImportsWithAlias ((string) $1, (string) $3, lexer.Location);
575           }
576         ;
577
578 opt_attributes
579         : /* empty */
580         | attribute_sections    { $$ = $1; }
581         ;
582
583 attribute_sections
584         : attribute_section
585           { 
586                 AttributeSection sect = (AttributeSection) $1;
587
588                 if (sect.Target == "assembly") 
589                         RootContext.AddGlobalAttributeSection (current_container, sect);
590                 
591                 $$ = new Attributes ((AttributeSection) $1, lexer.Location);
592                 
593           }     
594           /* 
595              FIXME: we should check if extended syntax is enabled;
596                     otherwise an exception should be thrown since VB.NET 
597                     only allows one attribute section 
598           */  
599         | attribute_sections attribute_section
600           {
601                 Attributes attrs = null;
602                 AttributeSection sect = (AttributeSection) $2;
603
604                 if (sect.Target == "assembly")
605                         RootContext.AddGlobalAttributeSection (current_container, sect);
606
607                 if ($1 != null) {
608                         attrs = (Attributes) $1;
609                         attrs.AddAttributeSection (sect);
610                 }
611                 
612                 $$ = attrs;
613           }     
614         ;
615         
616 attribute_section
617         : OP_LT attribute_target_specifier attribute_list OP_GT
618           { 
619                 string target = null;
620                 
621                 if ($2 != null)
622                         target = (string) $2;
623                 
624                 $$ = new AttributeSection (target, (ArrayList) $3);
625           }     
626         | OP_LT attribute_list OP_GT
627           {
628                 $$ = new AttributeSection (null, (ArrayList) $2);
629           }     
630         ; 
631
632 attribute_target_specifier
633         : attribute_target COLON
634           {
635                 $$ = $1;
636           }
637         ;
638
639 attribute_target
640         : identifier
641           {
642                 CheckAttributeTarget ((string) $1);
643                 $$ = $1;
644           }
645         | EVENT  { $$ = "event"; }        
646         | RETURN { $$ = "return"; }
647         ;
648         
649 attribute_list
650         : attribute 
651           {
652                 ArrayList attrs = new ArrayList ();
653                 attrs.Add ($1);
654
655                 $$ = attrs;
656                
657           }     
658         | attribute_list COMMA attribute
659           {
660                 ArrayList attrs = (ArrayList) $1;
661                 attrs.Add ($3);
662
663                 $$ = attrs;
664           }     
665         ;
666         
667 attribute 
668         : attribute_name
669           {
670                 $$ = lexer.Location;
671           }
672           opt_attribute_arguments
673           {
674                 $$ = new Mono.MonoBASIC.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
675           }       
676         ;
677         
678 attribute_name
679         : type_name 
680         ;
681                         
682 opt_attribute_arguments
683         : /* empty */   { $$ = null; }
684         | OPEN_PARENS attribute_arguments CLOSE_PARENS
685           {
686                 $$ = $2;
687           }     
688         ;
689         
690 attribute_arguments
691         : opt_positional_argument_list
692           {
693                 if ($1 == null)
694                         $$ = null;
695                 else {
696                         ArrayList args = new ArrayList ();
697                         args.Add ($1);
698                 
699                         $$ = args;
700                 }
701           }
702         | positional_argument_list COMMA named_argument_list
703           {
704                 ArrayList args = new ArrayList ();
705                 args.Add ($1);
706                 args.Add ($3);
707
708                 $$ = args;
709           }
710         | named_argument_list
711           {
712                 ArrayList args = new ArrayList ();
713                 args.Add (null);
714                 args.Add ($1);
715                 
716                 $$ = args;
717           }
718         ;
719
720
721 opt_positional_argument_list
722         : /* empty */           { $$ = null; } 
723         | positional_argument_list
724         ;
725
726 positional_argument_list
727         : expression
728           {
729                 ArrayList args = new ArrayList ();
730                 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
731
732                 $$ = args;
733           }
734         | positional_argument_list COMMA expression
735          {
736                 ArrayList args = (ArrayList) $1;
737                 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
738
739                 $$ = args;
740          }
741         ;
742
743 named_argument_list
744         : named_argument
745           {
746                 ArrayList args = new ArrayList ();
747                 args.Add ($1);
748
749                 $$ = args;
750           }
751         | named_argument_list COMMA named_argument
752           {       
753                 ArrayList args = (ArrayList) $1;
754                 args.Add ($3);
755
756                 $$ = args;
757           }
758         ;
759
760 named_argument
761         : identifier ATTR_ASSIGN expression
762           {
763                 $$ = new DictionaryEntry (
764                         (string) $1, 
765                         new Argument ((Expression) $3, Argument.AType.Expression));
766           }
767         ;
768                                 
769 namespace_declaration
770         : opt_attributes NAMESPACE qualified_identifier EOL
771           {
772                 Attributes attrs = (Attributes) $1;
773
774                 if (attrs != null) {
775                         foreach (AttributeSection asec in attrs.AttributeSections)
776                                 if (asec.Target == "assembly")
777                                         RootContext.AddGlobalAttributeSection (current_container, asec);
778                 }
779                           
780                 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$3);
781           } 
782           opt_imports_directives
783           opt_declarations
784           END NAMESPACE EOL
785           { 
786                 current_namespace = current_namespace.Parent;
787           }
788         ;
789
790 type_declaration
791         : opt_attributes 
792           opt_modifiers 
793           { 
794                 current_attributes = (Attributes) $1; 
795                 current_modifiers = (int) $2; 
796           }       
797           type_spec_declaration
798         ;
799
800 type_spec_declaration
801         : class_declaration
802         | module_declaration
803         | interface_declaration
804         | delegate_declaration
805         | struct_declaration
806         | enum_declaration
807         ;
808
809 class_declaration
810         : CLASS identifier EOL opt_inherits opt_implements
811           {
812                 // Module members are static by default, but Class *can't* be declared static
813                 // so we must fix it, if mbas was the one actually responsible for this
814                 // instead of triggering an error.
815                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
816                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
817           
818                 Class new_class;
819                 string name;
820                 
821                 name = MakeName ((string) $2);
822                 new_class = new Class (current_container, name, current_modifiers, 
823                                        (Attributes) current_attributes, lexer.Location);
824
825                 current_container = new_class;
826                 current_container.Namespace = current_namespace;
827                 RootContext.Tree.RecordDecl (name, new_class);
828           }
829           opt_class_member_declarations
830           END CLASS EOL
831           {
832                 Class new_class = (Class) current_container;
833                 new_class.Bases = (ArrayList) $4;       
834         
835                 current_container = current_container.Parent;
836                 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
837
838                 $$ = new_class;
839           }
840         ;
841
842 opt_inherits
843         : /* empty */                           { $$ = null; }
844         | INHERITS type_list EOL        { $$ = $2; }
845         ;
846
847 opt_implements
848         : /* empty */                           { $$ = null; }
849         | IMPLEMENTS type_list EOL      { $$ = $2; }
850         ;
851
852 opt_modifiers
853         : /* empty */           { $$ = (int) 0; current_modifiers = 0; }
854         | modifiers             { $$ = $1; current_modifiers = (int) $1; }
855         ;
856         
857 modifiers
858         : modifier
859         | modifiers modifier
860           { 
861                 int m1 = (int) $1;
862                 int m2 = (int) $2;
863
864                 if ((m1 & m2) != 0) {
865                         Location l = lexer.Location;
866                         Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
867                 }
868                 $$ = (int) (m1 | m2);
869           }
870         ;
871
872 modifier
873         : PUBLIC                        { $$ = Modifiers.PUBLIC; }
874         | PROTECTED                     { $$ = Modifiers.PROTECTED; }
875         | PRIVATE                       { $$ = Modifiers.PRIVATE; }
876         | SHARED                        { $$ = Modifiers.STATIC; }
877         | FRIEND                        { $$ = Modifiers.INTERNAL; }
878         | NOTINHERITABLE                { $$ = Modifiers.SEALED; } 
879         | OVERRIDABLE                   { $$ = Modifiers.VIRTUAL; }
880         | NOTOVERRIDABLE                { $$ = Modifiers.NONVIRTUAL; }
881         | OVERRIDES                     { $$ = Modifiers.OVERRIDE; }
882         | OVERLOADS                     { $$ = Modifiers.NEW; }
883         | SHADOWS                       { $$ = Modifiers.SHADOWS; }
884         | MUSTINHERIT                   { $$ = Modifiers.ABSTRACT; }
885         | READONLY                      { $$ = Modifiers.READONLY; }
886         | DEFAULT                       { $$ = Modifiers.DEFAULT; }
887         | WRITEONLY                     { $$ = Modifiers.WRITEONLY; }
888         ;
889
890 module_declaration
891         : MODULE identifier EOL
892           { 
893                 Module new_module;
894                 string name;
895                 name = MakeName((string) $2);
896                 new_module = new Module(current_container, 
897                                         name, 
898                                         current_modifiers, // already checks then
899                                         (Attributes) current_attributes,
900                                         lexer.Location);
901                 current_container = new_module;
902                 current_container.Namespace = current_namespace;
903                 RootContext.Tree.RecordDecl(name, new_module);
904           }
905           opt_module_member_declarations
906           END MODULE EOL
907           {
908                 Module new_module = (Module)current_container;
909
910                 current_container = current_container.Parent;
911                 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
912                 
913                 TypeManager.AddStandardModule(new_module);
914
915                 $$ = new_module;
916           }
917         ;
918
919 opt_module_member_declarations
920         : /* empty */
921         | module_member_declarations
922         ;
923
924 module_member_declarations
925         : module_member_declaration
926         | module_member_declarations module_member_declaration
927         ;
928
929 module_member_declaration
930         :  opt_attributes
931            opt_modifiers
932            { 
933                 current_attributes = (Attributes) $1;
934                 current_modifiers = ((int)$2) | Modifiers.STATIC; 
935                 bool explicit_static = (((int) $2 & Modifiers.STATIC) > 0);
936                 implicit_modifiers = (!explicit_static);
937            }
938            module_member_declarator
939            {
940                 implicit_modifiers = false;
941                 $$ = $3;
942            }
943         ;
944
945 module_member_declarator
946         :  constructor_declaration
947         |  method_declaration
948            { 
949                 Method method = (Method) $1;
950                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
951            }    
952         |  field_declaration
953         |  withevents_declaration       /* This is a field but must be treated specially, see below */
954         |  constant_declaration
955         |  property_declaration                 
956         |  event_declaration    
957         |  type_spec_declaration                        
958         ;
959         
960 constant_declaration
961         : CONST constant_declarators EOL
962         {
963                 // Module members are static by default, but constants *can't* be declared static
964                 // so we must fix it, if mbas was the one actually responsible for this
965                 // instead of triggering an error.
966                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
967                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
968                 
969                 int mod = (int) current_modifiers;
970                 
971                 // Structure members are Public by default                      
972                 if ((current_container is Struct) && (mod == 0))
973                         mod = Modifiers.PUBLIC;                 
974
975                 ArrayList consts = (ArrayList) $2;
976                 if(consts.Count > 0) 
977                 {
978                         VariableDeclaration.FixupTypes ((ArrayList) $2);
979                         VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
980
981                         foreach (VariableDeclaration var in (ArrayList) $2){
982                                 Location l = var.Location;
983                                 Const vconstant = new Const ((Expression)var.type, (String)var.identifier, 
984                                                         (Expression)var.expression_or_array_initializer, 
985                                                         mod, (Attributes) null, l);
986
987                                 CheckDef (current_container.AddConstant (vconstant), vconstant.Name, l);
988                         }
989                 }
990         }
991         ;
992            
993 opt_class_member_declarations
994         : /* empty */
995         | class_member_declarations
996         ;
997
998 class_member_declarations
999         : class_member_declaration
1000         | class_member_declarations class_member_declaration
1001         ;
1002
1003 class_member_declaration
1004         :  opt_attributes
1005            opt_modifiers
1006            { 
1007                 current_attributes = (Attributes) $1;
1008                 current_modifiers = (int) $2;
1009            }
1010            class_member_declarator
1011            {
1012                 $$ = $3;
1013            }
1014         ;
1015
1016 class_member_declarator
1017         :  constructor_declaration
1018         |  method_declaration
1019            { 
1020                 Method method = (Method) $1;
1021                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
1022            }    
1023         |  field_declaration
1024         |  constant_declaration
1025         |  property_declaration                 
1026         |  event_declaration    
1027         |  withevents_declaration       /* This is a field but must be treated specially, see below */
1028         |  type_spec_declaration
1029         ;
1030         
1031         
1032 method_declaration
1033         : sub_declaration
1034         | func_declaration 
1035         | must_override_declaration
1036         ;
1037         
1038 must_override_declaration
1039         : must_override_sub_declaration
1040         | must_override_func_declaration        
1041         ;
1042         
1043 must_override_sub_declaration
1044         : MUSTOVERRIDE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1045           {     
1046                 if (current_container is Module)
1047                         Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
1048                         
1049                 if (current_container is Struct)
1050                         Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1051                 
1052                 current_modifiers |= Modifiers.ABSTRACT;
1053                                         
1054                 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3,
1055                                             (Parameters) $5, null, null, lexer.Location);
1056                                             
1057                 if (!(current_container is Class))
1058                         Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");               
1059                         
1060                 // FIXME ASAP: This will crash the compiler at resolution time                  
1061                 $$ = method;                        
1062           }
1063         ;
1064
1065         
1066 must_override_func_declaration
1067         : MUSTOVERRIDE FUNCTION identifier opt_type_character OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks EOL
1068           {     
1069                 Expression ftype = ($8 == null) ? (($4 == null) ? TypeManager.  
1070                         system_object_expr : (Expression) $4 ) : (Expression) $8;
1071
1072                 if (current_container is Module)
1073                         Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
1074                         
1075                 if (current_container is Struct)
1076                         Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1077                                 
1078                 current_modifiers |= Modifiers.ABSTRACT;
1079                                                         
1080                 Method method = new Method ((Expression) ftype, (int) current_modifiers, 
1081                                                 (string) $3,(Parameters) $6, null, null, 
1082                                                 lexer.Location);
1083                                             
1084                 if (!(current_container is Class))
1085                         Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1086                         
1087                 $$ = method;                                    
1088           }     
1089         ;
1090         
1091 sub_declaration
1092         : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
1093           { 
1094                 current_local_parameters = (Parameters) $4;
1095                 start_block(); 
1096
1097                 // Structure members are Public by default                      
1098                 if ((current_container is Struct) && (current_modifiers == 0))
1099                         current_modifiers = Modifiers.PUBLIC;           
1100                         
1101                 member_location = lexer.Location;
1102           }
1103           opt_statement_list 
1104           END SUB EOL
1105           {
1106                 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
1107                                             (Parameters) current_local_parameters, (Attributes) current_attributes, 
1108                                             (Expression) $7, member_location);
1109         
1110                 method.Block = (Block) end_block();
1111                 $$ = method;
1112
1113                 if ($6 != null) { 
1114                         // we have an event handler to take care of 
1115
1116                         string evt_def = ((MemberAccess)$6).ToString();
1117                         int pos = evt_def.LastIndexOf (".");
1118                         string evt_target = evt_def.Substring (0, pos);
1119                         bool found = false;
1120                 
1121                         if (current_container.Properties != null) {
1122                                 foreach (Property p in current_container.Properties) {
1123                                         if (p.Name == evt_target) {
1124                                                 Location loc = lexer.Location;
1125
1126                                                 Statement addhnd = (Statement) new AddHandler ((Expression) $6, 
1127                                                                                         DecomposeQI((string) $2, loc), 
1128                                                                                         DecomposeQI(evt_target, loc), loc);
1129
1130                                                 current_container.AddEventHandler (addhnd);
1131                                                 found = true;
1132                                                 break;
1133                                         }
1134                                 }               
1135                         }
1136
1137                         if (!found){
1138                                 Report.Error(30506, lexer.Location,
1139                                                 evt_target + " is not declared with WithEvents");
1140                         }
1141                 }       
1142           }       
1143         ;
1144         
1145 func_declaration
1146         : FUNCTION identifier opt_type_character
1147           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks opt_implement_clause EOL
1148           { 
1149                 current_local_parameters = (Parameters) $5;
1150                 member_location = lexer.Location;
1151                 start_block(); 
1152                                 
1153                 Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
1154
1155                 // Structure members are Public by default                      
1156                 if ((current_container is Struct) && (current_modifiers == 0))
1157                         current_modifiers = Modifiers.PUBLIC;                           
1158                 // Add local var declaration
1159                 // for return value
1160                 ArrayList retval = new ArrayList ();
1161                 retval.Add (new VariableDeclaration ((string) $2, (Expression) ftype, lexer.Location));
1162                 declare_local_variables ((Expression) ftype, retval, lexer.Location);
1163           }       
1164           opt_statement_list
1165           END FUNCTION EOL
1166           {
1167                 Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
1168
1169                 Method method = new Method ((Expression) ftype, (int) current_modifiers, (string) $2,
1170                                             (Parameters) current_local_parameters, (Attributes) current_attributes,/* (Attributes) currx ent_attributes,  */
1171                                             (Expression) $8, member_location);
1172                 method.Block = end_block();
1173                 $$ = method;
1174           }       
1175         ;               
1176
1177 struct_declaration
1178         : STRUCTURE identifier EOL
1179           opt_implement_clause
1180           {
1181                 Struct new_struct;
1182                 string full_struct_name = MakeName ((string) $2);
1183                 
1184                 // Module members are static by default, but structures *can't* be declared static
1185                 // so we must fix it, if mbas was the one actually responsible for this
1186                 // instead of triggering an error.
1187                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1188                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1189                         
1190                 new_struct = new Struct (current_container, full_struct_name, 
1191                                          (int) current_modifiers,
1192                                          (Attributes) current_attributes, lexer.Location);
1193                 current_container = new_struct;
1194                 current_container.Namespace = current_namespace;
1195                 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1196           }
1197           opt_struct_member_declarations
1198           {
1199                 Struct new_struct = (Struct) current_container;
1200
1201                 if ($4 != null)
1202                         new_struct.Bases = (ArrayList) $4;
1203
1204                 current_container = current_container.Parent;
1205                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1206                 $$ = new_struct;
1207           }
1208           END STRUCTURE EOL
1209         ;
1210         
1211 opt_struct_member_declarations
1212         : /* empty */
1213         | struct_member_declarations
1214         ;
1215
1216 struct_member_declarations
1217         : struct_member_declaration
1218         | struct_member_declarations struct_member_declaration
1219         ;
1220
1221 struct_member_declaration
1222         : opt_modifiers
1223           struct_member_declarator
1224         ;
1225         
1226 struct_member_declarator        
1227         : field_declaration
1228         | constant_declaration
1229         | constructor_declaration
1230         | method_declaration
1231           { 
1232                 Method method = (Method) $1;
1233                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
1234           }     
1235         | property_declaration
1236         | event_declaration
1237         | type_spec_declaration
1238
1239         /*
1240          * This is only included so we can flag error 575:
1241          * destructors only allowed on class types
1242          */
1243         //| destructor_declaration
1244         ;
1245         
1246 event_declaration
1247         : EVENT identifier AS type EOL
1248           {
1249                 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1250
1251                 Event e = new Event ((Expression) $4, var.identifier, 
1252                                      null, current_modifiers, null, null, 
1253                                      current_attributes, lexer.Location);
1254
1255                 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1256
1257           }
1258         | EVENT identifier opt_event_params EOL
1259           {
1260                 string delName = (string) $2;
1261                 delName = delName + "EventHandler";
1262             Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate 
1263                                                 (current_container, TypeManager.system_void_expr, 
1264                                              (int) current_modifiers, MakeName(delName), (Parameters) $3, 
1265                                              (Attributes) current_attributes, lexer.Location);
1266                                                   
1267                 del.Namespace = current_namespace;
1268                 CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location);
1269           
1270                 Event e = new Event (DecomposeQI (delName, lexer.Location),
1271                                          (string) $2, 
1272                                      null, current_modifiers, null, null, 
1273                                      current_attributes, lexer.Location);
1274
1275                 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1276           }
1277         ;
1278         
1279 opt_event_params
1280         : /* empty */   { $$ = Parameters.EmptyReadOnlyParameters; }
1281         | OPEN_PARENS CLOSE_PARENS      { $$ = Parameters.EmptyReadOnlyParameters; }
1282         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS    { $$ = $2; }
1283         ;
1284         
1285 enum_declaration
1286         : ENUM identifier opt_type_spec EOL
1287           opt_enum_member_declarations
1288           { 
1289                 Location enum_location = lexer.Location;
1290                 string full_name = MakeName ((string) $2);
1291                 Expression enum_type = ($3 == null) ? TypeManager.system_int32_expr : (Expression) $3;
1292                 ArrayList enum_members = (ArrayList) $5;
1293                 
1294                 // Module members are static by default, but enums *can't* be declared static
1295                 // so we must fix it if mbas was the one actually responsible for this
1296                 // instead of triggering an error.
1297                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1298                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1299                         
1300                 Mono.MonoBASIC.Enum e = new Mono.MonoBASIC.Enum (current_container, enum_type, 
1301                                         (int) current_modifiers, full_name, 
1302                                         (Attributes) current_attributes, enum_location);
1303                 
1304                 foreach (VariableDeclaration ev in enum_members) {
1305                         Location loc = (Location) ev.Location;
1306
1307                         CheckDef (e.AddEnumMember (ev.identifier, 
1308                                                    (Expression) ev.expression_or_array_initializer,
1309                                                    loc, ev.OptAttributes), ev.identifier, loc);
1310                 }
1311
1312                 e.Namespace = current_namespace;
1313
1314                 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1315                 RootContext.Tree.RecordDecl (full_name, e);
1316
1317           }
1318           END ENUM EOL
1319         ;
1320
1321 opt_enum_member_declarations
1322         : /* empty */                   { $$ = new ArrayList (); }
1323         | enum_member_declarations      { $$ = $1; }
1324         ;
1325
1326 enum_member_declarations
1327         : enum_member_declaration 
1328           {
1329                 ArrayList l = new ArrayList ();
1330
1331                 l.Add ($1);
1332                 $$ = l;
1333           }
1334         | enum_member_declarations  enum_member_declaration
1335           {
1336                 ArrayList l = (ArrayList) $1;
1337
1338                 l.Add ($2);
1339
1340                 $$ = l;
1341           }
1342         ;
1343
1344 enum_member_declaration
1345         : opt_attributes identifier EOL
1346           {
1347                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1348           }
1349         | opt_attributes identifier
1350           {
1351                   $$ = lexer.Location;
1352           }
1353           ASSIGN expression EOL
1354           { 
1355                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1356           }
1357         ;
1358                 
1359 interface_declaration
1360         : INTERFACE identifier EOL
1361           {
1362                 Interface new_interface;
1363                 string full_interface_name = MakeName ((string) $2);
1364
1365                 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1366                                                (Attributes) current_attributes, lexer.Location);
1367                 if (current_interface != null) {
1368                         Location l = lexer.Location;
1369                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
1370                 }
1371                 current_interface = new_interface;
1372                 new_interface.Namespace = current_namespace;
1373                 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1374           }
1375           opt_interface_base
1376           interface_body
1377           { 
1378                 Interface new_interface = (Interface) current_interface;
1379
1380                 if ($5 != null)
1381                         new_interface.Bases = (ArrayList) $5;
1382
1383                 current_interface = null;
1384                 CheckDef (current_container.AddInterface (new_interface),
1385                           new_interface.Name, new_interface.Location);
1386
1387           }
1388           END INTERFACE EOL
1389         ;
1390
1391 opt_interface_base
1392         : /* empty */                     { $$ = null; }
1393         | interface_base
1394         ;
1395
1396 interface_base
1397         : INHERITS interface_type_list    { $$ = $2; }
1398         ;
1399
1400 interface_type_list
1401         : interface_type
1402           {
1403                 ArrayList interfaces = new ArrayList ();
1404
1405                 interfaces.Add ($1);
1406                 $$ = interfaces;
1407           }
1408         | interface_type_list COMMA interface_type
1409           {
1410                 ArrayList interfaces = (ArrayList) $1;
1411                 interfaces.Add ($3);
1412                 $$ = interfaces;
1413           }
1414         ;
1415
1416 interface_body
1417         : opt_interface_member_declarations
1418         ;
1419
1420 opt_interface_member_declarations
1421         : /* empty */
1422         | interface_member_declarations
1423         ;
1424
1425 interface_member_declarations
1426         : interface_member_declaration
1427         | interface_member_declarations interface_member_declaration
1428         ;
1429
1430 interface_member_declaration
1431         : interface_method_declaration          
1432           { 
1433                 InterfaceMethod m = (InterfaceMethod) $1;
1434
1435                 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1436           }
1437         | interface_property_declaration        
1438           { 
1439                 InterfaceProperty p = (InterfaceProperty) $1;
1440                 
1441                 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1442           }
1443         | interface_event_declaration 
1444           { 
1445                 InterfaceEvent e = (InterfaceEvent) $1;
1446
1447                 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1448           }
1449         ;
1450
1451 opt_new
1452         : /* empty */   { $$ = false; }
1453         | NEW           { $$ = true; }
1454         ;
1455         
1456 interface_method_declaration
1457         : SUB identifier
1458           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1459           {
1460                 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1461                                           (Parameters) $4, current_attributes, lexer.Location);
1462           }
1463         | FUNCTION identifier opt_type_character
1464           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1465           {
1466                 if ($3 != null && $3 != $8)
1467                         Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1468                 
1469                 $$ = new InterfaceMethod (
1470                                           (Expression) $8, (string) $2, false, (Parameters) $5,
1471                                           current_attributes, lexer.Location);
1472           }
1473         | FUNCTION identifier type_character
1474           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1475           {
1476                 $$ = new InterfaceMethod (
1477                                           (Expression) $3, (string) $2, false, (Parameters) $5,
1478                                           current_attributes, lexer.Location);
1479           }
1480         ;
1481
1482 interface_property_declaration
1483         : opt_modifiers PROPERTY identifier
1484           OPEN_PARENS
1485           opt_formal_parameter_list
1486           CLOSE_PARENS opt_type_spec EOL
1487           {
1488                 // FIXME we MUST pass property parameters
1489                 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1490                                             true, true, current_attributes,
1491                                             lexer.Location);
1492           }
1493         ;
1494         
1495 interface_event_declaration
1496         : opt_attributes opt_new EVENT type identifier EOL
1497           {
1498                 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1499                                          lexer.Location);
1500           }
1501         ;
1502
1503  property_declaration
1504         : abstruct_propery_declaration
1505         | non_abstruct_propery_declaration 
1506         ;
1507         
1508 abstruct_propery_declaration
1509         : MUSTOVERRIDE PROPERTY identifier opt_type_character opt_property_parameters AS type EOL
1510           {     
1511                 Expression ftype = ($7 == null) ? (($4 == null) ? 
1512                                 TypeManager.system_object_expr : (Expression) $4 ) : (Expression) $7;
1513
1514                 if (current_container is Module)
1515                         Report.Error (30503, "Properties in a Module cannot be declared 'MustOverride'.");
1516                         
1517                 if (current_container is Struct)
1518                         Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1519                                 
1520                 current_modifiers |= Modifiers.ABSTRACT;
1521                 
1522                 current_local_parameters = (Parameters) $5;
1523                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
1524                         get_parameters = current_local_parameters.Copy (lexer.Location);
1525                         set_parameters = current_local_parameters.Copy (lexer.Location);
1526                 }
1527                 else
1528                 {
1529                         get_parameters = Parameters.EmptyReadOnlyParameters;
1530                         set_parameters = new Parameters (null, null ,lexer.Location); 
1531                         
1532                         Parameter implicit_value_parameter = new Parameter (
1533                                         ftype, "Value", Parameter.Modifier.NONE, null);
1534                         
1535                         set_parameters.AppendParameter (implicit_value_parameter);
1536                 }
1537                 lexer.PropertyParsing = true;
1538                 
1539                 Accessor get_block = new Accessor (null, null); 
1540                 Accessor set_block = new Accessor (null, null); 
1541                                 
1542                 Property prop = new Property ((Expression) ftype, (string) $3, current_modifiers, 
1543                                          get_block, set_block, current_attributes, lexer.Location,
1544                                          null, get_parameters, set_parameters, null);
1545     
1546                 if (!(current_container is Class))
1547                         Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1548                         
1549                 CheckDef (current_container.AddProperty (prop), prop.Name, lexer.Location);
1550                 
1551                 get_implicit_value_parameter_type = null;
1552                 set_implicit_value_parameter_type = null;
1553                 get_parameters = null;
1554                 set_parameters = null;
1555                 current_local_parameters = null;                                
1556           }     
1557         ;
1558         
1559         
1560  non_abstruct_propery_declaration
1561           : PROPERTY identifier opt_type_character opt_property_parameters AS type opt_implement_clause EOL
1562           {
1563                 get_implicit_value_parameter_type  = 
1564                         ($6 == null) ? (($3 == null) ? 
1565                                 TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $6;
1566                 get_implicit_value_parameter_name = (string) $2;
1567                 
1568                 current_local_parameters = (Parameters) $4;
1569                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
1570                         get_parameters = current_local_parameters.Copy (lexer.Location);
1571                         set_parameters = current_local_parameters.Copy (lexer.Location);
1572                 }
1573                 else
1574                 {
1575                         get_parameters = Parameters.EmptyReadOnlyParameters;
1576                         set_parameters = new Parameters (null, null ,lexer.Location);           
1577                 }
1578                 lexer.PropertyParsing = true;
1579
1580                 $$ = lexer.Location;
1581           }
1582           accessor_declarations 
1583           END PROPERTY EOL
1584           {
1585                 lexer.PropertyParsing = false;
1586
1587                 Property prop;
1588                 Pair pair = (Pair) $10;
1589                 
1590                 Accessor get_block = null;
1591                 Accessor set_block = null;
1592                 
1593                 if (pair.First != null){
1594                         get_block = (Accessor) pair.First;
1595                 }
1596                 
1597                 if (pair.Second != null) {
1598                         set_block = (Accessor) pair.Second;
1599                 }
1600                 
1601                 Location loc = lexer.Location;
1602                 
1603                 // Structure members are Public by default                      
1604                 if ((current_container is Struct) && (current_modifiers == 0))
1605                         current_modifiers = Modifiers.PUBLIC;                           
1606                         
1607                 prop = new Property ((Expression) /*$6*/ get_implicit_value_parameter_type, 
1608                                          (string) $2, current_modifiers, get_block, set_block,
1609                                      current_attributes, loc, set_implicit_value_parameter_name, 
1610                                      get_parameters, set_parameters, (Expression) $7);
1611                 
1612                 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1613                 get_implicit_value_parameter_type = null;
1614                 set_implicit_value_parameter_type = null;
1615                 get_parameters = null;
1616                 set_parameters = null;
1617                 current_local_parameters = null;
1618           }
1619         ;
1620
1621 opt_property_parameters
1622         : /* empty */
1623           {
1624                 $$ = Parameters.EmptyReadOnlyParameters;
1625           }
1626         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1627           {
1628                 $$ = $2;
1629           }
1630         ;
1631         
1632 opt_implement_clause
1633         : /* empty */
1634           {
1635                 $$ = null;
1636           }
1637         | IMPLEMENTS qualified_identifier
1638           {
1639                 $$ = DecomposeQI ((string)$2, lexer.Location);
1640           }     
1641         ;
1642         
1643 accessor_declarations
1644         : get_accessor_declaration opt_set_accessor_declaration
1645           { 
1646                 $$ = new Pair ($1, $2);
1647           }
1648         | set_accessor_declaration opt_get_accessor_declaration
1649           {
1650                 $$ = new Pair ($2, $1);
1651           }
1652         ;
1653
1654 opt_get_accessor_declaration
1655         : /* empty */                   { $$ = null; }
1656         | get_accessor_declaration
1657         ;
1658
1659 opt_set_accessor_declaration
1660         : /* empty */                   { $$ = null; }
1661         | set_accessor_declaration
1662         ;
1663
1664 get_accessor_declaration
1665         : opt_attributes GET EOL
1666           {
1667                 if ((current_modifiers & Modifiers.WRITEONLY) != 0)
1668                         Report.Error (30023, "'WriteOnly' properties cannot have a 'Get' accessor");
1669           
1670                 current_local_parameters = get_parameters;
1671                 
1672                 lexer.PropertyParsing = false;
1673                 
1674                 start_block();  
1675                 // Add local var declaration
1676                 // for return value
1677                 ArrayList retval = new ArrayList ();
1678                 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1679                 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);    
1680           }
1681           opt_statement_list
1682           END GET EOL
1683           {
1684                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1685                 current_local_parameters = null;
1686                 lexer.PropertyParsing = true;
1687           }
1688         ;
1689
1690 set_accessor_declaration
1691         : opt_attributes SET opt_set_parameter EOL
1692           {
1693         if ((current_modifiers & Modifiers.READONLY) != 0)
1694                         Report.Error (30022, "'ReadOnly' properties cannot have a 'Set' accessor");
1695                         
1696                 Parameter implicit_value_parameter = new Parameter (
1697                         set_implicit_value_parameter_type, 
1698                         set_implicit_value_parameter_name, 
1699                         Parameter.Modifier.NONE, null);
1700
1701                 current_local_parameters = set_parameters;
1702                 current_local_parameters.AppendParameter (implicit_value_parameter);
1703                 
1704                 start_block();
1705                 lexer.PropertyParsing = false;
1706           }
1707           opt_statement_list
1708           END SET EOL
1709           {
1710                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1711                 current_local_parameters = null;
1712                 lexer.PropertyParsing = true;
1713           }
1714         ;
1715                 
1716 opt_set_parameter
1717         : /* empty */
1718         {
1719                 set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; // TypeManager.system_object_expr;
1720                 set_implicit_value_parameter_name = "Value";
1721         }       
1722         |OPEN_PARENS CLOSE_PARENS
1723         {
1724                 set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type;
1725                 set_implicit_value_parameter_name = "Value";
1726         }       
1727         | OPEN_PARENS opt_parameter_modifier opt_identifier opt_type_spec CLOSE_PARENS
1728         {
1729                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1730                 if ((pm | Parameter.Modifier.VAL) != 0)
1731                         Report.Error (31065, 
1732                                 lexer.Location, 
1733                                 "Set cannot have a paremeter modifier other than 'ByVal'");
1734                                 
1735                 set_implicit_value_parameter_type = (Expression) $4;
1736                 
1737                 if (set_implicit_value_parameter_type != get_implicit_value_parameter_type)
1738                         Report.Error (31064, 
1739                                 lexer.Location, 
1740                                 "Set value parameter type can not be different from property type");
1741                 
1742                 if ($2 != null)
1743                         set_implicit_value_parameter_name = (string) $3;
1744                 else
1745                         set_implicit_value_parameter_name = "Value";
1746         }
1747         ;
1748                         
1749 field_declaration
1750         : opt_dim_stmt 
1751           variable_declarators EOL
1752           {               
1753                 int mod = (int) current_modifiers;
1754                 
1755
1756                 VariableDeclaration.FixupTypes ((ArrayList) $2);
1757                 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1758                 
1759                 if (current_container is Module)
1760                         mod = mod | Modifiers.STATIC;
1761                         
1762                 // Structure members are Public by default                      
1763                 if ((current_container is Struct) && (mod == 0))
1764                         mod = Modifiers.PUBLIC;                 
1765                 
1766                 if ((mod & Modifiers.Accessibility) == 0)
1767                         mod |= Modifiers.PRIVATE;
1768                                         
1769                 foreach (VariableDeclaration var in (ArrayList) $2){
1770                         Location l = var.Location;
1771                         Field field = new Field (var.type, mod, var.identifier, 
1772                                                  var.expression_or_array_initializer, 
1773                                                  (Attributes) null, l);
1774
1775                         CheckDef (current_container.AddField (field), field.Name, l);
1776                 }
1777           }
1778         ;
1779         
1780 withevents_declaration
1781         : opt_dim_stmt WITHEVENTS variable_declarators EOL
1782           {
1783                 // Module members are static by default, but delegates *can't* be declared static
1784                 // so we must fix it, if mbas was the one actually responsible for this
1785                 // instead of triggering an error.
1786                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1787                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1788           
1789                 /* WithEvents Fields must be resolved into properties
1790                    with a bit of magic behind the scenes */
1791                   
1792                 VariableDeclaration.FixupTypes ((ArrayList) $3);
1793                 
1794                 foreach (VariableDeclaration var in (ArrayList) $3) {
1795                         // 1 - We create a private field
1796                         Location l = var.Location;
1797                         Property prop;
1798                         if ((current_modifiers & Modifiers.STATIC) > 0) 
1799                                 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1800                         
1801                         Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, 
1802                                                  var.expression_or_array_initializer, 
1803                                                  (Attributes) null, l);
1804                                                  
1805                         CheckDef (current_container.AddField (field), field.Name, l);   
1806                         
1807                         // 2 - Public property
1808                                 
1809                         prop = BuildSimpleProperty (var.type, (string) var.identifier, 
1810                                                 field, (int) current_modifiers, 
1811                                                 (Attributes) current_attributes, l);
1812                         
1813                         CheckDef (current_container.AddProperty (prop), prop.Name, l);
1814                 }               
1815           }
1816         ;
1817         
1818 opt_dim_stmt 
1819         : /* empty */
1820         | DIM
1821         ; 
1822                 
1823 delegate_declaration
1824         : DELEGATE SUB  
1825           identifier OPEN_PARENS 
1826           opt_formal_parameter_list
1827           CLOSE_PARENS 
1828           EOL
1829           {
1830                 Location l = lexer.Location;
1831                 // Module members are static by default, but delegates *can't* be declared static
1832                 // so we must fix it, if mbas was the one actually responsible for this
1833                 // instead of triggering an error.
1834                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1835                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1836                                         
1837                 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (current_container, 
1838                                                  TypeManager.system_void_expr, 
1839                                              (int) current_modifiers, 
1840                                  MakeName ((string) $3), (Parameters) $5, 
1841                                              (Attributes) current_attributes, l);
1842                                                   
1843                 del.Namespace = current_namespace;
1844                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1845           }     
1846         | DELEGATE FUNCTION       
1847           identifier OPEN_PARENS 
1848           opt_formal_parameter_list
1849           CLOSE_PARENS opt_type_spec EOL
1850           {
1851                 Location l = lexer.Location;
1852                 
1853                 // Module members are static by default, but delegates *can't* be declared static
1854                 // so we must fix it, if mbas was the one actually responsible for this
1855                 // instead of triggering an error.
1856                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1857                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1858                         
1859                 Expression ftype = ($7 == null) ? TypeManager.system_object_expr : (Expression) $7;
1860                         
1861                 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (
1862                         current_container,
1863                         ftype, (int) current_modifiers, MakeName ((string) $3), 
1864                         (Parameters) $5, (Attributes) current_attributes, l);
1865
1866                 del.Namespace = current_namespace;
1867                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1868           }
1869         ;
1870         
1871 opt_evt_handler
1872         : /* empty */
1873           {     $$ = null; }
1874         | HANDLES qualified_identifier
1875           {
1876                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
1877           }
1878         | HANDLES MYBASE DOT qualified_identifier
1879           {
1880                 // FIXME: this is blatantly wrong and crash-prone
1881                 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
1882           }
1883         ;       
1884
1885 opt_empty_parens
1886         : /* empty */
1887         | OPEN_PARENS CLOSE_PARENS
1888         ;       
1889
1890 constructor_declaration
1891         : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1892           {
1893                 current_local_parameters = (Parameters) $4;
1894                 start_block();
1895                 oob_stack.Push (lexer.Location);
1896
1897                 Location l = (Location) oob_stack.Pop ();
1898                 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1899                 $1 = $$;
1900           }
1901           opt_statement_list
1902           { 
1903                 Constructor c = (Constructor) $1;
1904                 c.Block = (Block) end_block();
1905                 c.ModFlags = (int) current_modifiers;
1906                 c.OptAttributes = current_attributes;
1907                 
1908                 c.Initializer = CheckConstructorInitializer (ref c.Block.statements);
1909
1910                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1911                 current_local_parameters = null;
1912           }
1913           END SUB EOL
1914         ;
1915         
1916 opt_formal_parameter_list
1917         : /* empty */                   
1918           { 
1919                 $$ = Parameters.EmptyReadOnlyParameters; 
1920           }
1921         | formal_parameter_list 
1922           { 
1923                 $$ = $1;        
1924                 //Parameter p = ((Parameters) $1).FixedParameters[0];
1925           }
1926         ;
1927         
1928 formal_parameter_list
1929         : fixed_parameters              
1930           { 
1931                 ArrayList pars_list = (ArrayList) $1;
1932
1933                 Parameter [] pars = new Parameter [pars_list.Count];
1934                 pars_list.CopyTo (pars);
1935                 $$ = new Parameters (pars, null, lexer.Location); 
1936           } 
1937         | fixed_parameters COMMA parameter_array
1938           {
1939                 ArrayList pars_list = (ArrayList) $1;
1940
1941                 Parameter [] pars = new Parameter [pars_list.Count];
1942                 pars_list.CopyTo (pars);
1943
1944                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1945           }
1946         | parameter_array 
1947           {
1948                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1949           }
1950         ;
1951
1952 fixed_parameters
1953         : fixed_parameter       
1954           {
1955                 ArrayList pars = new ArrayList ();
1956
1957                 pars.Add ($1);
1958                 $$ = pars;
1959           }
1960         | fixed_parameters COMMA fixed_parameter
1961           {
1962                 ArrayList pars = (ArrayList) $1;
1963
1964                 pars.Add ($3);
1965                 $$ = $1;
1966           }
1967         ;
1968
1969 fixed_parameter
1970         : opt_attributes
1971           opt_parameter_modifier
1972           identifier opt_type_character opt_rank_specifiers opt_type_spec opt_variable_initializer
1973           {
1974                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1975                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1976                 Expression ptype;
1977                 
1978                 if (opt_parm && ($7 == null))
1979                         Report.Error (999, "Optional parameters must have a default value");
1980                 
1981                 if (opt_parm) {
1982                         if ((pm & Parameter.Modifier.REF) !=0)
1983                                 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1984                         else
1985                                 pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
1986                 }       
1987                 
1988                 if ($4 != null && $6 != null && $4 != $6)
1989                         Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1990
1991                 ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6);
1992                 if ($5 != null) {
1993                         string t = ptype.ToString() + VariableDeclaration.BuildRank ((ArrayList) $5);
1994                         ptype = DecomposeQI (t, lexer.Location);
1995                 }                       
1996                 $$ = new Parameter (ptype, (string) $3, pm,
1997                                         (Attributes) $1, (Expression) $7, opt_parm);
1998           }
1999         ;
2000         
2001 parameter_array
2002         : PARAM_ARRAY identifier opt_parens AS type 
2003           { 
2004                 string s_patype = ((Expression) $5).ToString();
2005                 if ((bool) $3)
2006                         s_patype += "[]";
2007                         
2008                 Expression patype = DecomposeQI (s_patype, Location.Null);
2009                 $$ = new Parameter (patype, (string) $2, Parameter.Modifier.PARAMS, null);
2010                 // note  ("type must be a single-dimension array type"); 
2011           }
2012         ;
2013                 
2014 opt_parens
2015         : /* empty */
2016           {     $$ = false;     }
2017         | OPEN_PARENS CLOSE_PARENS
2018           {     $$ = true;      }
2019         ;
2020         
2021 opt_parameter_modifier
2022         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
2023         | parameter_modifiers   { $$ = $1;                      }
2024         ;
2025
2026 parameter_modifiers
2027         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
2028         | parameter_modifier                            { $$ = $1;      }
2029         ;
2030         
2031 parameter_modifier
2032         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
2033         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
2034         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
2035         ;       
2036
2037 opt_statement_list
2038         : /* empty */
2039         | statement_list end_of_stmt
2040         ;
2041
2042 statement_list
2043         : statement 
2044         | statement_list end_of_stmt statement
2045         ;
2046         
2047 statement : 
2048             declaration_statement
2049             {
2050                   if ($1 != null && (Block) $1 != current_block){
2051                         current_block.AddStatement ((Statement) $1);
2052                         current_block = (Block) $1;
2053                   }
2054             }
2055           | embedded_statement
2056             {
2057                   Statement s = (Statement) $1;
2058
2059                   current_block.AddStatement ((Statement) $1);
2060             } 
2061           | labeled_statement 
2062           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
2063             {
2064                   AddHandler ((Expression) $2, (string) $5);
2065             }
2066           | REMOVEHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
2067                 {
2068                   RemoveHandler ((Expression) $2, (string) $5);
2069             }
2070           | RAISEEVENT identifier opt_raise_event_args  //OPEN_PARENS opt_argument_list CLOSE_PARENS
2071             {
2072               RaiseEvent ((string) $2, (ArrayList) $3);
2073             }
2074           /* | array_handling_statement */
2075           /* | empty_statement */
2076           | with_statement 
2077             {
2078                   Statement s = (Statement) $1;
2079
2080               current_block.AddStatement ((Statement) $1);
2081             }     
2082           ;     
2083           
2084 opt_raise_event_args 
2085         : /* empty */   { $$ = null; }
2086         | OPEN_PARENS opt_argument_list CLOSE_PARENS
2087           {
2088                 $$ = $2;
2089           }
2090         ;
2091
2092 labeled_statement
2093         : identifier COLON end_of_stmt 
2094           {
2095                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
2096
2097                 if (!current_block.AddLabel ((string) $1, labeled)){
2098                         Location l = lexer.Location;
2099                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2100                 }       
2101                 current_block.AddStatement (labeled);
2102           }
2103           statement
2104         ;
2105
2106 embedded_statement
2107         : expression_statement
2108         | selection_statement
2109         | iteration_statement
2110         | try_statement
2111         | jump_statement
2112         | array_handling_statement 
2113         ;
2114 /*        
2115 empty_statement
2116         : end_of_stmt
2117           {
2118                   $$ = new EmptyStatement ();
2119           }
2120         ;        
2121 */
2122
2123 with_statement
2124         : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */
2125           {
2126                 // was : Expression e = DecomposeQI ((string) $2, lexer.Location);
2127                 Expression e = (Expression) $2;
2128                 with_stack.Push(e);
2129                 start_block();
2130           }
2131           opt_statement_list
2132           END WITH
2133           {
2134                 Block b = end_block();
2135                 with_stack.Pop();
2136                 $$ = b;
2137           }
2138         ;
2139         
2140         
2141 array_handling_statement
2142         : redim_statement
2143         | erase_statement
2144         ;
2145         
2146 redim_statement
2147         : REDIM opt_preserve redim_clauses
2148           {
2149                 ArrayList list = (ArrayList) $3;
2150                 ReDim r = new ReDim (list, (bool) $2, lexer.Location);
2151                 $$ = r;
2152
2153           }
2154         ;
2155         
2156 opt_preserve
2157         : /* empty */   { $$ = false; }
2158         | PRESERVE      { $$ = true;  }
2159         ;
2160         
2161 redim_clauses
2162         : redim_clause
2163           {
2164                 ArrayList clauses = new ArrayList ();
2165
2166                 clauses.Add ($1);
2167                 $$ = clauses;
2168           }
2169         | redim_clauses COMMA redim_clause
2170           {
2171                 ArrayList clauses = (ArrayList) ($1);
2172                 clauses.Add ($2);
2173
2174                 $$ = clauses;
2175           }
2176         ;
2177
2178 redim_clause
2179         : invocation_expression
2180           {
2181                 Invocation i = (Invocation) $1;
2182                 RedimClause rc = new RedimClause (i.expr, i.Arguments);
2183                 $$ = rc;
2184           }
2185         ;
2186
2187 erase_statement
2188         : ERASE erase_clauses
2189         {
2190                 ArrayList list = (ArrayList) $2;
2191                 foreach(Expression e in list)
2192                 {
2193                         Erase r = new Erase (e, lexer.Location);
2194                         $$ = r;
2195                 }
2196         }
2197         ;
2198
2199 erase_clauses
2200         : erase_clause
2201           {
2202                 ArrayList clauses = new ArrayList ();
2203
2204                 clauses.Add ($1);
2205                 $$ = clauses;
2206           }
2207         | erase_clauses COMMA erase_clause
2208           {
2209                 ArrayList clauses = (ArrayList) ($1);
2210                 clauses.Add ($2);
2211
2212                 $$ = clauses;
2213           }
2214         ;
2215
2216 erase_clause
2217         : primary_expression
2218         ;       
2219                         
2220 jump_statement
2221         : /*break_statement
2222         | continue_statement
2223         | */return_statement
2224         | goto_statement        
2225         | throw_statement       
2226         | exit_statement
2227         | yield_statement
2228         ;
2229                 
2230 goto_statement
2231         : GOTO identifier  
2232           {
2233                 $$ = new Goto (current_block, (string) $2, lexer.Location);
2234           }
2235         ;
2236         
2237 throw_statement
2238         : THROW opt_expression
2239           {
2240                 $$ = new Throw ((Expression) $2, lexer.Location);
2241           }
2242         ;       
2243                         
2244 exit_statement
2245         : EXIT exit_type
2246           {
2247                 $$ = new Exit ((ExitType)$2, lexer.Location);           
2248           }
2249         ;
2250         
2251 exit_type
2252         : DO            { $$ = ExitType.DO;             }
2253         | FOR           { $$ = ExitType.FOR;            }
2254         | WHILE         { $$ = ExitType.WHILE;          }
2255         | SELECT        { $$ = ExitType.SELECT;         }
2256         | SUB           { $$ = ExitType.SUB;            }
2257         | FUNCTION      { $$ = ExitType.FUNCTION;       }
2258         | PROPERTY      { $$ = ExitType.PROPERTY;       }
2259         | TRY           { $$ = ExitType.TRY;            }
2260         ;
2261 return_statement
2262         : RETURN opt_expression 
2263           {       
2264                 $$ = new Return ((Expression) $2, lexer.Location);
2265           }
2266         ;
2267                 
2268 iteration_statement
2269         : while_statement
2270         | do_statement
2271         | for_statement
2272         | foreach_statement
2273         ;
2274
2275 foreach_statement
2276         : FOR EACH identifier IN 
2277           {
2278                 oob_stack.Push (lexer.Location);
2279           }       
2280           expression end_of_stmt
2281           {
2282                 
2283                 start_block();
2284                 Block foreach_block = current_block;
2285                 Location l = lexer.Location;            
2286                 LocalVariableReference v = null;
2287                 VariableInfo vi;
2288
2289                 vi = foreach_block.GetVariableInfo ((string) $3);
2290                 if (vi != null) {
2291                         // Get a reference to this variable.
2292                         v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2293                 }
2294                 else
2295                         Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2296         
2297                 oob_stack.Push (v);
2298           }       
2299           opt_statement_list
2300           NEXT opt_identifier
2301           {
2302                 Block foreach_block = current_block;
2303                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2304                 Block prev_block = end_block();
2305                 Location l = (Location) oob_stack.Pop ();
2306
2307                 Foreach f = null;
2308                 if (v != null) {
2309                         f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
2310                 }
2311                 
2312                 $$ = f;
2313           }       
2314         ;
2315
2316 yield_statement 
2317         : YIELD expression
2318           {
2319                 if (!UseExtendedSyntax)
2320                 {
2321                         ReportError9998();
2322                         $$ = null;
2323                 }
2324 /*              else
2325                         if (iterator_container == null){
2326                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2327                                 $$ = null;
2328                         } else {
2329                                 iterator_container.SetYields ();
2330                                 $$ = new Yield ((Expression) $2, lexer.Location);
2331                         } */
2332           }
2333         | YIELD STOP
2334           {
2335                 if (!UseExtendedSyntax)
2336                 {
2337                         ReportError9998();
2338                         $$ = null;
2339                 }
2340 /*              else
2341                         if (iterator_container == null){
2342                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2343                                 $$ = null;
2344                         } else {
2345                                 iterator_container.SetYields ();
2346                                 $$ = new YieldBreak (lexer.Location);
2347                         } */
2348           }
2349         ;
2350
2351
2352
2353 try_statement
2354         : try_catch
2355         | try_catch_finally
2356         ;
2357                                 
2358 try_header
2359         : TRY end_of_stmt
2360           {   
2361                 start_block();  
2362           }
2363           opt_statement_list 
2364           opt_catch_clauses
2365           {
2366                 tmp_catch_clauses = (ArrayList) $5;
2367           }
2368         ;
2369                                         
2370 try_catch
2371         : try_header 
2372           END TRY
2373           { 
2374                 Catch g = null;
2375                 ArrayList s = new ArrayList ();
2376
2377                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2378                         if (cc.IsGeneral)
2379                                 g = cc;
2380                         else
2381                                 s.Add (cc);
2382                 }
2383
2384                 // Now s contains the list of specific catch clauses
2385                 // and g contains the general one.
2386                 Block b = end_block();
2387
2388                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2389           }       
2390         ;       
2391           
2392 try_catch_finally
2393         : try_header 
2394           { 
2395                 tmp_block = end_block(); 
2396           }     
2397           FINALLY end_of_stmt
2398           { 
2399                 start_block(); 
2400           }       
2401           opt_statement_list 
2402           END TRY
2403           {
2404                 Catch g = null;
2405                 ArrayList s = new ArrayList ();
2406                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2407
2408                 if (catch_list != null){
2409                         foreach (Catch cc in catch_list) {
2410                                 if (cc.IsGeneral)
2411                                         g = cc;
2412                                 else
2413                                         s.Add (cc);
2414                         }
2415                 }
2416
2417                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2418         
2419           }     
2420           ;             
2421
2422 opt_catch_clauses
2423         : /* empty */  {  $$ = null;  }
2424         | catch_clauses
2425         ;
2426
2427 catch_clauses
2428         : catch_clause 
2429           {
2430                 ArrayList l = new ArrayList ();
2431
2432                 l.Add ($1);
2433                 $$ = l;
2434           }
2435         | catch_clauses catch_clause
2436           {
2437                 ArrayList l = (ArrayList) $1;
2438
2439                 l.Add ($2);
2440                 $$ = l;
2441           }
2442         ;
2443
2444 opt_identifier
2445         : /* empty */   {  $$ = null;  }
2446         | identifier
2447         ;
2448
2449 catch_clause 
2450         : CATCH opt_catch_args end_of_stmt
2451         {
2452                 Expression type = null;
2453                 string id = null;
2454                 
2455                 if ($2 != null) {
2456                         DictionaryEntry cc = (DictionaryEntry) $2;
2457                         type = (Expression) cc.Key;
2458                         id   = (string) cc.Value;
2459                         
2460                         if (id != null){
2461                                 ArrayList one = new ArrayList ();
2462                                 Location loc = lexer.Location;
2463
2464                                 one.Add (new VariableDeclaration (id, type, loc));
2465
2466
2467                                 $1 = current_block;
2468                                 current_block = new Block (current_block);
2469                                 Block b = declare_local_variables (type, one, loc);
2470                                 current_block = b;
2471                         }
2472                 }
2473         
2474         } 
2475         opt_statement_list {
2476                 Expression type = null;
2477                 string id = null;
2478                 Block b_catch = current_block;
2479                 
2480                 if ($2 != null){
2481                         DictionaryEntry cc = (DictionaryEntry) $2;
2482                         type = (Expression) cc.Key;
2483                         id   = (string) cc.Value;
2484                         
2485                         if ($1 != null) {
2486                                 //
2487                                 // FIXME: I can change this for an assignment.
2488                                 //
2489                                 while (current_block != (Block) $1)
2490                                         current_block = current_block.Parent;
2491                         }
2492                 }
2493
2494                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2495         }
2496         ;
2497
2498 opt_catch_args
2499         : /* empty */ {  $$ = null; }
2500         | catch_args
2501         ;         
2502
2503 catch_args 
2504         : identifier AS type
2505         {
2506                  $$ = new DictionaryEntry ($3, $1); 
2507         }
2508         ;
2509         
2510         
2511 do_statement
2512         : DO opt_do_construct end_of_stmt
2513           {
2514                 start_block();
2515                 oob_stack.Push (lexer.Location);
2516           }     
2517           opt_statement_list
2518           LOOP opt_do_construct
2519           {
2520                 Expression t_before = (Expression) $2;
2521                 Expression t_after = (Expression) $7;
2522                 Expression t;
2523
2524                 if  ((t_before != null) && (t_after != null))
2525                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2526
2527                 if ((t_before == null) && (t_after == null))
2528                         t = new BoolLiteral (true);
2529                 else
2530                         t = (t_before != null) ? t_before : t_after;
2531                         
2532                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2533                 
2534                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2535                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2536                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2537                          
2538                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2539           }
2540           ;
2541
2542 opt_do_construct
2543         : /* empty */ { $$ = null; }
2544         | while_or_until boolean_expression
2545           {
2546                 do_type = (DoOptions)$1;
2547                 $$ = (Expression) $2;
2548           }
2549         ;
2550
2551 while_or_until
2552         : WHILE { $$ = DoOptions.WHILE; }
2553         | UNTIL { $$ = DoOptions.UNTIL; }
2554         ;
2555
2556 while_statement
2557         : WHILE
2558         {
2559                 start_block();
2560                 oob_stack.Push (lexer.Location);
2561         }
2562         boolean_expression end_of_stmt
2563         opt_statement_list
2564         END WHILE
2565         {
2566                 Location l = (Location) oob_stack.Pop ();
2567                 Block b = end_block();
2568                 Expression e = (Expression) $3;
2569                 $$ = new While ((Expression) e, (Statement) b, l);
2570         }
2571         ;
2572         
2573                 
2574 for_statement
2575         : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2576           {
2577                 start_block();
2578           }
2579           opt_statement_list
2580           NEXT opt_identifier 
2581           {
2582                 Block statement = end_block();
2583                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2584                 
2585                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2586                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
2587                                                 for_var, (Expression) $6, lexer.Location);
2588                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2589                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
2590                                  
2591                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
2592                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2593                 
2594                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
2595           }       
2596         ;
2597
2598 opt_step
2599         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
2600         | STEP expression       { $$ = $2; }
2601         ;
2602
2603 selection_statement
2604         : if_statement
2605         | select_statement
2606         ;
2607
2608 if_statement
2609         : if_statement_open opt_then if_statement_rest
2610           {
2611                 $$ = $3;
2612           }
2613         | if_statement_open THEN pre_embedded_statement
2614           {
2615                 Location l = (Location) oob_stack.Pop ();
2616                 tmp_expr = (Expression)expr_stack.Pop(); 
2617                 $$ = new If ((Expression) tmp_expr, end_block(), l);
2618           }
2619         ;
2620
2621 pre_embedded_statement
2622         : embedded_statement 
2623           {
2624                 Statement s = (Statement) $1;
2625
2626                 current_block.AddStatement ((Statement) $1);
2627           } 
2628         ;       
2629         
2630 if_statement_open
2631         : IF boolean_expression 
2632           {
2633                 oob_stack.Push (lexer.Location);
2634                 start_block();
2635                 tmp_expr = (Expression) $2;
2636                 expr_stack.Push(tmp_expr);
2637           }
2638          ;
2639
2640 opt_then
2641         : /* empty */
2642         | THEN
2643         ;
2644         
2645 if_statement_rest
2646         : end_of_stmt
2647           opt_statement_list
2648           END IF
2649           { 
2650                 Location l = (Location) oob_stack.Pop ();
2651                 Expression expr = (Expression)expr_stack.Pop(); 
2652                 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2653           }       
2654         | end_of_stmt
2655           opt_statement_list
2656           ELSE end_of_stmt 
2657           { 
2658                 Block bl = end_block(); 
2659                 tmp_blocks.Push(bl); 
2660                 start_block();
2661           }
2662           opt_statement_list
2663           END IF        
2664           {
2665                 Location l = (Location) oob_stack.Pop ();
2666                 tmp_expr = (Expression)expr_stack.Pop(); 
2667                 tmp_block = (Block) tmp_blocks.Pop(); 
2668                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2669           }     
2670         | end_of_stmt
2671           opt_statement_list 
2672           ELSEIF boolean_expression opt_then 
2673           { 
2674                 tmp_expr = (Expression) $4;                                                  
2675                 expr_stack.Push(tmp_expr);                                                 
2676                 tmp_block = end_block();
2677                 tmp_blocks.Push(tmp_block);
2678                 start_block();
2679           }
2680           else_if_statement_rest 
2681           {
2682                 Statement stmt = (Statement) statement_stack.Pop();
2683                 Block bl = (Block) tmp_blocks.Pop();  
2684                 Expression expr =  (Expression)expr_stack.Pop();  
2685                 Location l = (Location) oob_stack.Pop ();
2686                 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l); 
2687           }
2688         ;
2689         
2690         
2691 else_if_statement_rest
2692         : end_of_stmt
2693           opt_statement_list 
2694           END IF
2695           { 
2696                 Location l = (Location) oob_stack.Pop ();
2697                 oob_stack.Push (l);
2698                 Expression expr = (Expression)expr_stack.Pop(); 
2699                 Statement stmt = (Statement) new If ((Expression) expr, (Statement)  end_block(), l);
2700                 statement_stack.Push(stmt);
2701           }
2702         | end_of_stmt
2703           opt_statement_list
2704           ELSE end_of_stmt 
2705           { 
2706                 Block bl = end_block();
2707                 tmp_blocks.Push(bl);
2708                 start_block();
2709           }
2710           opt_statement_list
2711           END IF        
2712           {
2713                 Location l = (Location) oob_stack.Pop ();
2714                 oob_stack.Push (l);
2715                 Expression expr = (Expression)expr_stack.Pop(); 
2716                 Block bl = (Block)tmp_blocks.Pop(); 
2717                 Statement stmt = (Statement) new If ((Expression) expr,  (Statement) bl , (Statement)  end_block(), l);
2718                 statement_stack.Push(stmt);
2719           }     
2720         | end_of_stmt
2721           opt_statement_list 
2722           ELSEIF boolean_expression opt_then 
2723           { 
2724                 expr_stack.Push((Expression) $4);                                                 
2725                 Block bl = end_block();
2726                 tmp_blocks.Push(bl);
2727                 start_block();
2728           }
2729           else_if_statement_rest 
2730           {
2731                 Location l = (Location) oob_stack.Pop ();
2732                 oob_stack.Push (l);
2733                 Statement tmp_stmt = (Statement)statement_stack.Pop();
2734                 Block bl = (Block) tmp_blocks.Pop();  
2735                 Expression expr =  (Expression)expr_stack.Pop();  
2736                 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
2737                 statement_stack.Push(stmt);
2738           }          
2739         ;
2740         
2741 select_statement
2742         : SELECT opt_case expression end_of_stmt
2743           { 
2744                 oob_stack.Push (lexer.Location);
2745                 switch_stack.Push (current_block);
2746           }     
2747           opt_case_sections
2748           END SELECT 
2749           {
2750                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2751                 current_block = (Block) switch_stack.Pop ();
2752           }       
2753         ;
2754
2755 opt_case_sections
2756         : /* empty */   { $$ = null; }
2757         | case_sections { $$ = $1; }
2758         ;
2759         
2760 case_sections
2761         : case_sections case_section
2762           {
2763                 ArrayList sections = (ArrayList) $1;
2764
2765                 sections.Add ($2);
2766                 $$ = sections;
2767           }
2768         | case_section
2769           {
2770                 ArrayList sections = new ArrayList ();
2771
2772                 sections.Add ($1);
2773                 $$ = sections;
2774           }
2775         ;
2776
2777 ends 
2778         : end_of_stmt
2779         | ends end_of_stmt
2780         ;
2781         
2782
2783 case_section
2784         : CASE case_clauses ends
2785           { 
2786                 start_block();
2787           }
2788           opt_statement_list
2789           {
2790                 //Block topmost = current_block;
2791                 Block topmost = end_block();
2792                 
2793                 while (topmost.Implicit)
2794                         topmost = topmost.Parent;
2795                         
2796                 // FIXME: This is a horrible hack which MUST go                 
2797                 topmost.statements.Add (new Break (lexer.Location));
2798                 $$ = new SwitchSection ((ArrayList) $2, topmost);
2799           }
2800           | CASE ELSE ends
2801             /* FIXME: we should somehow flag an error 
2802                (BC30321 'Case' cannot follow a 'Case Else' 
2803                in the same 'Select' statement.) 
2804                if Case Else is not the last of the Case clauses
2805             */
2806           { 
2807                 start_block();
2808           }     
2809           opt_statement_list
2810           { 
2811                 //Block topmost = current_block;
2812                 Block topmost = end_block();
2813
2814                 while (topmost.Implicit)
2815                         topmost = topmost.Parent;
2816                         
2817                 // FIXME: This is a horrible hack which MUST go                 
2818                 topmost.statements.Add (new Break (lexer.Location));
2819                 
2820                 ArrayList a = new ArrayList();
2821                 a.Add (new SwitchLabel (null, lexer.Location));                 
2822                 $$ = new SwitchSection ((ArrayList) a, topmost);                
2823           }
2824         ;         
2825         
2826 case_clauses
2827         : case_clause
2828           {
2829                 ArrayList labels = new ArrayList ();
2830
2831                 labels.Add ($1);
2832                 $$ = labels;
2833           }     
2834         | case_clauses COMMA case_clause
2835           {
2836                 ArrayList labels = (ArrayList) ($1);
2837                 labels.Add ($2);
2838
2839                 $$ = labels;
2840           }     
2841         ;
2842         
2843 case_clause
2844         : opt_is comparison_operator expression
2845         | expression
2846           {
2847                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2848           }
2849         ;
2850         
2851 opt_is 
2852         : /* empty */
2853         | IS
2854         ;
2855
2856 comparison_operator
2857         : OP_LT
2858         | OP_GT
2859         | OP_LE
2860         | OP_NE
2861         /*| OP_EQ */
2862         ;
2863
2864 opt_case
2865         : /* empty */
2866         | CASE
2867         ;
2868
2869 expression_statement
2870         : statement_expression 
2871           {
2872                  $$ = $1; 
2873           }
2874         ;
2875
2876
2877 statement_expression
2878         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2879         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2880         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2881         ;
2882
2883 object_creation_expression
2884         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2885           {
2886                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2887           }
2888         | NEW type
2889           {
2890                 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
2891           }
2892         ;
2893         
2894 array_creation_expression
2895         : object_creation_expression array_initializer
2896           {
2897                 New n = (New) $1;
2898                 ArrayList dims = new ArrayList();
2899                 
2900                 if (n.Arguments != null) {
2901                         foreach (Argument a in n.Arguments) {
2902                                 dims.Add (a.Expr);
2903                         }
2904                 }
2905                         
2906                 Expression atype = n.RequestedType;
2907
2908                 ArrayList init = (ArrayList) $2;
2909                 if (init.Count == 0)
2910                         init = null;
2911         
2912                 if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
2913                         VariableDeclaration.VBFixIndexList (ref dims);
2914                         $$ = new ArrayCreation (atype, dims, "", init, lexer.Location); 
2915                 }
2916                 else
2917                 {
2918                         string rank = VariableDeclaration.BuildRank (dims);
2919                         $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location); 
2920                 }
2921                 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
2922           }
2923         ;       
2924
2925 delegate_creation_expression
2926         : NEW type OPEN_PARENS ADDRESSOF expression CLOSE_PARENS
2927           {
2928             ArrayList args = new ArrayList();
2929                 Argument arg = new Argument ((Expression) $5, Argument.AType.Expression);
2930                 args.Add (arg);
2931           
2932                 New n = new New ((Expression) $2, (ArrayList) args, lexer.Location);
2933                 $$ = n;
2934           }
2935         ;
2936
2937 new_expression
2938         : object_creation_expression
2939         | array_creation_expression
2940         | delegate_creation_expression
2941         ;
2942
2943 declaration_statement
2944         : local_variable_declaration 
2945           {
2946                 if ($1 != null){
2947                         DictionaryEntry de = (DictionaryEntry) $1;
2948
2949                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2950                 }
2951           }
2952         | local_constant_declaration 
2953           {
2954                 if ($1 != null){
2955                         DictionaryEntry de = (DictionaryEntry) $1;
2956
2957                         $$ = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value);
2958                 }
2959           }
2960         ;        
2961         
2962 local_variable_declaration
2963         : DIM variable_declarators
2964           {
2965                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
2966           }
2967         ;
2968
2969         
2970 local_constant_declaration
2971         : CONST constant_declarators
2972           {
2973                 if ($2 != null)
2974                         $$ = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), $2);
2975                 else
2976                         $$ = null;
2977           }
2978         ;        
2979         
2980 constant_declarators
2981         : constant_declarator 
2982           {
2983                 ArrayList decl = new ArrayList ();
2984                 if ($1 != null) 
2985                         decl.Add ($1);
2986                         
2987                 $$ = decl;
2988           }
2989         | constant_declarators COMMA constant_declarator
2990           {
2991                 ArrayList decls = (ArrayList) $1;
2992                 if ($3 != null)
2993                         decls.Add ($3);
2994
2995                 $$ = $1;
2996           }
2997         ;
2998
2999 constant_declarator
3000         : variable_name opt_type_decl opt_variable_initializer
3001           {
3002                 VarName vname = (VarName) $1;
3003                 string varname = (string) vname.Name;
3004                 current_rank_specifiers = (ArrayList) vname.Rank;
3005                 object varinit = $3;
3006                 ArrayList a_dims = null;
3007
3008                 if (varinit == null)
3009                         Report.Error (
3010                                 30438, lexer.Location, "Constant should have a value"
3011                                 );
3012
3013                 if (vname.Type != null && $2 != null)
3014                         Report.Error (
3015                                 30302, lexer.Location, 
3016                                 "Type character cannot be used with explicit type declaration" );
3017
3018                 Expression vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3019
3020                 if (current_rank_specifiers != null) 
3021                 {
3022                         Report.Error (30424, lexer.Location, "Constant doesn't support array");
3023                         $$ = null;
3024                 }
3025                 else
3026                         $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
3027           }
3028         ;               
3029
3030 variable_declarators
3031         : variable_declarator 
3032           {
3033                 ArrayList decl = new ArrayList ();
3034                 decl.AddRange ((ArrayList) $1);
3035                 $$ = decl;
3036           }
3037         | variable_declarators COMMA variable_declarator
3038           {
3039                 ArrayList decls = (ArrayList) $1;
3040                 decls.AddRange ((ArrayList) $3);
3041                 $$ = $1;
3042           }
3043         ;
3044
3045 variable_declarator
3046         : variable_names opt_type_decl opt_variable_initializer
3047           {
3048             ArrayList names = (ArrayList) $1;
3049                 object varinit = $3;
3050                 ArrayList VarDeclarations = new ArrayList();
3051                 Expression vartype;
3052                 ArrayList a_dims = null;
3053
3054                 if ((names.Count > 1) && (varinit != null)) 
3055                         Report.Error (
3056                                 30671, lexer.Location, 
3057                                 "Multiple variables with single type can not have " +
3058                                 "a explicit initialization" );
3059
3060                                 
3061                 foreach (VarName vname in names)
3062                 {
3063                         string varname = (string) vname.Name;
3064                         current_rank_specifiers = (ArrayList) vname.Rank;
3065                         a_dims = null;
3066                         varinit = $3;
3067
3068                         if(vname.Type != null && $2 != null)
3069                                 Report.Error (
3070                                         30302, lexer.Location, 
3071                                         "Type character cannot be used with explicit type declaration" );
3072
3073                         // Some checking is required for particularly weird declarations
3074                         // like Dim a As Integer(,)
3075                         if ($2 is Pair) {
3076                                 vartype = (Expression) ((Pair) $2).First;
3077                                 
3078                                 /*if ($3 != null && $3 is ArrayList)
3079                                         Report.Error (205, "End of statement expected.");*/
3080                                         
3081                                 ArrayList args = (ArrayList) ((Pair) $2).Second;
3082                                 if (current_rank_specifiers != null)
3083                                         Report.Error (31087, lexer.Location,
3084                                                  "Array types specified in too many places");   
3085                                 
3086                                 if (VariableDeclaration.IndexesSpecifiedInRank (args))            
3087                                         Report.Error (30638, "Array bounds cannot appear in type specifiers."); 
3088                                 
3089                                 current_rank_specifiers = new ArrayList ();
3090                                 current_rank_specifiers.Add (args);
3091                                 
3092                                 /*string s_vartype = vartype.ToString();                                
3093                                 s_vartype += "[";
3094                                 if (args != null)
3095                                         for (int x = 0; x < args.Count; x++)
3096                                                 s_vartype += ",";
3097                                         
3098                                 s_vartype += "]";       
3099                                 vartype = DecomposeQI(s_vartype, Location.Null);        */
3100                         }
3101                         else
3102                                 vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3103
3104                         // if the variable is an array with explicit bound
3105                         // and having explicit initialization throw exception
3106                         if (current_rank_specifiers != null && varinit != null) 
3107                         {
3108                                 bool broken = false;
3109                                 foreach (ArrayList exprs in current_rank_specifiers)
3110                                 {
3111                                         foreach (Expression expr in exprs)
3112                                         {
3113                                                 if (!((Expression)expr is EmptyExpression ))
3114                                                 {
3115                                                         Report.Error (
3116                                                                 30672, lexer.Location, 
3117                                                                 "Array declared with explicit bound " +
3118                                                                 " can not have explicit initialization");
3119                                                         broken = true;
3120                                                         break;
3121                                                 }
3122                                         }
3123                                         if (broken)
3124                                                 break;
3125                                 }
3126                         }
3127                         
3128                         /*
3129                         Check for a declaration like Dim a(2) or Dim a(2,3)
3130                         If this is the case, we must generate an ArrayCreationExpression
3131                         and, in case, add the initializer after the array has been created.
3132                         */
3133                         if (VariableDeclaration.IsArrayDecl (this)) {   
3134                                 if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) {   
3135                                         a_dims = (ArrayList) current_rank_specifiers;
3136                                         VariableDeclaration.VBFixIndexLists (ref a_dims);
3137                                         varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
3138                                 }
3139                                 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
3140                         }
3141
3142                         if (vartype is New) {
3143                                 if (varinit != null) {
3144                                         Report.Error (30205, lexer.Location, "End of statement expected");
3145                                         $$ = null;
3146                                 }
3147                                 else
3148                                 {
3149                                         varinit = vartype;
3150                                         vartype = ((New)vartype).RequestedType;
3151                                 }
3152                         }
3153                         VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null));
3154             }// end of for
3155             $$ = VarDeclarations;
3156           } 
3157         ;
3158
3159 variable_names
3160         : variable_name
3161           {
3162                 ArrayList list = new ArrayList ();
3163                 list.Add ($1);
3164                 $$ = list;
3165           }
3166         | variable_names COMMA variable_name
3167           {
3168                 ArrayList list = (ArrayList) $1;
3169                 list.Add ($3);
3170                 $$ = list;
3171           }
3172         ;
3173         
3174 variable_name
3175         : identifier opt_type_character opt_array_name_modifier
3176           {
3177                 $$ = new VarName ($1, $2, $3);
3178           }
3179         ;
3180
3181 opt_type_spec
3182         : /* empty */   
3183           { 
3184                 $$ = null;              
3185           }
3186         | AS type       
3187           { 
3188                 $$ = (Expression) $2;
3189           }
3190         ;
3191                 
3192 opt_type_with_ranks
3193         : opt_type_spec 
3194         | AS type rank_specifiers
3195           {
3196                 $$ = TypeManager.system_object_expr; 
3197           }
3198         ;
3199         
3200 opt_type_decl
3201         : opt_type_spec
3202           {
3203                 $$ = $1;
3204           }
3205         | AS type OPEN_PARENS /*opt_argument_list*/ opt_dim_separators CLOSE_PARENS
3206           {
3207                 $$ = new Pair ($2, $4);
3208           }
3209         | AS NEW type
3210           {
3211                 New n = new New ((Expression)$3, null, lexer.Location);
3212                 $$ = (Expression) n;
3213           }
3214         | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS 
3215           {
3216                 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
3217                 $$ = (Expression) n;
3218           }
3219         | AS NEW type OPEN_PARENS ADDRESSOF expression CLOSE_PARENS 
3220           {
3221             ArrayList args = new ArrayList();
3222                 Argument arg = new Argument ((Expression) $6, Argument.AType.Expression);
3223                 args.Add (arg);
3224                 
3225                 New n = new New ((Expression)$3, (ArrayList) args, lexer.Location);
3226                 $$ = (Expression) n;
3227           }
3228         ;
3229                 
3230 opt_array_name_modifier
3231         : /* empty */                           { $$ = null; }
3232         | array_type_modifier                   { $$ = $1;   }
3233         ;
3234         
3235 array_type_modifier
3236         : rank_specifiers               { $$ = $1; }
3237         ;
3238         
3239 opt_variable_initializer
3240         : /* empty */                   { $$ = null; }
3241         | ASSIGN variable_initializer   { $$ = $2; }
3242         ;
3243                 
3244 variable_initializer
3245         : expression
3246           {
3247                 $$ = $1;
3248           }
3249         | array_initializer
3250           {
3251                 $$ = $1;
3252           }
3253         
3254         ;       
3255         
3256 array_initializer
3257         : OPEN_BRACE CLOSE_BRACE
3258           {
3259                 ArrayList list = new ArrayList ();
3260                 $$ = list;
3261           }
3262         | OPEN_BRACE variable_initializer_list CLOSE_BRACE
3263           {
3264                 $$ = (ArrayList) $2;
3265           }
3266         ;
3267
3268 variable_initializer_list
3269         : variable_initializer
3270           {
3271                 ArrayList list = new ArrayList ();
3272                 list.Add ($1);
3273                 $$ = list;
3274           }
3275         | variable_initializer_list COMMA variable_initializer
3276           {
3277                 ArrayList list = (ArrayList) $1;
3278                 list.Add ($3);
3279                 $$ = list;
3280           }
3281         ;
3282
3283 opt_rank_specifiers
3284         : /* empty */
3285           {
3286                   // $$ = "";
3287                   $$ = null;
3288           }
3289         | rank_specifiers
3290           {
3291                         $$ = $1;
3292           }
3293         ;      
3294         
3295 rank_specifiers
3296         : rank_specifier
3297           {
3298                   ArrayList rs = new ArrayList();
3299                   rs.Add ($1);
3300                   $$ = rs;
3301           }
3302         | rank_specifiers rank_specifier
3303           {
3304                   ArrayList rs = (ArrayList) $1;
3305                   rs.Add ($2);
3306                   $$ = rs;
3307           }             
3308         ;               
3309         
3310 rank_specifier
3311         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
3312           {
3313                 $$ = $2;
3314           }
3315         ;
3316                 
3317 opt_dim_separators
3318         : /* empty */
3319           {
3320                 ArrayList ds = new ArrayList();
3321                 ds.Add (new EmptyExpression());
3322                 $$ = ds;                
3323           }
3324         | dim_separators
3325           {
3326                 ArrayList ds = (ArrayList) $1;
3327                 ds.Add (new EmptyExpression());
3328                 $$ = ds;        
3329           }     
3330         | dim_specifiers
3331           {
3332                 $$ = $1;
3333           }       
3334         ;
3335
3336 dim_separators
3337         : COMMA
3338           {
3339                 ArrayList ds = new ArrayList();
3340                 ds.Add (new EmptyExpression());
3341                 $$ = ds;
3342           }
3343         | dim_separators COMMA
3344           {
3345                 ArrayList ds = (ArrayList) $1;
3346                 ds.Add (new EmptyExpression());
3347                 $$ = ds;                
3348           }
3349         ;
3350
3351 dim_specifiers
3352         : expression
3353           {
3354                 ArrayList ds = new ArrayList();
3355                 ds.Add ((Expression) $1);
3356                 $$ = ds;
3357           }     
3358         | dim_specifiers COMMA expression
3359           {
3360                 ArrayList ds = (ArrayList) $1;
3361                 ds.Add ((Expression) $3);
3362                 $$ = ds;                
3363           }     
3364         ;
3365         
3366 /* Expressions */
3367 primary_expression
3368         : literal
3369           {
3370                 // 7.5.1: Literals
3371           }
3372
3373         | qualified_identifier
3374           {
3375                 string name = (string) $1;
3376
3377                 $$ = DecomposeQI (name, lexer.Location);
3378           }
3379         | parenthesized_expression
3380         | member_access
3381         | invocation_expression
3382         //| element_access
3383         | this_access
3384         | base_access
3385         | new_expression
3386         | cast_expression
3387         ;
3388
3389 literal
3390         : boolean_literal
3391         | integer_literal
3392         | real_literal
3393         | LITERAL_DATE                  { $$ = new DateLiteral ((DateTime)lexer.Value); }
3394         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
3395         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
3396         | NOTHING                               { $$ = NullLiteral.Null; }
3397         ;
3398
3399 real_literal
3400         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
3401         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
3402         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3403         ;
3404
3405 integer_literal
3406         : LITERAL_INTEGER       {
3407                 object v = lexer.Value;
3408
3409                 if (v is int)
3410                         $$ = new IntLiteral ((Int32)v); 
3411                 else if (v is short)
3412                         $$ = new ShortLiteral ((Int16)v);
3413                 else if (v is long)
3414                         $$ = new LongLiteral ((Int64)v);
3415                 else
3416                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
3417                         
3418           }
3419         ;
3420
3421 boolean_literal
3422         : TRUE                  { $$ = new BoolLiteral (true); }
3423         | FALSE                 { $$ = new BoolLiteral (false); }
3424         ;
3425
3426 parenthesized_expression
3427         : OPEN_PARENS expression CLOSE_PARENS
3428           { $$ = $2; }
3429         ;
3430
3431 member_access
3432         : primary_expression DOT identifier
3433           {
3434                 if ($1 != null) {
3435                         string id_name = (string)$3;
3436                         if (id_name.ToUpper() == "NEW")
3437                                 id_name = ".ctor";
3438                         $$ = new MemberAccess ((Expression) $1, id_name, lexer.Location);
3439                 }
3440                 else
3441                 {
3442                         if (with_stack.Count > 0) {
3443                                 Expression e = (Expression) with_stack.Peek();
3444                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3445                         }
3446                         else
3447                         {
3448                                 // OOps
3449                         }
3450                 }
3451           }
3452 /*      | primary_expression DOT NEW
3453           {
3454                 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3455           }       */
3456         | predefined_type DOT identifier
3457           {
3458                 if ($1 != null)
3459                         $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3460                 else
3461                 {
3462                         if (with_stack.Count > 0) {
3463                                 Expression e = (Expression) with_stack.Peek();
3464                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3465                         }
3466                         else
3467                         {
3468                                 // OOps
3469                         }
3470                 }
3471           }
3472         ;
3473
3474 predefined_type
3475         : builtin_types
3476         ;
3477
3478 invocation_expression
3479         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3480           {
3481                 if ($1 == null) {
3482                         Location l = lexer.Location;
3483                         Report.Error (1, l, "THIS IS CRAZY");
3484                 }
3485                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3486 //              Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3487           } 
3488         ;
3489         
3490 base_access
3491         : MYBASE DOT IDENTIFIER
3492           {
3493                 string id_name = (string) $3;
3494                 if (id_name.ToUpper() == "NEW")
3495                         id_name = "New";
3496                 $$ = new BaseAccess (id_name, lexer.Location);
3497           }
3498 /*      | MYBASE DOT NEW
3499           {
3500                 $$ = new BaseAccess ("New", lexer.Location);
3501           }*/
3502         ;       
3503
3504 opt_argument_list
3505         : argument_list
3506           { 
3507                 /*
3508                    The 'argument' rule returns an 'empty' argument
3509                    of type NoArg (used for default arguments in invocations)
3510                    if no arguments are actually passed.
3511
3512                    If there is only one argument and it is o type NoArg,
3513                    we return a null (empty) list
3514                 */
3515                 ArrayList args = (ArrayList) $1;
3516                 if (args.Count == 1 &&
3517                     ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3518                         $$ = null;
3519                 else
3520                         $$ = $1;
3521           }
3522         ;
3523
3524 argument_list
3525         : argument
3526           {
3527                 ArrayList list = new ArrayList ();
3528                 list.Add ($1);
3529                 $$ = list;
3530           }
3531         | argument_list COMMA argument
3532           {
3533                 ArrayList list = (ArrayList) $1;
3534                 list.Add ($3);
3535                 $$ = list;
3536           }
3537         ;
3538
3539 argument
3540         : expression
3541           {
3542                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3543           }
3544         | BYREF variable_reference
3545           {
3546                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3547           }
3548         | /* empty */
3549           {
3550                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3551           }
3552         /*| ADDRESSOF expression
3553           {
3554                 $$ = new Argument ((Expression) $2, Argument.AType.AddressOf);
3555           }*/
3556         ;
3557
3558 variable_reference
3559         : expression {/* note ("section 5.4"); */  $$ = $1;  }
3560         ;
3561
3562 negation_expression
3563         : NOT expression 
3564           {
3565                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3566           }
3567         ;
3568                 
3569 expression
3570         : conditional_expression { $$ = $1; }
3571         | negation_expression
3572         /*| assignment_expression*/
3573         ;
3574
3575 opt_expression
3576         : /* empty */
3577         | expression
3578         ;
3579                 
3580 this_access
3581         : ME
3582           {
3583                 $$ = new This (current_block, lexer.Location);
3584           }
3585         | MYCLASS
3586           {
3587                 // FIXME: This is actually somewhat different from Me
3588                 // because it is for accessing static (classifier) methods/properties/fields
3589                 $$ = new This (current_block, lexer.Location);
3590           }
3591         ;
3592
3593 unary_expression
3594         : primary_expression
3595         /*| NOT prefixed_unary_expression
3596           {
3597                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3598           }
3599         | cast_expression */
3600         ;
3601         
3602 cast_expression
3603         : cast_operator OPEN_PARENS expression CLOSE_PARENS
3604           {
3605                   $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3606           }     
3607         | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3608           {
3609                   $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3610           }                       
3611         ;
3612         
3613 cast_operator
3614         : CBOOL         { $$ = TypeManager.system_boolean_expr;         }
3615         | CBYTE         { $$ = TypeManager.system_byte_expr;            }
3616         | CCHAR         { $$ = TypeManager.system_char_expr;            }
3617         | CDATE         { $$ = TypeManager.system_date_expr;            }
3618         | CDBL          { $$ = TypeManager.system_double_expr;          }
3619         | CDEC          { $$ = TypeManager.system_decimal_expr;         }
3620         | CINT          { $$ = TypeManager.system_int32_expr;           }
3621         | CLNG          { $$ = TypeManager.system_int64_expr;           }
3622         | COBJ          { $$ = TypeManager.system_object_expr;          }
3623         | CSHORT        { $$ = TypeManager.system_int16_expr;           }
3624         | CSNG          { $$ = TypeManager.system_single_expr;          }
3625         | CSTR          { $$ = TypeManager.system_string_expr;  }
3626         ;
3627         
3628         //
3629         // The idea to split this out is from Rhys' grammar
3630         // to solve the problem with casts.
3631         //
3632 prefixed_unary_expression
3633         : unary_expression
3634         | PLUS prefixed_unary_expression
3635           {
3636                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3637           }
3638         | MINUS prefixed_unary_expression
3639           {
3640                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3641           }
3642         ;
3643
3644 multiplicative_expression
3645         : prefixed_unary_expression
3646         | multiplicative_expression STAR prefixed_unary_expression
3647           {
3648                 $$ = new Binary (Binary.Operator.Multiply,
3649                                  (Expression) $1, (Expression) $3, lexer.Location);
3650           }
3651         | multiplicative_expression DIV prefixed_unary_expression
3652           {
3653                 $$ = new Binary (Binary.Operator.Division,
3654                                  (Expression) $1, (Expression) $3, lexer.Location);
3655           }
3656         | multiplicative_expression OP_IDIV prefixed_unary_expression
3657           {
3658                 $$ = new Binary (Binary.Operator.Division,
3659                                  (Expression) $1, (Expression) $3, lexer.Location);
3660           }       
3661         | multiplicative_expression MOD prefixed_unary_expression
3662           {
3663                 $$ = new Binary (Binary.Operator.Modulus,
3664                                  (Expression) $1, (Expression) $3, lexer.Location);
3665           }
3666         ;
3667
3668 additive_expression
3669         : multiplicative_expression
3670         | additive_expression PLUS multiplicative_expression
3671           {
3672                 $$ = new Binary (Binary.Operator.Addition,
3673                                  (Expression) $1, (Expression) $3, lexer.Location);
3674           }
3675         | additive_expression MINUS multiplicative_expression
3676           {
3677                 $$ = new Binary (Binary.Operator.Subtraction,
3678                                  (Expression) $1, (Expression) $3, lexer.Location);
3679           }
3680         | additive_expression OP_CONCAT multiplicative_expression
3681           {
3682                 // FIXME: This should only work for String expressions
3683                 // We probably need to use something from the runtime
3684                 $$ = new Binary (Binary.Operator.Addition,
3685                                  (Expression) $1, (Expression) $3, lexer.Location);
3686           }       
3687         ;
3688
3689 relational_expression
3690         : additive_expression
3691         | relational_expression OP_LT additive_expression
3692           {
3693                 $$ = new Binary (Binary.Operator.LessThan,
3694                                  (Expression) $1, (Expression) $3, lexer.Location);
3695           }
3696         | relational_expression OP_GT additive_expression
3697           {
3698                 $$ = new Binary (Binary.Operator.GreaterThan,
3699                                  (Expression) $1, (Expression) $3, lexer.Location);
3700           }
3701         | relational_expression OP_LE additive_expression
3702           {
3703                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
3704                                  (Expression) $1, (Expression) $3, lexer.Location);
3705           }
3706         | relational_expression OP_GE additive_expression
3707           {
3708                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
3709                                  (Expression) $1, (Expression) $3, lexer.Location);
3710           }
3711         | relational_expression IS unary_expression
3712           {
3713                 $$ = new Binary (Binary.Operator.Equality,
3714                         (Expression) $1, (Expression) $3, lexer.Location);
3715           }
3716         | relational_expression AS type_name
3717           {
3718                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
3719           }
3720         ;
3721
3722 equality_expression
3723         : relational_expression
3724         | equality_expression ASSIGN relational_expression
3725           {
3726                 $$ = new Binary (Binary.Operator.Equality,
3727                                  (Expression) $1, (Expression) $3, lexer.Location);
3728           }
3729         | equality_expression OP_NE relational_expression
3730           {
3731                 $$ = new Binary (Binary.Operator.Inequality, 
3732                                  (Expression) $1, (Expression) $3, lexer.Location);
3733           }       
3734         ;
3735
3736 and_expression
3737         : equality_expression
3738         | and_expression AND equality_expression
3739           {
3740                 $$ = new Binary (Binary.Operator.BitwiseAnd,
3741                                  (Expression) $1, (Expression) $3, lexer.Location);
3742           }
3743         ;
3744
3745 exclusive_or_expression
3746         : and_expression
3747         | exclusive_or_expression OP_XOR and_expression
3748           {
3749                 $$ = new Binary (Binary.Operator.ExclusiveOr,
3750                                  (Expression) $1, (Expression) $3, lexer.Location);
3751           }
3752         ;
3753
3754 conditional_and_expression
3755         : exclusive_or_expression
3756         | conditional_and_expression AND exclusive_or_expression
3757           {
3758                 $$ = new Binary (Binary.Operator.LogicalAnd,
3759                                  (Expression) $1, (Expression) $3, lexer.Location);
3760           }
3761         | conditional_and_expression ANDALSO exclusive_or_expression
3762           {     // FIXME: this is likely to be broken
3763                 $$ = new Binary (Binary.Operator.LogicalAnd,
3764                                  (Expression) $1, (Expression) $3, lexer.Location);
3765           }
3766         ;
3767
3768 conditional_or_expression
3769         : conditional_and_expression
3770         | conditional_or_expression OR conditional_and_expression
3771           {
3772                 $$ = new Binary (Binary.Operator.LogicalOr,
3773                                  (Expression) $1, (Expression) $3, lexer.Location);
3774           }
3775         | conditional_or_expression ORELSE conditional_and_expression
3776           {     // FIXME: this is likely to be broken
3777                 $$ = new Binary (Binary.Operator.LogicalOr,
3778                                  (Expression) $1, (Expression) $3, lexer.Location);
3779           }
3780         ;
3781
3782 conditional_expression
3783         : conditional_or_expression
3784         ;
3785
3786 assignment_expression
3787         : prefixed_unary_expression ASSIGN expression
3788           { 
3789                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3790           }
3791         | prefixed_unary_expression ASSIGN ADDRESSOF expression
3792           { 
3793             ArrayList args = new ArrayList();
3794                 Argument arg = new Argument ((Expression) $4, Argument.AType.Expression);
3795                 args.Add (arg);
3796                 
3797                 New n = new New ((Expression) $1, (ArrayList) args, lexer.Location);
3798                 n.isDelegate = true;
3799                 $$ = new Assign ((Expression) $1, (Expression) n, lexer.Location);
3800           }
3801         | prefixed_unary_expression OP_MULT_ASSIGN expression
3802           {
3803                 Location l = lexer.Location;
3804
3805                 $$ = new CompoundAssign (
3806                         Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
3807           }
3808         | prefixed_unary_expression OP_DIV_ASSIGN expression
3809           {
3810                 Location l = lexer.Location;
3811
3812                 $$ = new CompoundAssign (
3813                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3814           }
3815         | prefixed_unary_expression OP_IDIV_ASSIGN expression
3816           {
3817                 Location l = lexer.Location;
3818
3819                 $$ = new CompoundAssign (
3820                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3821           }       
3822         | prefixed_unary_expression OP_ADD_ASSIGN expression
3823           {
3824                 Location l = lexer.Location;
3825
3826                 $$ = new CompoundAssign (
3827                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3828           }
3829         | prefixed_unary_expression OP_SUB_ASSIGN expression
3830           {
3831                 Location l = lexer.Location;
3832
3833                 $$ = new CompoundAssign (
3834                         Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
3835           }
3836         | prefixed_unary_expression OP_CONCAT_ASSIGN expression
3837           {
3838                 Location l = lexer.Location;
3839
3840                 $$ = new CompoundAssign (
3841                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3842           }               
3843         ;
3844
3845 /*constant_expression
3846         : expression
3847         ;
3848 */
3849
3850 boolean_expression
3851         : expression
3852         ;
3853
3854 type
3855         : type_name {   /* class_type */
3856                 /*
3857                    This does interfaces, delegates, struct_types, class_types,
3858                    parent classes, and more! 4.2
3859                  */
3860                 $$ = DecomposeQI ((string) $1, lexer.Location); 
3861           }
3862         | builtin_types 
3863         /*| array_type 
3864          | pointer_type */
3865         ;
3866
3867 type_list
3868         : type
3869           {
3870                 ArrayList types = new ArrayList ();
3871
3872                 types.Add ($1);
3873                 $$ = types;
3874           }
3875         | type_list COMMA type
3876           {
3877                 ArrayList types = (ArrayList) $1;
3878
3879                 types.Add ($3);
3880                 $$ = types;
3881           }
3882         ;
3883
3884 type_name
3885         : namespace_or_type_name
3886         ;
3887         
3888 namespace_or_type_name
3889         : qualified_identifier
3890         ;
3891
3892 /* Built-in / Integral types */
3893 builtin_types
3894         : OBJECT        { $$ = TypeManager.system_object_expr; }
3895         | STRING        { $$ = TypeManager.system_string_expr; }
3896         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
3897         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
3898         | SINGLE        { $$ = TypeManager.system_single_expr; }
3899         | DOUBLE        { $$ = TypeManager.system_double_expr; }
3900         | DATE          { $$ = TypeManager.system_date_expr; }
3901         | integral_type
3902         ;
3903
3904 integral_type
3905         :
3906         | BYTE          { $$ = TypeManager.system_byte_expr; }
3907         | SHORT         { $$ = TypeManager.system_int16_expr; }
3908         | LONG          { $$ = TypeManager.system_int64_expr; }
3909         | INTEGER       { $$ = TypeManager.system_int32_expr; }
3910         | CHAR          { $$ = TypeManager.system_char_expr; }
3911         ;
3912
3913 interface_type
3914         : type_name
3915         ;
3916         
3917 end_of_stmt
3918         : EOL
3919         | COLON
3920         ;       
3921 %%
3922
3923
3924 Tokenizer lexer;
3925
3926 public Tokenizer Lexer {
3927         get {
3928                 return lexer;
3929         }
3930 }                  
3931
3932 public static Expression DecomposeQI (string name, Location loc)
3933 {
3934         Expression o;
3935
3936         if (name.IndexOf ('.') == -1){
3937                 return new SimpleName (name, loc);
3938         } else {
3939                 int pos = name.LastIndexOf (".");
3940                 string left = name.Substring (0, pos);
3941                 string right = name.Substring (pos + 1);
3942
3943                 o = DecomposeQI (left, loc);
3944
3945                 return new MemberAccess (o, right, loc);
3946         }
3947 }
3948
3949 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3950 {
3951         Block implicit_block;
3952         ArrayList inits = null;
3953
3954         //
3955         // We use the `Used' property to check whether statements
3956         // have been added to the current block.  If so, we need
3957         // to create another block to contain the new declaration
3958         // otherwise, as an optimization, we use the same block to
3959         // add the declaration.
3960         //
3961         // FIXME: A further optimization is to check if the statements
3962         // that were added were added as part of the initialization
3963         // below.  In which case, no other statements have been executed
3964         // and we might be able to reduce the number of blocks for
3965         // situations like this:
3966         //
3967         // int j = 1;  int k = j + 1;
3968         //
3969         
3970         VariableDeclaration.FixupTypes (variable_declarators);
3971         
3972         if (current_block.Used) {
3973                 implicit_block = new Block (current_block, true, loc, Location.Null);
3974                 implicit_block.AddChildVariableNames (current_block);
3975         } else
3976                 implicit_block = current_block;
3977
3978         foreach (VariableDeclaration decl in variable_declarators){
3979                 Expression type = decl.type;
3980                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3981                         if (decl.expression_or_array_initializer != null){
3982                                 if (inits == null)
3983                                         inits = new ArrayList ();
3984                                 inits.Add (decl);
3985                         }
3986                 }
3987         }
3988
3989         if (inits == null)
3990                 return implicit_block;
3991
3992         foreach (VariableDeclaration decl in inits){
3993                 Assign assign;
3994                 Expression expr;
3995                 Expression type = decl.type;
3996                 
3997                 if ((decl.expression_or_array_initializer is Expression) || 
3998                     (decl.expression_or_array_initializer is New)) {
3999                         expr = (Expression) decl.expression_or_array_initializer;
4000                 } else {
4001                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
4002                         
4003                         expr = new ArrayCreation (type, "", init, decl.Location);
4004                 }
4005
4006                 LocalVariableReference var;
4007                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
4008
4009                 assign = new Assign (var, expr, decl.Location);
4010
4011                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
4012         }
4013         
4014         return implicit_block;
4015 }
4016
4017 Block declare_local_constant (Expression dummy_type, ArrayList variable_declarators)
4018 {
4019         Block implicit_block;
4020         VariableDeclaration.FixupTypes (variable_declarators);
4021
4022         if (current_block.Used)
4023                 implicit_block = new Block (current_block, true);
4024         else
4025                 implicit_block = current_block;
4026
4027         foreach (VariableDeclaration decl in variable_declarators){
4028                 Expression type = decl.type;
4029                 implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
4030                                           current_local_parameters, decl.Location);
4031         }
4032         
4033         return implicit_block;
4034 }
4035
4036 struct VarName {
4037                 public object Name;
4038                 public object Type;
4039                 public object Rank;
4040                                                                                 
4041                 public VarName (object n, object t, object r)
4042                 {
4043                         Name = n;
4044                         Type = t;
4045                         Rank = r;
4046                 }
4047         }
4048
4049
4050 // <summary>
4051 //   A class used to pass around variable declarations and constants
4052 // </summary>
4053 public class VariableDeclaration {
4054         public string identifier;
4055         public object expression_or_array_initializer;
4056         public Location Location;
4057         public Attributes OptAttributes;
4058         public Expression type;
4059         public ArrayList dims;
4060                 
4061         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
4062         {
4063                 this.identifier = id;
4064                 this.expression_or_array_initializer = eoai;
4065                 this.Location = l;
4066                 this.OptAttributes = opt_attrs;
4067                 this.type = t;
4068                 this.dims = null;
4069         }       
4070
4071         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
4072         {
4073         }
4074         
4075         public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
4076         {
4077         }       
4078         
4079         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
4080                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
4081         {
4082         }       
4083         
4084         public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
4085         {       
4086                 // FIXME : This is broken: only the first rank is parsed
4087                 return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
4088         }
4089         
4090         public static void FixupTypes (ArrayList vars)
4091         {
4092                 int varcount =  vars.Count;
4093                 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
4094                         
4095                 if (last_var.type == null)
4096                         last_var.type = TypeManager.system_object_expr;
4097                         
4098                 Expression cur_type = last_var.type;
4099                 int n = varcount - 1;
4100                 
4101                 while (n >= 0) {
4102                         VariableDeclaration var = (VariableDeclaration) vars[n--];
4103                         if (var.type == null)
4104                                 var.type = cur_type;
4105                         else
4106                                 cur_type = var.type;
4107                 }
4108         }
4109         
4110         public static bool IndexesSpecifiedInRank (ArrayList IndexList)
4111         {
4112                 bool res = false;
4113                 
4114                 if (IndexList != null) {
4115                         foreach (Expression e in IndexList)
4116                                 if (!(e is EmptyExpression)) {
4117                                         res = true;
4118                                         break;
4119                                 }       
4120                 }
4121                 return (res);
4122         }       
4123         
4124         
4125         public static bool IndexesSpecified (ArrayList ranks)
4126         {
4127                 bool res = false;
4128                 
4129                 if (ranks != null) {
4130                         foreach (ArrayList IndexList in ranks) {
4131                                 if (IndexesSpecifiedInRank (IndexList)) {
4132                                         res = true;
4133                                         break;
4134                                 }       
4135                         }       
4136                 }
4137                 return (res);
4138         }
4139         
4140         public static string StripDims (string varname, ref string d)
4141         {
4142                 string res = varname;
4143                 string dres = "";
4144                 
4145                 if (varname.IndexOf("[") >= 0) {
4146                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
4147                         res = varname.Substring(0, varname.IndexOf("["));
4148                 }
4149                 d = dres;
4150                 return (res);
4151         }       
4152         
4153         public static string StripDims (string varname)
4154         {
4155                 string dres = "";
4156                 
4157                 return (StripDims(varname, ref dres));
4158         }       
4159         
4160         public static string StripIndexesFromDims (string dims)
4161         {
4162                 StringBuilder sb = new StringBuilder();
4163
4164                 foreach (char c in dims) 
4165                         if (c == ',' || c == ']' || c == '[')
4166                                 sb.Append (c);
4167                                 
4168                 return sb.ToString();                           
4169         }
4170         
4171         public static string BuildRank (ArrayList rank)
4172         {
4173                 string res = "";
4174
4175                 res += "[";
4176                 for (int x = 0; x < (rank.Count -1 ); x++)
4177                         res += ",";
4178                         
4179                 res += "]";
4180                 return res;
4181         }
4182                 
4183         public static string BuildRanks (Parser t)
4184         {
4185                 string res = "";
4186
4187                 foreach (ArrayList rank in t.current_rank_specifiers)
4188                         res += BuildRank (rank);
4189
4190                 return res;
4191         }       
4192         
4193         public static void VBFixIndexList (ref ArrayList IndexList)
4194         {
4195                 if (IndexList != null) {
4196                         for (int x = 0; x < IndexList.Count; x++) {
4197                                 Expression e = (Expression) IndexList[x];
4198                                 if (!(e is EmptyExpression)) {
4199                                         IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
4200                                 }
4201                         }
4202                 }
4203         }               
4204         
4205         public static bool IsArrayDecl (Parser t)
4206         {
4207                 // return (varname.IndexOf("[") >= 0);
4208                 return (t.current_rank_specifiers != null);
4209         }                       
4210         
4211         public static void VBFixIndexLists (ref ArrayList ranks)
4212         {       
4213                 if (ranks != null) {
4214                         for (int x = 0; x < ranks.Count; x++) {
4215                                 ArrayList IndexList = (ArrayList) ranks[x];
4216                                 VBFixIndexList (ref IndexList);
4217                         }       
4218                 }       
4219         }
4220                 
4221         public static void FixupArrayTypes (ArrayList vars)
4222         {
4223                 int varcount =  vars.Count;
4224                 string dims;
4225                 
4226                 foreach (VariableDeclaration var in vars) {
4227                         if (var.identifier.EndsWith(",")) {
4228                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
4229                                                                 var.identifier.LastIndexOf(",")) + "]";
4230                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
4231                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
4232                         }
4233                 }
4234         }                               
4235 }
4236
4237
4238 public Property BuildSimpleProperty (Expression p_type, string name, 
4239                                         Field p_fld, int mod_flags,
4240                                         Attributes attrs, Location loc) 
4241 {
4242         Property p;
4243         Block get_block, set_block;
4244         Accessor acc_set, acc_get;
4245         StatementExpression a_set;
4246         Statement a_get;
4247         Parameter [] args;
4248         
4249         // Build SET Block
4250         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
4251         args  = new Parameter [1];
4252         args [0] = implicit_value_parameter;
4253                 
4254         Parameters set_params = new Parameters (args, null, loc);
4255         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
4256                             (Expression) new SimpleName("value", loc), loc), loc);
4257                             
4258         set_block = new Block (current_block, set_params, loc, Location.Null);
4259         set_block.AddStatement ((Statement) a_set);                                         
4260         acc_set = new Accessor (set_block, attrs);
4261         
4262         // Build GET Block
4263         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
4264         get_block = new Block (current_block, null, loc, Location.Null);
4265         get_block.AddStatement ((Statement) a_get);                                         
4266         acc_get = new Accessor (get_block, attrs);
4267                 
4268         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
4269         
4270         return (p);
4271 }
4272         
4273 void start_block () 
4274 {
4275         current_block = new Block (current_block, current_local_parameters,
4276                            lexer.Location, Location.Null);
4277
4278
4279 Block end_block ()
4280
4281         Block res;
4282         
4283         while (current_block.Implicit)
4284                 current_block = current_block.Parent;
4285
4286         res = current_block;
4287
4288         current_block.SetEndLocation (lexer.Location);
4289         current_block = current_block.Parent;
4290         
4291         return (res);
4292 }
4293
4294 private void AddHandler (Expression evt_definition, string handler_name)
4295 {
4296         AddHandler (current_block, evt_definition, handler_name);
4297 }
4298
4299 void CheckAttributeTarget (string a)
4300 {
4301         switch (a) {
4302
4303         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
4304                 return;
4305                 
4306         default :
4307                 Location l = lexer.Location;
4308                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
4309                 break;
4310         }
4311 }
4312
4313 private void AddHandler (Block b, Expression evt_id, string handler_name)
4314 {
4315         Location loc = lexer.Location;
4316         string evt_target = evt_id.ToString();
4317         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
4318         Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
4319         b.AddStatement (s);
4320 }
4321
4322 private void RaiseEvent (string evt_name, ArrayList args)
4323 {
4324         Location loc = lexer.Location;
4325         
4326         Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
4327         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); 
4328         current_block.AddStatement (s); 
4329 }
4330
4331 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
4332 {
4333         Location loc = lexer.Location;
4334         string evt_target = evt_definition.ToString();
4335         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
4336         Statement s = (Statement) new RemoveHandler (evt_definition, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
4337         b.AddStatement (s);
4338 }
4339
4340 // <summary>
4341 //  This method is used to get at the complete string representation of
4342 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
4343 //  This is necessary because local_variable_type admits primary_expression
4344 //  as the type of the variable. So we do some extra checking
4345 // </summary>
4346 string GetQualifiedIdentifier (Expression expr)
4347 {
4348         if (expr is SimpleName)
4349                 return ((SimpleName)expr).Name;
4350         else if (expr is MemberAccess)
4351                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4352         else 
4353                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4354         
4355 }
4356
4357 private void RemoveHandler (Expression evt_definition, string handler_name)
4358 {
4359         RemoveHandler (current_block, evt_definition, handler_name);
4360 }
4361
4362 private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s)
4363 {
4364         ConstructorInitializer ci = null;
4365         
4366         if (s.Count > 0) {
4367                 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4368                         Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4369                         
4370                         if (i.expr is BaseAccess) {
4371                                 BaseAccess ba = (BaseAccess) i.expr;
4372                                 if (ba.member == "New" || ba.member == ".ctor") {
4373                                         ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4374                                         s.RemoveAt(0);
4375                                 }
4376                         }
4377                         if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
4378                                 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location); 
4379                                 s.RemoveAt(0);
4380                         }
4381                 }
4382         }
4383         return ci;
4384 }
4385
4386 void Error_ExpectingTypeName (Location l, Expression expr)
4387 {
4388         if (expr is Invocation){
4389                 Report.Error (1002, l, "; expected");
4390         } else {
4391                 Report.Error (-1, l, "Invalid Type definition");
4392         }
4393 }
4394
4395 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4396         return true;
4397 }
4398
4399 private void ReportError9998()
4400 {
4401         Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4402 }
4403
4404 protected override int parse ()
4405 {
4406         RootContext.InitializeImports(ImportsList);
4407         current_namespace = new Namespace (null, RootContext.RootNamespace);
4408         current_container = RootContext.Tree.Types;
4409         current_container.Namespace = current_namespace;
4410         oob_stack = new Stack ();
4411         switch_stack = new Stack ();
4412         expr_stack = new Stack ();      
4413         tmp_blocks = new Stack(); 
4414         with_stack = new Stack();
4415         statement_stack = new Stack();  
4416
4417         UseExtendedSyntax = name.EndsWith(".mbs");
4418         OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4419         OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4420         OptionCompareBinary = InitialOptionCompareBinary;
4421
4422         lexer = new Tokenizer (input, name, defines);
4423         StringBuilder value = new StringBuilder ();
4424         try {
4425                 if (yacc_verbose_flag)
4426                         yyparse (lexer, new yydebug.yyDebugSimple ());
4427                 else
4428                         yyparse (lexer);
4429         } catch (Exception e) {
4430                 Report.Error (29999, lexer.Location, lexer.location + "\nParsing error in " + lexer.ref_name + "\n" + e.ToString());
4431         }
4432
4433         RootContext.VerifyImports();
4434
4435         return Report.Errors;
4436 }
4437
4438 /* end end end */
4439 }