reduce toods crying
[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 AS type 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                 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (
1860                         current_container,
1861                         (Expression) $8, (int) current_modifiers, MakeName ((string) $3), 
1862                         (Parameters) $5, (Attributes) current_attributes, l);
1863
1864                 del.Namespace = current_namespace;
1865                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1866           }
1867         ;
1868         
1869 opt_evt_handler
1870         : /* empty */
1871           {     $$ = null; }
1872         | HANDLES qualified_identifier
1873           {
1874                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
1875           }
1876         | HANDLES MYBASE DOT qualified_identifier
1877           {
1878                 // FIXME: this is blatantly wrong and crash-prone
1879                 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
1880           }
1881         ;       
1882
1883 opt_empty_parens
1884         : /* empty */
1885         | OPEN_PARENS CLOSE_PARENS
1886         ;       
1887
1888 constructor_declaration
1889         : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1890           {
1891                 current_local_parameters = (Parameters) $4;
1892                 start_block();
1893                 oob_stack.Push (lexer.Location);
1894
1895                 Location l = (Location) oob_stack.Pop ();
1896                 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1897                 $1 = $$;
1898           }
1899           opt_statement_list
1900           { 
1901                 Constructor c = (Constructor) $1;
1902                 c.Block = (Block) end_block();
1903                 c.ModFlags = (int) current_modifiers;
1904                 c.OptAttributes = current_attributes;
1905                 
1906                 c.Initializer = CheckConstructorInitializer (ref c.Block.statements);
1907
1908                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1909                 current_local_parameters = null;
1910           }
1911           END SUB EOL
1912         ;
1913         
1914 opt_formal_parameter_list
1915         : /* empty */                   
1916           { 
1917                 $$ = Parameters.EmptyReadOnlyParameters; 
1918           }
1919         | formal_parameter_list 
1920           { 
1921                 $$ = $1;        
1922                 //Parameter p = ((Parameters) $1).FixedParameters[0];
1923           }
1924         ;
1925         
1926 formal_parameter_list
1927         : fixed_parameters              
1928           { 
1929                 ArrayList pars_list = (ArrayList) $1;
1930
1931                 Parameter [] pars = new Parameter [pars_list.Count];
1932                 pars_list.CopyTo (pars);
1933                 $$ = new Parameters (pars, null, lexer.Location); 
1934           } 
1935         | fixed_parameters COMMA parameter_array
1936           {
1937                 ArrayList pars_list = (ArrayList) $1;
1938
1939                 Parameter [] pars = new Parameter [pars_list.Count];
1940                 pars_list.CopyTo (pars);
1941
1942                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1943           }
1944         | parameter_array 
1945           {
1946                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1947           }
1948         ;
1949
1950 fixed_parameters
1951         : fixed_parameter       
1952           {
1953                 ArrayList pars = new ArrayList ();
1954
1955                 pars.Add ($1);
1956                 $$ = pars;
1957           }
1958         | fixed_parameters COMMA fixed_parameter
1959           {
1960                 ArrayList pars = (ArrayList) $1;
1961
1962                 pars.Add ($3);
1963                 $$ = $1;
1964           }
1965         ;
1966
1967 fixed_parameter
1968         : opt_attributes
1969           opt_parameter_modifier
1970           identifier opt_type_character opt_rank_specifiers opt_type_spec opt_variable_initializer
1971           {
1972                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1973                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1974                 Expression ptype;
1975                 
1976                 if (opt_parm && ($7 == null))
1977                         Report.Error (999, "Optional parameters must have a default value");
1978                 
1979                 if (opt_parm) {
1980                         if ((pm & Parameter.Modifier.REF) !=0)
1981                                 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1982                         else
1983                                 pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
1984                 }       
1985                 
1986                 if ($4 != null && $6 != null && $4 != $6)
1987                         Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1988
1989                 ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6);
1990                 if ($5 != null) {
1991                         string t = ptype.ToString() + VariableDeclaration.BuildRank ((ArrayList) $5);
1992                         ptype = DecomposeQI (t, lexer.Location);
1993                 }                       
1994                 $$ = new Parameter (ptype, (string) $3, pm,
1995                                         (Attributes) $1, (Expression) $7, opt_parm);
1996           }
1997         ;
1998         
1999 parameter_array
2000         : PARAM_ARRAY identifier opt_parens AS type 
2001           { 
2002                 string s_patype = ((Expression) $5).ToString();
2003                 if ((bool) $3)
2004                         s_patype += "[]";
2005                         
2006                 Expression patype = DecomposeQI (s_patype, Location.Null);
2007                 $$ = new Parameter (patype, (string) $2, Parameter.Modifier.PARAMS, null);
2008                 // note  ("type must be a single-dimension array type"); 
2009           }
2010         ;
2011                 
2012 opt_parens
2013         : /* empty */
2014           {     $$ = false;     }
2015         | OPEN_PARENS CLOSE_PARENS
2016           {     $$ = true;      }
2017         ;
2018         
2019 opt_parameter_modifier
2020         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
2021         | parameter_modifiers   { $$ = $1;                      }
2022         ;
2023
2024 parameter_modifiers
2025         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
2026         | parameter_modifier                            { $$ = $1;      }
2027         ;
2028         
2029 parameter_modifier
2030         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
2031         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
2032         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
2033         ;       
2034
2035 opt_statement_list
2036         : /* empty */
2037         | statement_list end_of_stmt
2038         ;
2039
2040 statement_list
2041         : statement 
2042         | statement_list end_of_stmt statement
2043         ;
2044         
2045 statement : 
2046             declaration_statement
2047             {
2048                 if ($1 != null && (Block) $1 != current_block){
2049                         current_block.AddStatement ((Statement) $1);
2050                         current_block = (Block) $1;
2051                 }
2052             }
2053           | embedded_statement
2054             {
2055                 Statement s = (Statement) $1;
2056
2057                 current_block.AddStatement ((Statement) $1);
2058             } 
2059           | labeled_statement 
2060           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
2061            {
2062                 AddHandler ((Expression) $2, (string) $5);
2063            }
2064           | RAISEEVENT identifier opt_raise_event_args  //OPEN_PARENS opt_argument_list CLOSE_PARENS
2065             {
2066                 RaiseEvent ((string) $2, (ArrayList) $3);
2067             }
2068           /* | array_handling_statement */
2069           /* | empty_statement */
2070           | with_statement 
2071             {
2072                 Statement s = (Statement) $1;
2073
2074                 current_block.AddStatement ((Statement) $1);
2075             }     
2076           ;     
2077           
2078 opt_raise_event_args 
2079         : /* empty */   { $$ = null; }
2080         | OPEN_PARENS opt_argument_list CLOSE_PARENS
2081           {
2082                 $$ = $2;
2083           }
2084         ;
2085
2086 labeled_statement
2087         : identifier COLON end_of_stmt 
2088           {
2089                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
2090
2091                 if (!current_block.AddLabel ((string) $1, labeled)){
2092                         Location l = lexer.Location;
2093                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2094                 }       
2095                 current_block.AddStatement (labeled);
2096           }
2097           statement
2098         ;
2099
2100 embedded_statement
2101         : expression_statement
2102         | selection_statement
2103         | iteration_statement
2104         | try_statement
2105         | jump_statement
2106         | array_handling_statement 
2107         ;
2108 /*        
2109 empty_statement
2110         : end_of_stmt
2111           {
2112                   $$ = new EmptyStatement ();
2113           }
2114         ;        
2115 */
2116
2117 with_statement
2118         : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */
2119           {
2120                 // was : Expression e = DecomposeQI ((string) $2, lexer.Location);
2121                 Expression e = (Expression) $2;
2122                 with_stack.Push(e);
2123                 start_block();
2124           }
2125           opt_statement_list
2126           END WITH
2127           {
2128                 Block b = end_block();
2129                 with_stack.Pop();
2130                 $$ = b;
2131           }
2132         ;
2133         
2134         
2135 array_handling_statement
2136         : redim_statement
2137         | erase_statement
2138         ;
2139         
2140 redim_statement
2141         : REDIM opt_preserve redim_clauses
2142           {
2143                 ArrayList list = (ArrayList) $3;
2144                 ReDim r = new ReDim (list, (bool) $2, lexer.Location);
2145                 $$ = r;
2146
2147           }
2148         ;
2149         
2150 opt_preserve
2151         : /* empty */   { $$ = false; }
2152         | PRESERVE      { $$ = true;  }
2153         ;
2154         
2155 redim_clauses
2156         : redim_clause
2157           {
2158                 ArrayList clauses = new ArrayList ();
2159
2160                 clauses.Add ($1);
2161                 $$ = clauses;
2162           }
2163         | redim_clauses COMMA redim_clause
2164           {
2165                 ArrayList clauses = (ArrayList) ($1);
2166                 clauses.Add ($2);
2167
2168                 $$ = clauses;
2169           }
2170         ;
2171
2172 redim_clause
2173         : invocation_expression
2174           {
2175                 Invocation i = (Invocation) $1;
2176                 RedimClause rc = new RedimClause (i.expr, i.Arguments);
2177                 $$ = rc;
2178           }
2179         ;
2180
2181 erase_statement
2182         : ERASE erase_clauses
2183         {
2184                 ArrayList list = (ArrayList) $2;
2185                 foreach(Expression e in list)
2186                 {
2187                         Erase r = new Erase (e, lexer.Location);
2188                         $$ = r;
2189                 }
2190         }
2191         ;
2192
2193 erase_clauses
2194         : erase_clause
2195           {
2196                 ArrayList clauses = new ArrayList ();
2197
2198                 clauses.Add ($1);
2199                 $$ = clauses;
2200           }
2201         | erase_clauses COMMA erase_clause
2202           {
2203                 ArrayList clauses = (ArrayList) ($1);
2204                 clauses.Add ($2);
2205
2206                 $$ = clauses;
2207           }
2208         ;
2209
2210 erase_clause
2211         : primary_expression
2212         ;       
2213                         
2214 jump_statement
2215         : /*break_statement
2216         | continue_statement
2217         | */return_statement
2218         | goto_statement        
2219         | throw_statement       
2220         | exit_statement
2221         | yield_statement
2222         ;
2223                 
2224 goto_statement
2225         : GOTO identifier  
2226           {
2227                 $$ = new Goto (current_block, (string) $2, lexer.Location);
2228           }
2229         ;
2230         
2231 throw_statement
2232         : THROW opt_expression
2233           {
2234                 $$ = new Throw ((Expression) $2, lexer.Location);
2235           }
2236         ;       
2237                         
2238 exit_statement
2239         : EXIT exit_type
2240           {
2241                 $$ = new Exit ((ExitType)$2, lexer.Location);           
2242           }
2243         ;
2244         
2245 exit_type
2246         : DO            { $$ = ExitType.DO;             }
2247         | FOR           { $$ = ExitType.FOR;            }
2248         | WHILE         { $$ = ExitType.WHILE;          }
2249         | SELECT        { $$ = ExitType.SELECT;         }
2250         | SUB           { $$ = ExitType.SUB;            }
2251         | FUNCTION      { $$ = ExitType.FUNCTION;       }
2252         | PROPERTY      { $$ = ExitType.PROPERTY;       }
2253         | TRY           { $$ = ExitType.TRY;            }
2254         ;
2255 return_statement
2256         : RETURN opt_expression 
2257           {       
2258                 $$ = new Return ((Expression) $2, lexer.Location);
2259           }
2260         ;
2261                 
2262 iteration_statement
2263         : while_statement
2264         | do_statement
2265         | for_statement
2266         | foreach_statement
2267         ;
2268
2269 foreach_statement
2270         : FOR EACH identifier IN 
2271           {
2272                 oob_stack.Push (lexer.Location);
2273           }       
2274           expression end_of_stmt
2275           {
2276                 
2277                 start_block();
2278                 Block foreach_block = current_block;
2279                 Location l = lexer.Location;            
2280                 LocalVariableReference v = null;
2281                 VariableInfo vi;
2282
2283                 vi = foreach_block.GetVariableInfo ((string) $3);
2284                 if (vi != null) {
2285                         // Get a reference to this variable.
2286                         v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2287                 }
2288                 else
2289                         Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2290         
2291                 oob_stack.Push (v);
2292           }       
2293           opt_statement_list
2294           NEXT opt_identifier
2295           {
2296                 Block foreach_block = current_block;
2297                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2298                 Block prev_block = end_block();
2299                 Location l = (Location) oob_stack.Pop ();
2300
2301                 Foreach f = null;
2302                 if (v != null) {
2303                         f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
2304                 }
2305                 
2306                 $$ = f;
2307           }       
2308         ;
2309
2310 yield_statement 
2311         : YIELD expression
2312           {
2313                 if (!UseExtendedSyntax)
2314                 {
2315                         ReportError9998();
2316                         $$ = null;
2317                 }
2318 /*              else
2319                         if (iterator_container == null){
2320                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2321                                 $$ = null;
2322                         } else {
2323                                 iterator_container.SetYields ();
2324                                 $$ = new Yield ((Expression) $2, lexer.Location);
2325                         } */
2326           }
2327         | YIELD STOP
2328           {
2329                 if (!UseExtendedSyntax)
2330                 {
2331                         ReportError9998();
2332                         $$ = null;
2333                 }
2334 /*              else
2335                         if (iterator_container == null){
2336                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2337                                 $$ = null;
2338                         } else {
2339                                 iterator_container.SetYields ();
2340                                 $$ = new YieldBreak (lexer.Location);
2341                         } */
2342           }
2343         ;
2344
2345
2346
2347 try_statement
2348         : try_catch
2349         | try_catch_finally
2350         ;
2351                                 
2352 try_header
2353         : TRY end_of_stmt
2354           {   
2355                 start_block();  
2356           }
2357           opt_statement_list 
2358           opt_catch_clauses
2359           {
2360                 tmp_catch_clauses = (ArrayList) $5;
2361           }
2362         ;
2363                                         
2364 try_catch
2365         : try_header 
2366           END TRY
2367           { 
2368                 Catch g = null;
2369                 ArrayList s = new ArrayList ();
2370
2371                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2372                         if (cc.IsGeneral)
2373                                 g = cc;
2374                         else
2375                                 s.Add (cc);
2376                 }
2377
2378                 // Now s contains the list of specific catch clauses
2379                 // and g contains the general one.
2380                 Block b = end_block();
2381
2382                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2383           }       
2384         ;       
2385           
2386 try_catch_finally
2387         : try_header 
2388           { 
2389                 tmp_block = end_block(); 
2390           }     
2391           FINALLY end_of_stmt
2392           { 
2393                 start_block(); 
2394           }       
2395           opt_statement_list 
2396           END TRY
2397           {
2398                 Catch g = null;
2399                 ArrayList s = new ArrayList ();
2400                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2401
2402                 if (catch_list != null){
2403                         foreach (Catch cc in catch_list) {
2404                                 if (cc.IsGeneral)
2405                                         g = cc;
2406                                 else
2407                                         s.Add (cc);
2408                         }
2409                 }
2410
2411                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2412         
2413           }     
2414           ;             
2415
2416 opt_catch_clauses
2417         : /* empty */  {  $$ = null;  }
2418         | catch_clauses
2419         ;
2420
2421 catch_clauses
2422         : catch_clause 
2423           {
2424                 ArrayList l = new ArrayList ();
2425
2426                 l.Add ($1);
2427                 $$ = l;
2428           }
2429         | catch_clauses catch_clause
2430           {
2431                 ArrayList l = (ArrayList) $1;
2432
2433                 l.Add ($2);
2434                 $$ = l;
2435           }
2436         ;
2437
2438 opt_identifier
2439         : /* empty */   {  $$ = null;  }
2440         | identifier
2441         ;
2442
2443 catch_clause 
2444         : CATCH opt_catch_args end_of_stmt
2445         {
2446                 Expression type = null;
2447                 string id = null;
2448                 
2449                 if ($2 != null) {
2450                         DictionaryEntry cc = (DictionaryEntry) $2;
2451                         type = (Expression) cc.Key;
2452                         id   = (string) cc.Value;
2453                         
2454                         if (id != null){
2455                                 ArrayList one = new ArrayList ();
2456                                 Location loc = lexer.Location;
2457
2458                                 one.Add (new VariableDeclaration (id, type, loc));
2459
2460
2461                                 $1 = current_block;
2462                                 current_block = new Block (current_block);
2463                                 Block b = declare_local_variables (type, one, loc);
2464                                 current_block = b;
2465                         }
2466                 }
2467         
2468         } 
2469         opt_statement_list {
2470                 Expression type = null;
2471                 string id = null;
2472                 Block b_catch = current_block;
2473                 
2474                 if ($2 != null){
2475                         DictionaryEntry cc = (DictionaryEntry) $2;
2476                         type = (Expression) cc.Key;
2477                         id   = (string) cc.Value;
2478                         
2479                         if ($1 != null) {
2480                                 //
2481                                 // FIXME: I can change this for an assignment.
2482                                 //
2483                                 while (current_block != (Block) $1)
2484                                         current_block = current_block.Parent;
2485                         }
2486                 }
2487
2488                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2489         }
2490         ;
2491
2492 opt_catch_args
2493         : /* empty */ {  $$ = null; }
2494         | catch_args
2495         ;         
2496
2497 catch_args 
2498         : identifier AS type
2499         {
2500                  $$ = new DictionaryEntry ($3, $1); 
2501         }
2502         ;
2503         
2504         
2505 do_statement
2506         : DO opt_do_construct end_of_stmt
2507           {
2508                 start_block();
2509                 oob_stack.Push (lexer.Location);
2510           }     
2511           opt_statement_list
2512           LOOP opt_do_construct
2513           {
2514                 Expression t_before = (Expression) $2;
2515                 Expression t_after = (Expression) $7;
2516                 Expression t;
2517
2518                 if  ((t_before != null) && (t_after != null))
2519                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2520
2521                 if ((t_before == null) && (t_after == null))
2522                         t = new BoolLiteral (true);
2523                 else
2524                         t = (t_before != null) ? t_before : t_after;
2525                         
2526                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2527                 
2528                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2529                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2530                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2531                          
2532                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2533           }
2534           ;
2535
2536 opt_do_construct
2537         : /* empty */ { $$ = null; }
2538         | while_or_until boolean_expression
2539           {
2540                 do_type = (DoOptions)$1;
2541                 $$ = (Expression) $2;
2542           }
2543         ;
2544
2545 while_or_until
2546         : WHILE { $$ = DoOptions.WHILE; }
2547         | UNTIL { $$ = DoOptions.UNTIL; }
2548         ;
2549
2550 while_statement
2551         : WHILE
2552         {
2553                 start_block();
2554                 oob_stack.Push (lexer.Location);
2555         }
2556         boolean_expression end_of_stmt
2557         opt_statement_list
2558         END WHILE
2559         {
2560                 Location l = (Location) oob_stack.Pop ();
2561                 Block b = end_block();
2562                 Expression e = (Expression) $3;
2563                 $$ = new While ((Expression) e, (Statement) b, l);
2564         }
2565         ;
2566         
2567                 
2568 for_statement
2569         : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2570           {
2571                 start_block();
2572           }
2573           opt_statement_list
2574           NEXT opt_identifier 
2575           {
2576                 Block statement = end_block();
2577                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2578                 
2579                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2580                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
2581                                                 for_var, (Expression) $6, lexer.Location);
2582                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2583                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
2584                                  
2585                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
2586                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2587                 
2588                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
2589           }       
2590         ;
2591
2592 opt_step
2593         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
2594         | STEP expression       { $$ = $2; }
2595         ;
2596
2597 selection_statement
2598         : if_statement
2599         | select_statement
2600         ;
2601
2602 if_statement
2603         : if_statement_open opt_then if_statement_rest
2604           {
2605                 $$ = $3;
2606           }
2607         | if_statement_open THEN pre_embedded_statement
2608           {
2609                 Location l = (Location) oob_stack.Pop ();
2610                 tmp_expr = (Expression)expr_stack.Pop(); 
2611                 $$ = new If ((Expression) tmp_expr, end_block(), l);
2612           }
2613         ;
2614
2615 pre_embedded_statement
2616         : embedded_statement 
2617           {
2618                 Statement s = (Statement) $1;
2619
2620                 current_block.AddStatement ((Statement) $1);
2621           } 
2622         ;       
2623         
2624 if_statement_open
2625         : IF boolean_expression 
2626           {
2627                 oob_stack.Push (lexer.Location);
2628                 start_block();
2629                 tmp_expr = (Expression) $2;
2630                 expr_stack.Push(tmp_expr);
2631           }
2632          ;
2633
2634 opt_then
2635         : /* empty */
2636         | THEN
2637         ;
2638         
2639 if_statement_rest
2640         : end_of_stmt
2641           opt_statement_list
2642           END IF
2643           { 
2644                 Location l = (Location) oob_stack.Pop ();
2645                 Expression expr = (Expression)expr_stack.Pop(); 
2646                 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2647           }       
2648         | end_of_stmt
2649           opt_statement_list
2650           ELSE end_of_stmt 
2651           { 
2652                 Block bl = end_block(); 
2653                 tmp_blocks.Push(bl); 
2654                 start_block();
2655           }
2656           opt_statement_list
2657           END IF        
2658           {
2659                 Location l = (Location) oob_stack.Pop ();
2660                 tmp_expr = (Expression)expr_stack.Pop(); 
2661                 tmp_block = (Block) tmp_blocks.Pop(); 
2662                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2663           }     
2664         | end_of_stmt
2665           opt_statement_list 
2666           ELSEIF boolean_expression opt_then 
2667           { 
2668                 tmp_expr = (Expression) $4;                                                  
2669                 expr_stack.Push(tmp_expr);                                                 
2670                 tmp_block = end_block();
2671                 tmp_blocks.Push(tmp_block);
2672                 start_block();
2673           }
2674           else_if_statement_rest 
2675           {
2676                 Statement stmt = (Statement) statement_stack.Pop();
2677                 Block bl = (Block) tmp_blocks.Pop();  
2678                 Expression expr =  (Expression)expr_stack.Pop();  
2679                 Location l = (Location) oob_stack.Pop ();
2680                 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l); 
2681           }
2682         ;
2683         
2684         
2685 else_if_statement_rest
2686         : end_of_stmt
2687           opt_statement_list 
2688           END IF
2689           { 
2690                 Location l = (Location) oob_stack.Pop ();
2691                 oob_stack.Push (l);
2692                 Expression expr = (Expression)expr_stack.Pop(); 
2693                 Statement stmt = (Statement) new If ((Expression) expr, (Statement)  end_block(), l);
2694                 statement_stack.Push(stmt);
2695           }
2696         | end_of_stmt
2697           opt_statement_list
2698           ELSE end_of_stmt 
2699           { 
2700                 Block bl = end_block();
2701                 tmp_blocks.Push(bl);
2702                 start_block();
2703           }
2704           opt_statement_list
2705           END IF        
2706           {
2707                 Location l = (Location) oob_stack.Pop ();
2708                 oob_stack.Push (l);
2709                 Expression expr = (Expression)expr_stack.Pop(); 
2710                 Block bl = (Block)tmp_blocks.Pop(); 
2711                 Statement stmt = (Statement) new If ((Expression) expr,  (Statement) bl , (Statement)  end_block(), l);
2712                 statement_stack.Push(stmt);
2713           }     
2714         | end_of_stmt
2715           opt_statement_list 
2716           ELSEIF boolean_expression opt_then 
2717           { 
2718                 expr_stack.Push((Expression) $4);                                                 
2719                 Block bl = end_block();
2720                 tmp_blocks.Push(bl);
2721                 start_block();
2722           }
2723           else_if_statement_rest 
2724           {
2725                 Location l = (Location) oob_stack.Pop ();
2726                 oob_stack.Push (l);
2727                 Statement tmp_stmt = (Statement)statement_stack.Pop();
2728                 Block bl = (Block) tmp_blocks.Pop();  
2729                 Expression expr =  (Expression)expr_stack.Pop();  
2730                 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
2731                 statement_stack.Push(stmt);
2732           }          
2733         ;
2734         
2735 select_statement
2736         : SELECT opt_case expression end_of_stmt
2737           { 
2738                 oob_stack.Push (lexer.Location);
2739                 switch_stack.Push (current_block);
2740           }     
2741           opt_case_sections
2742           END SELECT 
2743           {
2744                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2745                 current_block = (Block) switch_stack.Pop ();
2746           }       
2747         ;
2748
2749 opt_case_sections
2750         : /* empty */   { $$ = null; }
2751         | case_sections { $$ = $1; }
2752         ;
2753         
2754 case_sections
2755         : case_sections case_section
2756           {
2757                 ArrayList sections = (ArrayList) $1;
2758
2759                 sections.Add ($2);
2760                 $$ = sections;
2761           }
2762         | case_section
2763           {
2764                 ArrayList sections = new ArrayList ();
2765
2766                 sections.Add ($1);
2767                 $$ = sections;
2768           }
2769         ;
2770
2771 ends 
2772         : end_of_stmt
2773         | ends end_of_stmt
2774         ;
2775         
2776
2777 case_section
2778         : CASE case_clauses ends
2779           { 
2780                 start_block();
2781           }
2782           opt_statement_list
2783           {
2784                 //Block topmost = current_block;
2785                 Block topmost = end_block();
2786                 
2787                 while (topmost.Implicit)
2788                         topmost = topmost.Parent;
2789                         
2790                 // FIXME: This is a horrible hack which MUST go                 
2791                 topmost.statements.Add (new Break (lexer.Location));
2792                 $$ = new SwitchSection ((ArrayList) $2, topmost);
2793           }
2794           | CASE ELSE ends
2795             /* FIXME: we should somehow flag an error 
2796                (BC30321 'Case' cannot follow a 'Case Else' 
2797                in the same 'Select' statement.) 
2798                if Case Else is not the last of the Case clauses
2799             */
2800           { 
2801                 start_block();
2802           }     
2803           opt_statement_list
2804           { 
2805                 //Block topmost = current_block;
2806                 Block topmost = end_block();
2807
2808                 while (topmost.Implicit)
2809                         topmost = topmost.Parent;
2810                         
2811                 // FIXME: This is a horrible hack which MUST go                 
2812                 topmost.statements.Add (new Break (lexer.Location));
2813                 
2814                 ArrayList a = new ArrayList();
2815                 a.Add (new SwitchLabel (null, lexer.Location));                 
2816                 $$ = new SwitchSection ((ArrayList) a, topmost);                
2817           }
2818         ;         
2819         
2820 case_clauses
2821         : case_clause
2822           {
2823                 ArrayList labels = new ArrayList ();
2824
2825                 labels.Add ($1);
2826                 $$ = labels;
2827           }     
2828         | case_clauses COMMA case_clause
2829           {
2830                 ArrayList labels = (ArrayList) ($1);
2831                 labels.Add ($2);
2832
2833                 $$ = labels;
2834           }     
2835         ;
2836         
2837 case_clause
2838         : opt_is comparison_operator expression
2839         | expression
2840           {
2841                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2842           }
2843         ;
2844         
2845 opt_is 
2846         : /* empty */
2847         | IS
2848         ;
2849
2850 comparison_operator
2851         : OP_LT
2852         | OP_GT
2853         | OP_LE
2854         | OP_NE
2855         /*| OP_EQ */
2856         ;
2857
2858 opt_case
2859         : /* empty */
2860         | CASE
2861         ;
2862
2863 expression_statement
2864         : statement_expression 
2865           {
2866                  $$ = $1; 
2867           }
2868         ;
2869
2870
2871 statement_expression
2872         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2873         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2874         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2875         ;
2876
2877 object_creation_expression
2878         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2879           {
2880                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2881           }
2882         | NEW type
2883           {
2884                 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
2885           }
2886         ;
2887         
2888 array_creation_expression
2889         : object_creation_expression array_initializer
2890           {
2891                 New n = (New) $1;
2892                 ArrayList dims = new ArrayList();
2893                 
2894                 if (n.Arguments != null) {
2895                         foreach (Argument a in n.Arguments) {
2896                                 dims.Add (a.Expr);
2897                         }
2898                 }
2899                         
2900                 Expression atype = n.RequestedType;
2901
2902                 ArrayList init = (ArrayList) $2;
2903                 if (init.Count == 0)
2904                         init = null;
2905         
2906                 if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
2907                         VariableDeclaration.VBFixIndexList (ref dims);
2908                         $$ = new ArrayCreation (atype, dims, "", init, lexer.Location); 
2909                 }
2910                 else
2911                 {
2912                         string rank = VariableDeclaration.BuildRank (dims);
2913                         $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location); 
2914                 }
2915                 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
2916           }
2917         ;       
2918
2919 delegate_creation_expression
2920         : NEW type OPEN_PARENS ADDRESSOF opt_argument_list CLOSE_PARENS
2921           {
2922                 New n = new New ((Expression) $2, (ArrayList) $5, lexer.Location);
2923                 if (n==null)
2924                         Console.WriteLine("empty");
2925                 $$ = n;
2926           }
2927         ;
2928
2929 new_expression
2930         : object_creation_expression
2931         | array_creation_expression
2932         | delegate_creation_expression
2933         ;
2934
2935 declaration_statement
2936         : local_variable_declaration 
2937           {
2938                 if ($1 != null){
2939                         DictionaryEntry de = (DictionaryEntry) $1;
2940
2941                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2942                 }
2943           }
2944         | local_constant_declaration 
2945           {
2946                 if ($1 != null){
2947                         DictionaryEntry de = (DictionaryEntry) $1;
2948
2949                         $$ = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value);
2950                 }
2951           }
2952         ;        
2953         
2954 local_variable_declaration
2955         : DIM variable_declarators
2956           {
2957                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
2958           }
2959         ;
2960
2961         
2962 local_constant_declaration
2963         : CONST constant_declarators
2964           {
2965                 if ($2 != null)
2966                         $$ = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), $2);
2967                 else
2968                         $$ = null;
2969           }
2970         ;        
2971         
2972 constant_declarators
2973         : constant_declarator 
2974           {
2975                 ArrayList decl = new ArrayList ();
2976                 if ($1 != null) 
2977                         decl.Add ($1);
2978                         
2979                 $$ = decl;
2980           }
2981         | constant_declarators COMMA constant_declarator
2982           {
2983                 ArrayList decls = (ArrayList) $1;
2984                 if ($3 != null)
2985                         decls.Add ($3);
2986
2987                 $$ = $1;
2988           }
2989         ;
2990
2991 constant_declarator
2992         : variable_name opt_type_decl opt_variable_initializer
2993           {
2994                 VarName vname = (VarName) $1;
2995                 string varname = (string) vname.Name;
2996                 current_rank_specifiers = (ArrayList) vname.Rank;
2997                 object varinit = $3;
2998                 ArrayList a_dims = null;
2999
3000                 if (varinit == null)
3001                         Report.Error (
3002                                 30438, lexer.Location, "Constant should have a value"
3003                                 );
3004
3005                 if (vname.Type != null && $2 != null)
3006                         Report.Error (
3007                                 30302, lexer.Location, 
3008                                 "Type character cannot be used with explicit type declaration" );
3009
3010                 Expression vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3011
3012                 if (current_rank_specifiers != null) 
3013                 {
3014                         Report.Error (30424, lexer.Location, "Constant doesn't support array");
3015                         $$ = null;
3016                 }
3017                 else
3018                         $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
3019           }
3020         ;               
3021
3022 variable_declarators
3023         : variable_declarator 
3024           {
3025                 ArrayList decl = new ArrayList ();
3026                 decl.AddRange ((ArrayList) $1);
3027                 $$ = decl;
3028           }
3029         | variable_declarators COMMA variable_declarator
3030           {
3031                 ArrayList decls = (ArrayList) $1;
3032                 decls.AddRange ((ArrayList) $3);
3033                 $$ = $1;
3034           }
3035         ;
3036
3037 variable_declarator
3038         : variable_names opt_type_decl opt_variable_initializer
3039           {
3040             ArrayList names = (ArrayList) $1;
3041                 object varinit = $3;
3042                 ArrayList VarDeclarations = new ArrayList();
3043                 Expression vartype;
3044                 ArrayList a_dims = null;
3045
3046                 if ((names.Count > 1) && (varinit != null)) 
3047                         Report.Error (
3048                                 30671, lexer.Location, 
3049                                 "Multiple variables with single type can not have " +
3050                                 "a explicit initialization" );
3051
3052                                 
3053                 foreach (VarName vname in names)
3054                 {
3055                         string varname = (string) vname.Name;
3056                         current_rank_specifiers = (ArrayList) vname.Rank;
3057                         a_dims = null;
3058                         varinit = $3;
3059
3060                         if(vname.Type != null && $2 != null)
3061                                 Report.Error (
3062                                         30302, lexer.Location, 
3063                                         "Type character cannot be used with explicit type declaration" );
3064
3065                         // Some checking is required for particularly weird declarations
3066                         // like Dim a As Integer(,)
3067                         if ($2 is Pair) {
3068                                 vartype = (Expression) ((Pair) $2).First;
3069                                 
3070                                 /*if ($3 != null && $3 is ArrayList)
3071                                         Report.Error (205, "End of statement expected.");*/
3072                                         
3073                                 ArrayList args = (ArrayList) ((Pair) $2).Second;
3074                                 if (current_rank_specifiers != null)
3075                                         Report.Error (31087, lexer.Location,
3076                                                  "Array types specified in too many places");   
3077                                 
3078                                 if (VariableDeclaration.IndexesSpecifiedInRank (args))            
3079                                         Report.Error (30638, "Array bounds cannot appear in type specifiers."); 
3080                                 
3081                                 current_rank_specifiers = new ArrayList ();
3082                                 current_rank_specifiers.Add (args);
3083                                 
3084                                 /*string s_vartype = vartype.ToString();                                
3085                                 s_vartype += "[";
3086                                 if (args != null)
3087                                         for (int x = 0; x < args.Count; x++)
3088                                                 s_vartype += ",";
3089                                         
3090                                 s_vartype += "]";       
3091                                 vartype = DecomposeQI(s_vartype, Location.Null);        */
3092                         }
3093                         else
3094                                 vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3095
3096                         // if the variable is an array with explicit bound
3097                         // and having explicit initialization throw exception
3098                         if (current_rank_specifiers != null && varinit != null) 
3099                         {
3100                                 bool broken = false;
3101                                 foreach (ArrayList exprs in current_rank_specifiers)
3102                                 {
3103                                         foreach (Expression expr in exprs)
3104                                         {
3105                                                 if (!((Expression)expr is EmptyExpression ))
3106                                                 {
3107                                                         Report.Error (
3108                                                                 30672, lexer.Location, 
3109                                                                 "Array declared with explicit bound " +
3110                                                                 " can not have explicit initialization");
3111                                                         broken = true;
3112                                                         break;
3113                                                 }
3114                                         }
3115                                         if (broken)
3116                                                 break;
3117                                 }
3118                         }
3119                         
3120                         /*
3121                         Check for a declaration like Dim a(2) or Dim a(2,3)
3122                         If this is the case, we must generate an ArrayCreationExpression
3123                         and, in case, add the initializer after the array has been created.
3124                         */
3125                         if (VariableDeclaration.IsArrayDecl (this)) {   
3126                                 if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) {   
3127                                         a_dims = (ArrayList) current_rank_specifiers;
3128                                         VariableDeclaration.VBFixIndexLists (ref a_dims);
3129                                         varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
3130                                 }
3131                                 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
3132                         }
3133
3134                         if (vartype is New) {
3135                                 if (varinit != null) {
3136                                         Report.Error (30205, lexer.Location, "End of statement expected");
3137                                         $$ = null;
3138                                 }
3139                                 else
3140                                 {
3141                                         varinit = vartype;
3142                                         vartype = ((New)vartype).RequestedType;
3143                                 }
3144                         }
3145                         VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null));
3146             }// end of for
3147             $$ = VarDeclarations;
3148           } 
3149         ;
3150
3151 variable_names
3152         : variable_name
3153           {
3154                 ArrayList list = new ArrayList ();
3155                 list.Add ($1);
3156                 $$ = list;
3157           }
3158         | variable_names COMMA variable_name
3159           {
3160                 ArrayList list = (ArrayList) $1;
3161                 list.Add ($3);
3162                 $$ = list;
3163           }
3164         ;
3165         
3166 variable_name
3167         : identifier opt_type_character opt_array_name_modifier
3168           {
3169                 $$ = new VarName ($1, $2, $3);
3170           }
3171         ;
3172
3173 opt_type_spec
3174         : /* empty */   
3175           { 
3176                 $$ = null;              
3177           }
3178         | AS type       
3179           { 
3180                 $$ = (Expression) $2;
3181           }
3182         ;
3183                 
3184 opt_type_with_ranks
3185         : opt_type_spec 
3186         | AS type rank_specifiers
3187           {
3188                 $$ = TypeManager.system_object_expr; 
3189           }
3190         ;
3191         
3192 opt_type_decl
3193         : opt_type_spec
3194           {
3195                 $$ = $1;
3196           }
3197         | AS type OPEN_PARENS /*opt_argument_list*/ opt_dim_separators CLOSE_PARENS
3198           {
3199                 $$ = new Pair ($2, $4);
3200           }
3201         | AS NEW type
3202           {
3203                 New n = new New ((Expression)$3, null, lexer.Location);
3204                 $$ = (Expression) n;
3205           }
3206         | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS 
3207           {
3208                 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
3209                 $$ = (Expression) n;
3210           }
3211         | AS NEW type OPEN_PARENS ADDRESSOF opt_argument_list CLOSE_PARENS 
3212           {
3213                 New n = new New ((Expression)$3, (ArrayList) $6, lexer.Location);
3214                 $$ = (Expression) n;
3215           }
3216         ;
3217                 
3218 opt_array_name_modifier
3219         : /* empty */                           { $$ = null; }
3220         | array_type_modifier                   { $$ = $1;   }
3221         ;
3222         
3223 array_type_modifier
3224         : rank_specifiers               { $$ = $1; }
3225         ;
3226         
3227 opt_variable_initializer
3228         : /* empty */                   { $$ = null; }
3229         | ASSIGN variable_initializer   { $$ = $2; }
3230         ;
3231                 
3232 variable_initializer
3233         : expression
3234           {
3235                 $$ = $1;
3236           }
3237         | array_initializer
3238           {
3239                 $$ = $1;
3240           }
3241         
3242         ;       
3243         
3244 array_initializer
3245         : OPEN_BRACE CLOSE_BRACE
3246           {
3247                 ArrayList list = new ArrayList ();
3248                 $$ = list;
3249           }
3250         | OPEN_BRACE variable_initializer_list CLOSE_BRACE
3251           {
3252                 $$ = (ArrayList) $2;
3253           }
3254         ;
3255
3256 variable_initializer_list
3257         : variable_initializer
3258           {
3259                 ArrayList list = new ArrayList ();
3260                 list.Add ($1);
3261                 $$ = list;
3262           }
3263         | variable_initializer_list COMMA variable_initializer
3264           {
3265                 ArrayList list = (ArrayList) $1;
3266                 list.Add ($3);
3267                 $$ = list;
3268           }
3269         ;
3270
3271 opt_rank_specifiers
3272         : /* empty */
3273           {
3274                   // $$ = "";
3275                   $$ = null;
3276           }
3277         | rank_specifiers
3278           {
3279                         $$ = $1;
3280           }
3281         ;      
3282         
3283 rank_specifiers
3284         : rank_specifier
3285           {
3286                   ArrayList rs = new ArrayList();
3287                   rs.Add ($1);
3288                   $$ = rs;
3289           }
3290         | rank_specifiers rank_specifier
3291           {
3292                   ArrayList rs = (ArrayList) $1;
3293                   rs.Add ($2);
3294                   $$ = rs;
3295           }             
3296         ;               
3297         
3298 rank_specifier
3299         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
3300           {
3301                 $$ = $2;
3302           }
3303         ;
3304                 
3305 opt_dim_separators
3306         : /* empty */
3307           {
3308                 ArrayList ds = new ArrayList();
3309                 ds.Add (new EmptyExpression());
3310                 $$ = ds;                
3311           }
3312         | dim_separators
3313           {
3314                 ArrayList ds = (ArrayList) $1;
3315                 ds.Add (new EmptyExpression());
3316                 $$ = ds;        
3317           }     
3318         | dim_specifiers
3319           {
3320                 $$ = $1;
3321           }       
3322         ;
3323
3324 dim_separators
3325         : COMMA
3326           {
3327                 ArrayList ds = new ArrayList();
3328                 ds.Add (new EmptyExpression());
3329                 $$ = ds;
3330           }
3331         | dim_separators COMMA
3332           {
3333                 ArrayList ds = (ArrayList) $1;
3334                 ds.Add (new EmptyExpression());
3335                 $$ = ds;                
3336           }
3337         ;
3338
3339 dim_specifiers
3340         : expression
3341           {
3342                 ArrayList ds = new ArrayList();
3343                 ds.Add ((Expression) $1);
3344                 $$ = ds;
3345           }     
3346         | dim_specifiers COMMA expression
3347           {
3348                 ArrayList ds = (ArrayList) $1;
3349                 ds.Add ((Expression) $3);
3350                 $$ = ds;                
3351           }     
3352         ;
3353         
3354 /* Expressions */
3355 primary_expression
3356         : literal
3357           {
3358                 // 7.5.1: Literals
3359           }
3360
3361         | qualified_identifier
3362           {
3363                 string name = (string) $1;
3364
3365                 $$ = DecomposeQI (name, lexer.Location);
3366           }
3367         | parenthesized_expression
3368         | member_access
3369         | invocation_expression
3370         //| element_access
3371         | this_access
3372         | base_access
3373         | new_expression
3374         | cast_expression
3375         ;
3376
3377 literal
3378         : boolean_literal
3379         | integer_literal
3380         | real_literal
3381         | LITERAL_DATE                  { $$ = new DateLiteral ((DateTime)lexer.Value); }
3382         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
3383         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
3384         | NOTHING                               { $$ = NullLiteral.Null; }
3385         ;
3386
3387 real_literal
3388         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
3389         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
3390         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3391         ;
3392
3393 integer_literal
3394         : LITERAL_INTEGER       {
3395                 object v = lexer.Value;
3396
3397                 if (v is int)
3398                         $$ = new IntLiteral ((Int32)v); 
3399                 else if (v is short)
3400                         $$ = new ShortLiteral ((Int16)v);
3401                 else if (v is long)
3402                         $$ = new LongLiteral ((Int64)v);
3403                 else
3404                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
3405                         
3406           }
3407         ;
3408
3409 boolean_literal
3410         : TRUE                  { $$ = new BoolLiteral (true); }
3411         | FALSE                 { $$ = new BoolLiteral (false); }
3412         ;
3413
3414 parenthesized_expression
3415         : OPEN_PARENS expression CLOSE_PARENS
3416           { $$ = $2; }
3417         ;
3418
3419 member_access
3420         : primary_expression DOT identifier
3421           {
3422                 if ($1 != null) {
3423                         string id_name = (string)$3;
3424                         if (id_name.ToUpper() == "NEW")
3425                                 id_name = ".ctor";
3426                         $$ = new MemberAccess ((Expression) $1, id_name, lexer.Location);
3427                 }
3428                 else
3429                 {
3430                         if (with_stack.Count > 0) {
3431                                 Expression e = (Expression) with_stack.Peek();
3432                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3433                         }
3434                         else
3435                         {
3436                                 // OOps
3437                         }
3438                 }
3439           }
3440 /*      | primary_expression DOT NEW
3441           {
3442                 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3443           }       */
3444         | predefined_type DOT identifier
3445           {
3446                 if ($1 != null)
3447                         $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3448                 else
3449                 {
3450                         if (with_stack.Count > 0) {
3451                                 Expression e = (Expression) with_stack.Peek();
3452                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3453                         }
3454                         else
3455                         {
3456                                 // OOps
3457                         }
3458                 }
3459           }
3460         ;
3461
3462 predefined_type
3463         : builtin_types
3464         ;
3465
3466 invocation_expression
3467         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3468           {
3469                 if ($1 == null) {
3470                         Location l = lexer.Location;
3471                         Report.Error (1, l, "THIS IS CRAZY");
3472                 }
3473                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3474 //              Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3475           } 
3476         ;
3477         
3478 base_access
3479         : MYBASE DOT IDENTIFIER
3480           {
3481                 string id_name = (string) $3;
3482                 if (id_name.ToUpper() == "NEW")
3483                         id_name = "New";
3484                 $$ = new BaseAccess (id_name, lexer.Location);
3485           }
3486 /*      | MYBASE DOT NEW
3487           {
3488                 $$ = new BaseAccess ("New", lexer.Location);
3489           }*/
3490         ;       
3491
3492 opt_argument_list
3493         : argument_list
3494           { 
3495                 /*
3496                    The 'argument' rule returns an 'empty' argument
3497                    of type NoArg (used for default arguments in invocations)
3498                    if no arguments are actually passed.
3499
3500                    If there is only one argument and it is o type NoArg,
3501                    we return a null (empty) list
3502                 */
3503                 ArrayList args = (ArrayList) $1;
3504                 if (args.Count == 1 &&
3505                     ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3506                         $$ = null;
3507                 else
3508                         $$ = $1;
3509           }
3510         ;
3511
3512 argument_list
3513         : argument
3514           {
3515                 ArrayList list = new ArrayList ();
3516                 list.Add ($1);
3517                 $$ = list;
3518           }
3519         | argument_list COMMA argument
3520           {
3521                 ArrayList list = (ArrayList) $1;
3522                 list.Add ($3);
3523                 $$ = list;
3524           }
3525         ;
3526
3527 argument
3528         : expression
3529           {
3530                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3531           }
3532         | BYREF variable_reference
3533           {
3534                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3535           }
3536         | /* empty */
3537           {
3538                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3539           }
3540         ;
3541
3542 variable_reference
3543         : expression {/* note ("section 5.4"); */  $$ = $1;  }
3544         ;
3545
3546 negation_expression
3547         : NOT expression 
3548           {
3549                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3550           }
3551         ;
3552                 
3553 expression
3554         : conditional_expression { $$ = $1; }
3555         | negation_expression
3556         /*| assignment_expression*/
3557         ;
3558
3559 opt_expression
3560         : /* empty */
3561         | expression
3562         ;
3563                 
3564 this_access
3565         : ME
3566           {
3567                 $$ = new This (current_block, lexer.Location);
3568           }
3569         | MYCLASS
3570           {
3571                 // FIXME: This is actually somewhat different from Me
3572                 // because it is for accessing static (classifier) methods/properties/fields
3573                 $$ = new This (current_block, lexer.Location);
3574           }
3575         ;
3576
3577 unary_expression
3578         : primary_expression
3579         /*| NOT prefixed_unary_expression
3580           {
3581                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3582           }
3583         | cast_expression */
3584         ;
3585         
3586 cast_expression
3587         : cast_operator OPEN_PARENS expression CLOSE_PARENS
3588           {
3589                   $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3590           }     
3591         | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3592           {
3593                   $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3594           }                       
3595         ;
3596         
3597 cast_operator
3598         : CBOOL         { $$ = TypeManager.system_boolean_expr;         }
3599         | CBYTE         { $$ = TypeManager.system_byte_expr;            }
3600         | CCHAR         { $$ = TypeManager.system_char_expr;            }
3601         | CDATE         { $$ = TypeManager.system_date_expr;            }
3602         | CDBL          { $$ = TypeManager.system_double_expr;          }
3603         | CDEC          { $$ = TypeManager.system_decimal_expr;         }
3604         | CINT          { $$ = TypeManager.system_int32_expr;           }
3605         | CLNG          { $$ = TypeManager.system_int64_expr;           }
3606         | COBJ          { $$ = TypeManager.system_object_expr;          }
3607         | CSHORT        { $$ = TypeManager.system_int16_expr;           }
3608         | CSNG          { $$ = TypeManager.system_single_expr;          }
3609         | CSTR          { $$ = TypeManager.system_string_expr;  }
3610         ;
3611         
3612         //
3613         // The idea to split this out is from Rhys' grammar
3614         // to solve the problem with casts.
3615         //
3616 prefixed_unary_expression
3617         : unary_expression
3618         | PLUS prefixed_unary_expression
3619           {
3620                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3621           }
3622         | MINUS prefixed_unary_expression
3623           {
3624                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3625           }
3626         ;
3627
3628 multiplicative_expression
3629         : prefixed_unary_expression
3630         | multiplicative_expression STAR prefixed_unary_expression
3631           {
3632                 $$ = new Binary (Binary.Operator.Multiply,
3633                                  (Expression) $1, (Expression) $3, lexer.Location);
3634           }
3635         | multiplicative_expression DIV prefixed_unary_expression
3636           {
3637                 $$ = new Binary (Binary.Operator.Division,
3638                                  (Expression) $1, (Expression) $3, lexer.Location);
3639           }
3640         | multiplicative_expression OP_IDIV prefixed_unary_expression
3641           {
3642                 $$ = new Binary (Binary.Operator.Division,
3643                                  (Expression) $1, (Expression) $3, lexer.Location);
3644           }       
3645         | multiplicative_expression MOD prefixed_unary_expression
3646           {
3647                 $$ = new Binary (Binary.Operator.Modulus,
3648                                  (Expression) $1, (Expression) $3, lexer.Location);
3649           }
3650         ;
3651
3652 additive_expression
3653         : multiplicative_expression
3654         | additive_expression PLUS multiplicative_expression
3655           {
3656                 $$ = new Binary (Binary.Operator.Addition,
3657                                  (Expression) $1, (Expression) $3, lexer.Location);
3658           }
3659         | additive_expression MINUS multiplicative_expression
3660           {
3661                 $$ = new Binary (Binary.Operator.Subtraction,
3662                                  (Expression) $1, (Expression) $3, lexer.Location);
3663           }
3664         | additive_expression OP_CONCAT multiplicative_expression
3665           {
3666                 // FIXME: This should only work for String expressions
3667                 // We probably need to use something from the runtime
3668                 $$ = new Binary (Binary.Operator.Addition,
3669                                  (Expression) $1, (Expression) $3, lexer.Location);
3670           }       
3671         ;
3672
3673 relational_expression
3674         : additive_expression
3675         | relational_expression OP_LT additive_expression
3676           {
3677                 $$ = new Binary (Binary.Operator.LessThan,
3678                                  (Expression) $1, (Expression) $3, lexer.Location);
3679           }
3680         | relational_expression OP_GT additive_expression
3681           {
3682                 $$ = new Binary (Binary.Operator.GreaterThan,
3683                                  (Expression) $1, (Expression) $3, lexer.Location);
3684           }
3685         | relational_expression OP_LE additive_expression
3686           {
3687                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
3688                                  (Expression) $1, (Expression) $3, lexer.Location);
3689           }
3690         | relational_expression OP_GE additive_expression
3691           {
3692                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
3693                                  (Expression) $1, (Expression) $3, lexer.Location);
3694           }
3695         | relational_expression IS unary_expression
3696           {
3697                 $$ = new Binary (Binary.Operator.Equality,
3698                         (Expression) $1, (Expression) $3, lexer.Location);
3699           }
3700         | relational_expression AS type_name
3701           {
3702                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
3703           }
3704         ;
3705
3706 equality_expression
3707         : relational_expression
3708         | equality_expression ASSIGN relational_expression
3709           {
3710                 $$ = new Binary (Binary.Operator.Equality,
3711                                  (Expression) $1, (Expression) $3, lexer.Location);
3712           }
3713         | equality_expression OP_NE relational_expression
3714           {
3715                 $$ = new Binary (Binary.Operator.Inequality, 
3716                                  (Expression) $1, (Expression) $3, lexer.Location);
3717           }       
3718         ;
3719
3720 and_expression
3721         : equality_expression
3722         | and_expression AND equality_expression
3723           {
3724                 $$ = new Binary (Binary.Operator.BitwiseAnd,
3725                                  (Expression) $1, (Expression) $3, lexer.Location);
3726           }
3727         ;
3728
3729 exclusive_or_expression
3730         : and_expression
3731         | exclusive_or_expression OP_XOR and_expression
3732           {
3733                 $$ = new Binary (Binary.Operator.ExclusiveOr,
3734                                  (Expression) $1, (Expression) $3, lexer.Location);
3735           }
3736         ;
3737
3738 conditional_and_expression
3739         : exclusive_or_expression
3740         | conditional_and_expression AND exclusive_or_expression
3741           {
3742                 $$ = new Binary (Binary.Operator.LogicalAnd,
3743                                  (Expression) $1, (Expression) $3, lexer.Location);
3744           }
3745         | conditional_and_expression ANDALSO exclusive_or_expression
3746           {     // FIXME: this is likely to be broken
3747                 $$ = new Binary (Binary.Operator.LogicalAnd,
3748                                  (Expression) $1, (Expression) $3, lexer.Location);
3749           }
3750         ;
3751
3752 conditional_or_expression
3753         : conditional_and_expression
3754         | conditional_or_expression OR conditional_and_expression
3755           {
3756                 $$ = new Binary (Binary.Operator.LogicalOr,
3757                                  (Expression) $1, (Expression) $3, lexer.Location);
3758           }
3759         | conditional_or_expression ORELSE conditional_and_expression
3760           {     // FIXME: this is likely to be broken
3761                 $$ = new Binary (Binary.Operator.LogicalOr,
3762                                  (Expression) $1, (Expression) $3, lexer.Location);
3763           }
3764         ;
3765
3766 conditional_expression
3767         : conditional_or_expression
3768         ;
3769
3770 assignment_expression
3771         : prefixed_unary_expression ASSIGN expression
3772           { 
3773                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3774           }
3775         | prefixed_unary_expression ASSIGN ADDRESSOF expression
3776           { 
3777                         // fixme: this is not working
3778                         // d = AddressOf F
3779                         // type of d has to  get resolved somewhere
3780                         //$$ = new New ((Expression) $1, (ArrayList) $4, lexer.Location);
3781                         $$ = new Assign ((Expression) $1, (Expression) $4, lexer.Location);
3782           }
3783         | prefixed_unary_expression OP_MULT_ASSIGN expression
3784           {
3785                 Location l = lexer.Location;
3786
3787                 $$ = new CompoundAssign (
3788                         Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
3789           }
3790         | prefixed_unary_expression OP_DIV_ASSIGN expression
3791           {
3792                 Location l = lexer.Location;
3793
3794                 $$ = new CompoundAssign (
3795                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3796           }
3797         | prefixed_unary_expression OP_IDIV_ASSIGN expression
3798           {
3799                 Location l = lexer.Location;
3800
3801                 $$ = new CompoundAssign (
3802                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3803           }       
3804         | prefixed_unary_expression OP_ADD_ASSIGN expression
3805           {
3806                 Location l = lexer.Location;
3807
3808                 $$ = new CompoundAssign (
3809                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3810           }
3811         | prefixed_unary_expression OP_SUB_ASSIGN expression
3812           {
3813                 Location l = lexer.Location;
3814
3815                 $$ = new CompoundAssign (
3816                         Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
3817           }
3818         | prefixed_unary_expression OP_CONCAT_ASSIGN expression
3819           {
3820                 Location l = lexer.Location;
3821
3822                 $$ = new CompoundAssign (
3823                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3824           }               
3825         ;
3826
3827 /*constant_expression
3828         : expression
3829         ;
3830 */
3831
3832 boolean_expression
3833         : expression
3834         ;
3835
3836 type
3837         : type_name {   /* class_type */
3838                 /*
3839                    This does interfaces, delegates, struct_types, class_types,
3840                    parent classes, and more! 4.2
3841                  */
3842                 $$ = DecomposeQI ((string) $1, lexer.Location); 
3843           }
3844         | builtin_types 
3845         /*| array_type 
3846          | pointer_type */
3847         ;
3848
3849 type_list
3850         : type
3851           {
3852                 ArrayList types = new ArrayList ();
3853
3854                 types.Add ($1);
3855                 $$ = types;
3856           }
3857         | type_list COMMA type
3858           {
3859                 ArrayList types = (ArrayList) $1;
3860
3861                 types.Add ($3);
3862                 $$ = types;
3863           }
3864         ;
3865
3866 type_name
3867         : namespace_or_type_name
3868         ;
3869         
3870 namespace_or_type_name
3871         : qualified_identifier
3872         ;
3873
3874 /* Built-in / Integral types */
3875 builtin_types
3876         : OBJECT        { $$ = TypeManager.system_object_expr; }
3877         | STRING        { $$ = TypeManager.system_string_expr; }
3878         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
3879         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
3880         | SINGLE        { $$ = TypeManager.system_single_expr; }
3881         | DOUBLE        { $$ = TypeManager.system_double_expr; }
3882         | DATE          { $$ = TypeManager.system_date_expr; }
3883         | integral_type
3884         ;
3885
3886 integral_type
3887         :
3888         | BYTE          { $$ = TypeManager.system_byte_expr; }
3889         | SHORT         { $$ = TypeManager.system_int16_expr; }
3890         | LONG          { $$ = TypeManager.system_int64_expr; }
3891         | INTEGER       { $$ = TypeManager.system_int32_expr; }
3892         | CHAR          { $$ = TypeManager.system_char_expr; }
3893         ;
3894
3895 interface_type
3896         : type_name
3897         ;
3898         
3899 end_of_stmt
3900         : EOL
3901         | COLON
3902         ;       
3903 %%
3904
3905
3906 Tokenizer lexer;
3907
3908 public Tokenizer Lexer {
3909         get {
3910                 return lexer;
3911         }
3912 }                  
3913
3914 public static Expression DecomposeQI (string name, Location loc)
3915 {
3916         Expression o;
3917
3918         if (name.IndexOf ('.') == -1){
3919                 return new SimpleName (name, loc);
3920         } else {
3921                 int pos = name.LastIndexOf (".");
3922                 string left = name.Substring (0, pos);
3923                 string right = name.Substring (pos + 1);
3924
3925                 o = DecomposeQI (left, loc);
3926
3927                 return new MemberAccess (o, right, loc);
3928         }
3929 }
3930
3931 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3932 {
3933         Block implicit_block;
3934         ArrayList inits = null;
3935
3936         //
3937         // We use the `Used' property to check whether statements
3938         // have been added to the current block.  If so, we need
3939         // to create another block to contain the new declaration
3940         // otherwise, as an optimization, we use the same block to
3941         // add the declaration.
3942         //
3943         // FIXME: A further optimization is to check if the statements
3944         // that were added were added as part of the initialization
3945         // below.  In which case, no other statements have been executed
3946         // and we might be able to reduce the number of blocks for
3947         // situations like this:
3948         //
3949         // int j = 1;  int k = j + 1;
3950         //
3951         
3952         VariableDeclaration.FixupTypes (variable_declarators);
3953         
3954         if (current_block.Used) {
3955                 implicit_block = new Block (current_block, true, loc, Location.Null);
3956                 implicit_block.AddChildVariableNames (current_block);
3957         } else
3958                 implicit_block = current_block;
3959
3960         foreach (VariableDeclaration decl in variable_declarators){
3961                 Expression type = decl.type;
3962                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3963                         if (decl.expression_or_array_initializer != null){
3964                                 if (inits == null)
3965                                         inits = new ArrayList ();
3966                                 inits.Add (decl);
3967                         }
3968                 }
3969         }
3970
3971         if (inits == null)
3972                 return implicit_block;
3973
3974         foreach (VariableDeclaration decl in inits){
3975                 Assign assign;
3976                 Expression expr;
3977                 Expression type = decl.type;
3978                 
3979                 if ((decl.expression_or_array_initializer is Expression) || 
3980                     (decl.expression_or_array_initializer is New)) {
3981                         expr = (Expression) decl.expression_or_array_initializer;
3982                 } else {
3983                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3984                         
3985                         expr = new ArrayCreation (type, "", init, decl.Location);
3986                 }
3987
3988                 LocalVariableReference var;
3989                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3990
3991                 assign = new Assign (var, expr, decl.Location);
3992
3993                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3994         }
3995         
3996         return implicit_block;
3997 }
3998
3999 Block declare_local_constant (Expression dummy_type, ArrayList variable_declarators)
4000 {
4001         Block implicit_block;
4002         VariableDeclaration.FixupTypes (variable_declarators);
4003
4004         if (current_block.Used)
4005                 implicit_block = new Block (current_block, true);
4006         else
4007                 implicit_block = current_block;
4008
4009         foreach (VariableDeclaration decl in variable_declarators){
4010                 Expression type = decl.type;
4011                 implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
4012                                           current_local_parameters, decl.Location);
4013         }
4014         
4015         return implicit_block;
4016 }
4017
4018 struct VarName {
4019                 public object Name;
4020                 public object Type;
4021                 public object Rank;
4022                                                                                 
4023                 public VarName (object n, object t, object r)
4024                 {
4025                         Name = n;
4026                         Type = t;
4027                         Rank = r;
4028                 }
4029         }
4030
4031
4032 // <summary>
4033 //   A class used to pass around variable declarations and constants
4034 // </summary>
4035 public class VariableDeclaration {
4036         public string identifier;
4037         public object expression_or_array_initializer;
4038         public Location Location;
4039         public Attributes OptAttributes;
4040         public Expression type;
4041         public ArrayList dims;
4042                 
4043         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
4044         {
4045                 this.identifier = id;
4046                 this.expression_or_array_initializer = eoai;
4047                 this.Location = l;
4048                 this.OptAttributes = opt_attrs;
4049                 this.type = t;
4050                 this.dims = null;
4051         }       
4052
4053         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
4054         {
4055         }
4056         
4057         public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
4058         {
4059         }       
4060         
4061         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
4062                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
4063         {
4064         }       
4065         
4066         public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
4067         {       
4068                 // FIXME : This is broken: only the first rank is parsed
4069                 return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
4070         }
4071         
4072         public static void FixupTypes (ArrayList vars)
4073         {
4074                 int varcount =  vars.Count;
4075                 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
4076                         
4077                 if (last_var.type == null)
4078                         last_var.type = TypeManager.system_object_expr;
4079                         
4080                 Expression cur_type = last_var.type;
4081                 int n = varcount - 1;
4082                 
4083                 while (n >= 0) {
4084                         VariableDeclaration var = (VariableDeclaration) vars[n--];
4085                         if (var.type == null)
4086                                 var.type = cur_type;
4087                         else
4088                                 cur_type = var.type;
4089                 }
4090         }
4091         
4092         public static bool IndexesSpecifiedInRank (ArrayList IndexList)
4093         {
4094                 bool res = false;
4095                 
4096                 if (IndexList != null) {
4097                         foreach (Expression e in IndexList)
4098                                 if (!(e is EmptyExpression)) {
4099                                         res = true;
4100                                         break;
4101                                 }       
4102                 }
4103                 return (res);
4104         }       
4105         
4106         
4107         public static bool IndexesSpecified (ArrayList ranks)
4108         {
4109                 bool res = false;
4110                 
4111                 if (ranks != null) {
4112                         foreach (ArrayList IndexList in ranks) {
4113                                 if (IndexesSpecifiedInRank (IndexList)) {
4114                                         res = true;
4115                                         break;
4116                                 }       
4117                         }       
4118                 }
4119                 return (res);
4120         }
4121         
4122         public static string StripDims (string varname, ref string d)
4123         {
4124                 string res = varname;
4125                 string dres = "";
4126                 
4127                 if (varname.IndexOf("[") >= 0) {
4128                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
4129                         res = varname.Substring(0, varname.IndexOf("["));
4130                 }
4131                 d = dres;
4132                 return (res);
4133         }       
4134         
4135         public static string StripDims (string varname)
4136         {
4137                 string dres = "";
4138                 
4139                 return (StripDims(varname, ref dres));
4140         }       
4141         
4142         public static string StripIndexesFromDims (string dims)
4143         {
4144                 StringBuilder sb = new StringBuilder();
4145
4146                 foreach (char c in dims) 
4147                         if (c == ',' || c == ']' || c == '[')
4148                                 sb.Append (c);
4149                                 
4150                 return sb.ToString();                           
4151         }
4152         
4153         public static string BuildRank (ArrayList rank)
4154         {
4155                 string res = "";
4156
4157                 res += "[";
4158                 for (int x = 0; x < (rank.Count -1 ); x++)
4159                         res += ",";
4160                         
4161                 res += "]";
4162                 return res;
4163         }
4164                 
4165         public static string BuildRanks (Parser t)
4166         {
4167                 string res = "";
4168
4169                 foreach (ArrayList rank in t.current_rank_specifiers)
4170                         res += BuildRank (rank);
4171
4172                 return res;
4173         }       
4174         
4175         public static void VBFixIndexList (ref ArrayList IndexList)
4176         {
4177                 if (IndexList != null) {
4178                         for (int x = 0; x < IndexList.Count; x++) {
4179                                 Expression e = (Expression) IndexList[x];
4180                                 if (!(e is EmptyExpression)) {
4181                                         IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
4182                                 }
4183                         }
4184                 }
4185         }               
4186         
4187         public static bool IsArrayDecl (Parser t)
4188         {
4189                 // return (varname.IndexOf("[") >= 0);
4190                 return (t.current_rank_specifiers != null);
4191         }                       
4192         
4193         public static void VBFixIndexLists (ref ArrayList ranks)
4194         {       
4195                 if (ranks != null) {
4196                         for (int x = 0; x < ranks.Count; x++) {
4197                                 ArrayList IndexList = (ArrayList) ranks[x];
4198                                 VBFixIndexList (ref IndexList);
4199                         }       
4200                 }       
4201         }
4202                 
4203         public static void FixupArrayTypes (ArrayList vars)
4204         {
4205                 int varcount =  vars.Count;
4206                 string dims;
4207                 
4208                 foreach (VariableDeclaration var in vars) {
4209                         if (var.identifier.EndsWith(",")) {
4210                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
4211                                                                 var.identifier.LastIndexOf(",")) + "]";
4212                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
4213                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
4214                         }
4215                 }
4216         }                               
4217 }
4218
4219
4220 public Property BuildSimpleProperty (Expression p_type, string name, 
4221                                         Field p_fld, int mod_flags,
4222                                         Attributes attrs, Location loc) 
4223 {
4224         Property p;
4225         Block get_block, set_block;
4226         Accessor acc_set, acc_get;
4227         StatementExpression a_set;
4228         Statement a_get;
4229         Parameter [] args;
4230         
4231         // Build SET Block
4232         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
4233         args  = new Parameter [1];
4234         args [0] = implicit_value_parameter;
4235                 
4236         Parameters set_params = new Parameters (args, null, loc);
4237         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
4238                             (Expression) new SimpleName("value", loc), loc), loc);
4239                             
4240         set_block = new Block (current_block, set_params, loc, Location.Null);
4241         set_block.AddStatement ((Statement) a_set);                                         
4242         acc_set = new Accessor (set_block, attrs);
4243         
4244         // Build GET Block
4245         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
4246         get_block = new Block (current_block, null, loc, Location.Null);
4247         get_block.AddStatement ((Statement) a_get);                                         
4248         acc_get = new Accessor (get_block, attrs);
4249                 
4250         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
4251         
4252         return (p);
4253 }
4254         
4255 void start_block () 
4256 {
4257         current_block = new Block (current_block, current_local_parameters,
4258                            lexer.Location, Location.Null);
4259
4260
4261 Block end_block ()
4262
4263         Block res;
4264         
4265         while (current_block.Implicit)
4266                 current_block = current_block.Parent;
4267
4268         res = current_block;
4269
4270         current_block.SetEndLocation (lexer.Location);
4271         current_block = current_block.Parent;
4272         
4273         return (res);
4274 }
4275
4276 private void AddHandler (Expression evt_definition, string handler_name)
4277 {
4278         AddHandler (current_block, evt_definition, handler_name);
4279 }
4280
4281 void CheckAttributeTarget (string a)
4282 {
4283         switch (a) {
4284
4285         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
4286                 return;
4287                 
4288         default :
4289                 Location l = lexer.Location;
4290                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
4291                 break;
4292         }
4293 }
4294
4295 private void AddHandler (Block b, Expression evt_id, string handler_name)
4296 {
4297         Location loc = lexer.Location;
4298         string evt_target = evt_id.ToString();
4299         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
4300         Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
4301         b.AddStatement (s);
4302 }
4303
4304 private void RaiseEvent (string evt_name, ArrayList args)
4305 {
4306         Location loc = lexer.Location;
4307         
4308         Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
4309         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); 
4310         current_block.AddStatement (s); 
4311 }
4312
4313 // FIXME: THIS DOES NOT WORK!!!
4314 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
4315 {
4316         Location loc = lexer.Location;
4317         ArrayList neh_args = new ArrayList();
4318         neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
4319         
4320         ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
4321         
4322         CompoundAssign ca = new CompoundAssign (
4323                         Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
4324                         
4325         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
4326         b.AddStatement (s);     
4327 }
4328
4329 // <summary>
4330 //  This method is used to get at the complete string representation of
4331 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
4332 //  This is necessary because local_variable_type admits primary_expression
4333 //  as the type of the variable. So we do some extra checking
4334 // </summary>
4335 string GetQualifiedIdentifier (Expression expr)
4336 {
4337         if (expr is SimpleName)
4338                 return ((SimpleName)expr).Name;
4339         else if (expr is MemberAccess)
4340                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4341         else 
4342                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4343         
4344 }
4345
4346 private void RemoveHandler (Expression evt_definition, string handler_name)
4347 {
4348         RemoveHandler (current_block, evt_definition, handler_name);
4349 }
4350
4351 private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s)
4352 {
4353         ConstructorInitializer ci = null;
4354         
4355         if (s.Count > 0) {
4356                 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4357                         Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4358                         
4359                         if (i.expr is BaseAccess) {
4360                                 BaseAccess ba = (BaseAccess) i.expr;
4361                                 if (ba.member == "New" || ba.member == ".ctor") {
4362                                         ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4363                                         s.RemoveAt(0);
4364                                 }
4365                         }
4366                         if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
4367                                 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location); 
4368                                 s.RemoveAt(0);
4369                         }
4370                 }
4371         }
4372         return ci;
4373 }
4374
4375 void Error_ExpectingTypeName (Location l, Expression expr)
4376 {
4377         if (expr is Invocation){
4378                 Report.Error (1002, l, "; expected");
4379         } else {
4380                 Report.Error (-1, l, "Invalid Type definition");
4381         }
4382 }
4383
4384 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4385         return true;
4386 }
4387
4388 private void ReportError9998()
4389 {
4390         Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4391 }
4392
4393 protected override int parse ()
4394 {
4395         RootContext.InitializeImports(ImportsList);
4396         current_namespace = new Namespace (null, RootContext.RootNamespace);
4397         current_container = RootContext.Tree.Types;
4398         current_container.Namespace = current_namespace;
4399         oob_stack = new Stack ();
4400         switch_stack = new Stack ();
4401         expr_stack = new Stack ();      
4402         tmp_blocks = new Stack(); 
4403         with_stack = new Stack();
4404         statement_stack = new Stack();  
4405
4406         UseExtendedSyntax = name.EndsWith(".mbs");
4407         OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4408         OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4409         OptionCompareBinary = InitialOptionCompareBinary;
4410
4411         lexer = new Tokenizer (input, name, defines);
4412         StringBuilder value = new StringBuilder ();
4413         try {
4414                 if (yacc_verbose_flag)
4415                         yyparse (lexer, new yydebug.yyDebugSimple ());
4416                 else
4417                         yyparse (lexer);
4418         } catch (Exception e) {
4419                 Report.Error (29999, lexer.Location, lexer.location + "\nParsing error in " + lexer.ref_name + "\n" + e.ToString());
4420         }
4421
4422         RootContext.VerifyImports();
4423
4424         return Report.Errors;
4425 }
4426
4427 /* end end end */
4428 }