2004-06-08 Umadevi S <sumadevi@novell.com>
[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                 
1120                         foreach (Property p in current_container.Properties) {
1121                                 if (p.Name == evt_target) {
1122                                         Location loc = lexer.Location;
1123
1124                                         Statement addhnd = (Statement) new AddHandler ((Expression) $6, 
1125                                                                                 DecomposeQI((string) $2, loc), 
1126                                                                                 DecomposeQI(evt_target, loc), loc);
1127
1128                                         current_container.AddEventHandler (addhnd);
1129                                         break;
1130                                 }
1131                         }                               
1132                 }       
1133           }       
1134         ;
1135         
1136 func_declaration
1137         : FUNCTION identifier opt_type_character
1138           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks opt_implement_clause EOL
1139           { 
1140                 current_local_parameters = (Parameters) $5;
1141                 member_location = lexer.Location;
1142                 start_block(); 
1143                                 
1144                 Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
1145
1146                 // Structure members are Public by default                      
1147                 if ((current_container is Struct) && (current_modifiers == 0))
1148                         current_modifiers = Modifiers.PUBLIC;                           
1149                 // Add local var declaration
1150                 // for return value
1151                 ArrayList retval = new ArrayList ();
1152                 retval.Add (new VariableDeclaration ((string) $2, (Expression) ftype, lexer.Location));
1153                 declare_local_variables ((Expression) ftype, retval, lexer.Location);
1154           }       
1155           opt_statement_list
1156           END FUNCTION EOL
1157           {
1158                 Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
1159
1160                 Method method = new Method ((Expression) ftype, (int) current_modifiers, (string) $2,
1161                                             (Parameters) current_local_parameters, (Attributes) current_attributes,/* (Attributes) currx ent_attributes,  */
1162                                             (Expression) $8, member_location);
1163                 method.Block = end_block();
1164                 $$ = method;
1165           }       
1166         ;               
1167
1168 struct_declaration
1169         : STRUCTURE identifier EOL
1170           opt_implement_clause
1171           {
1172                 Struct new_struct;
1173                 string full_struct_name = MakeName ((string) $2);
1174                 
1175                 // Module members are static by default, but structures *can't* be declared static
1176                 // so we must fix it, if mbas was the one actually responsible for this
1177                 // instead of triggering an error.
1178                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1179                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1180                         
1181                 new_struct = new Struct (current_container, full_struct_name, 
1182                                          (int) current_modifiers,
1183                                          (Attributes) current_attributes, lexer.Location);
1184                 current_container = new_struct;
1185                 current_container.Namespace = current_namespace;
1186                 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1187           }
1188           opt_struct_member_declarations
1189           {
1190                 Struct new_struct = (Struct) current_container;
1191
1192                 if ($4 != null)
1193                         new_struct.Bases = (ArrayList) $4;
1194
1195                 current_container = current_container.Parent;
1196                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1197                 $$ = new_struct;
1198           }
1199           END STRUCTURE EOL
1200         ;
1201         
1202 opt_struct_member_declarations
1203         : /* empty */
1204         | struct_member_declarations
1205         ;
1206
1207 struct_member_declarations
1208         : struct_member_declaration
1209         | struct_member_declarations struct_member_declaration
1210         ;
1211
1212 struct_member_declaration
1213         : opt_modifiers
1214           struct_member_declarator
1215         ;
1216         
1217 struct_member_declarator        
1218         : field_declaration
1219         | constant_declaration
1220         | constructor_declaration
1221         | method_declaration
1222           { 
1223                 Method method = (Method) $1;
1224                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
1225           }     
1226         | property_declaration
1227         | event_declaration
1228         | type_spec_declaration
1229
1230         /*
1231          * This is only included so we can flag error 575:
1232          * destructors only allowed on class types
1233          */
1234         //| destructor_declaration
1235         ;
1236         
1237 event_declaration
1238         : EVENT identifier AS type EOL
1239           {
1240                 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1241
1242                 Event e = new Event ((Expression) $4, var.identifier, 
1243                                      null, current_modifiers, null, null, 
1244                                      current_attributes, lexer.Location);
1245
1246                 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1247
1248           }
1249         | EVENT identifier opt_event_params EOL
1250           {
1251                 string delName = (string) $2;
1252                 delName = delName + "EventHandler";
1253             Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate 
1254                                                 (current_container, TypeManager.system_void_expr, 
1255                                              (int) current_modifiers, MakeName(delName), (Parameters) $3, 
1256                                              (Attributes) current_attributes, lexer.Location);
1257                                                   
1258                 del.Namespace = current_namespace;
1259                 CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location);
1260           
1261                 Event e = new Event (DecomposeQI (delName, lexer.Location),
1262                                          (string) $2, 
1263                                      null, current_modifiers, null, null, 
1264                                      current_attributes, lexer.Location);
1265
1266                 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1267           }
1268         ;
1269         
1270 opt_event_params
1271         : /* empty */   { $$ = Parameters.EmptyReadOnlyParameters; }
1272         | OPEN_PARENS CLOSE_PARENS      { $$ = Parameters.EmptyReadOnlyParameters; }
1273         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS    { $$ = $2; }
1274         ;
1275         
1276 enum_declaration
1277         : ENUM identifier opt_type_spec EOL
1278           opt_enum_member_declarations
1279           { 
1280                 Location enum_location = lexer.Location;
1281                 string full_name = MakeName ((string) $2);
1282                 Expression enum_type = ($3 == null) ? TypeManager.system_int32_expr : (Expression) $3;
1283                 ArrayList enum_members = (ArrayList) $5;
1284                 
1285                 // Module members are static by default, but enums *can't* be declared static
1286                 // so we must fix it if mbas was the one actually responsible for this
1287                 // instead of triggering an error.
1288                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1289                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1290                         
1291                 Mono.MonoBASIC.Enum e = new Mono.MonoBASIC.Enum (current_container, enum_type, 
1292                                         (int) current_modifiers, full_name, 
1293                                         (Attributes) current_attributes, enum_location);
1294                 
1295                 foreach (VariableDeclaration ev in enum_members) {
1296                         Location loc = (Location) ev.Location;
1297
1298                         CheckDef (e.AddEnumMember (ev.identifier, 
1299                                                    (Expression) ev.expression_or_array_initializer,
1300                                                    loc, ev.OptAttributes), ev.identifier, loc);
1301                 }
1302
1303                 e.Namespace = current_namespace;
1304
1305                 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1306                 RootContext.Tree.RecordDecl (full_name, e);
1307
1308           }
1309           END ENUM EOL
1310         ;
1311
1312 opt_enum_member_declarations
1313         : /* empty */                   { $$ = new ArrayList (); }
1314         | enum_member_declarations      { $$ = $1; }
1315         ;
1316
1317 enum_member_declarations
1318         : enum_member_declaration 
1319           {
1320                 ArrayList l = new ArrayList ();
1321
1322                 l.Add ($1);
1323                 $$ = l;
1324           }
1325         | enum_member_declarations  enum_member_declaration
1326           {
1327                 ArrayList l = (ArrayList) $1;
1328
1329                 l.Add ($2);
1330
1331                 $$ = l;
1332           }
1333         ;
1334
1335 enum_member_declaration
1336         : opt_attributes identifier EOL
1337           {
1338                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1339           }
1340         | opt_attributes identifier
1341           {
1342                   $$ = lexer.Location;
1343           }
1344           ASSIGN expression EOL
1345           { 
1346                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1347           }
1348         ;
1349                 
1350 interface_declaration
1351         : INTERFACE identifier EOL
1352           {
1353                 Interface new_interface;
1354                 string full_interface_name = MakeName ((string) $2);
1355
1356                 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1357                                                (Attributes) current_attributes, lexer.Location);
1358                 if (current_interface != null) {
1359                         Location l = lexer.Location;
1360                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
1361                 }
1362                 current_interface = new_interface;
1363                 new_interface.Namespace = current_namespace;
1364                 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1365           }
1366           opt_interface_base
1367           interface_body
1368           { 
1369                 Interface new_interface = (Interface) current_interface;
1370
1371                 if ($5 != null)
1372                         new_interface.Bases = (ArrayList) $5;
1373
1374                 current_interface = null;
1375                 CheckDef (current_container.AddInterface (new_interface),
1376                           new_interface.Name, new_interface.Location);
1377
1378           }
1379           END INTERFACE EOL
1380         ;
1381
1382 opt_interface_base
1383         : /* empty */                     { $$ = null; }
1384         | interface_base
1385         ;
1386
1387 interface_base
1388         : INHERITS interface_type_list    { $$ = $2; }
1389         ;
1390
1391 interface_type_list
1392         : interface_type
1393           {
1394                 ArrayList interfaces = new ArrayList ();
1395
1396                 interfaces.Add ($1);
1397                 $$ = interfaces;
1398           }
1399         | interface_type_list COMMA interface_type
1400           {
1401                 ArrayList interfaces = (ArrayList) $1;
1402                 interfaces.Add ($3);
1403                 $$ = interfaces;
1404           }
1405         ;
1406
1407 interface_body
1408         : opt_interface_member_declarations
1409         ;
1410
1411 opt_interface_member_declarations
1412         : /* empty */
1413         | interface_member_declarations
1414         ;
1415
1416 interface_member_declarations
1417         : interface_member_declaration
1418         | interface_member_declarations interface_member_declaration
1419         ;
1420
1421 interface_member_declaration
1422         : interface_method_declaration          
1423           { 
1424                 InterfaceMethod m = (InterfaceMethod) $1;
1425
1426                 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1427           }
1428         | interface_property_declaration        
1429           { 
1430                 InterfaceProperty p = (InterfaceProperty) $1;
1431                 
1432                 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1433           }
1434         | interface_event_declaration 
1435           { 
1436                 InterfaceEvent e = (InterfaceEvent) $1;
1437
1438                 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1439           }
1440         ;
1441
1442 opt_new
1443         : /* empty */   { $$ = false; }
1444         | NEW           { $$ = true; }
1445         ;
1446         
1447 interface_method_declaration
1448         : SUB identifier
1449           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1450           {
1451                 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1452                                           (Parameters) $4, current_attributes, lexer.Location);
1453           }
1454         | FUNCTION identifier opt_type_character
1455           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1456           {
1457                 if ($3 != null && $3 != $8)
1458                         Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1459                 
1460                 $$ = new InterfaceMethod (
1461                                           (Expression) $8, (string) $2, false, (Parameters) $5,
1462                                           current_attributes, lexer.Location);
1463           }
1464         | FUNCTION identifier type_character
1465           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1466           {
1467                 $$ = new InterfaceMethod (
1468                                           (Expression) $3, (string) $2, false, (Parameters) $5,
1469                                           current_attributes, lexer.Location);
1470           }
1471         ;
1472
1473 interface_property_declaration
1474         : opt_modifiers PROPERTY identifier
1475           OPEN_PARENS
1476           opt_formal_parameter_list
1477           CLOSE_PARENS opt_type_spec EOL
1478           {
1479                 // FIXME we MUST pass property parameters
1480                 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1481                                             true, true, current_attributes,
1482                                             lexer.Location);
1483           }
1484         ;
1485         
1486 interface_event_declaration
1487         : opt_attributes opt_new EVENT type identifier EOL
1488           {
1489                 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1490                                          lexer.Location);
1491           }
1492         ;
1493
1494  property_declaration
1495         : abstruct_propery_declaration
1496         | non_abstruct_propery_declaration 
1497         ;
1498         
1499 abstruct_propery_declaration
1500         : MUSTOVERRIDE PROPERTY identifier opt_type_character opt_property_parameters AS type EOL
1501           {     
1502                 Expression ftype = ($7 == null) ? (($4 == null) ? 
1503                                 TypeManager.system_object_expr : (Expression) $4 ) : (Expression) $7;
1504
1505                 if (current_container is Module)
1506                         Report.Error (30503, "Properties in a Module cannot be declared 'MustOverride'.");
1507                         
1508                 if (current_container is Struct)
1509                         Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1510                                 
1511                 current_modifiers |= Modifiers.ABSTRACT;
1512                 
1513                 current_local_parameters = (Parameters) $5;
1514                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
1515                         get_parameters = current_local_parameters.Copy (lexer.Location);
1516                         set_parameters = current_local_parameters.Copy (lexer.Location);
1517                 }
1518                 else
1519                 {
1520                         get_parameters = Parameters.EmptyReadOnlyParameters;
1521                         set_parameters = new Parameters (null, null ,lexer.Location); 
1522                         
1523                         Parameter implicit_value_parameter = new Parameter (
1524                                         ftype, "Value", Parameter.Modifier.NONE, null);
1525                         
1526                         set_parameters.AppendParameter (implicit_value_parameter);
1527                 }
1528                 lexer.PropertyParsing = true;
1529                 
1530                 Accessor get_block = new Accessor (null, null); 
1531                 Accessor set_block = new Accessor (null, null); 
1532                                 
1533                 Property prop = new Property ((Expression) ftype, (string) $3, current_modifiers, 
1534                                          get_block, set_block, current_attributes, lexer.Location,
1535                                          null, get_parameters, set_parameters, null);
1536     
1537                 if (!(current_container is Class))
1538                         Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1539                         
1540                 CheckDef (current_container.AddProperty (prop), prop.Name, lexer.Location);
1541                 
1542                 get_implicit_value_parameter_type = null;
1543                 set_implicit_value_parameter_type = null;
1544                 get_parameters = null;
1545                 set_parameters = null;
1546                 current_local_parameters = null;                                
1547           }     
1548         ;
1549         
1550         
1551  non_abstruct_propery_declaration
1552           : PROPERTY identifier opt_type_character opt_property_parameters AS type opt_implement_clause EOL
1553           {
1554                 get_implicit_value_parameter_type  = 
1555                         ($6 == null) ? (($3 == null) ? 
1556                                 TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $6;
1557                 get_implicit_value_parameter_name = (string) $2;
1558                 
1559                 current_local_parameters = (Parameters) $4;
1560                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
1561                         get_parameters = current_local_parameters.Copy (lexer.Location);
1562                         set_parameters = current_local_parameters.Copy (lexer.Location);
1563                 }
1564                 else
1565                 {
1566                         get_parameters = Parameters.EmptyReadOnlyParameters;
1567                         set_parameters = new Parameters (null, null ,lexer.Location);           
1568                 }
1569                 lexer.PropertyParsing = true;
1570
1571                 $$ = lexer.Location;
1572           }
1573           accessor_declarations 
1574           END PROPERTY EOL
1575           {
1576                 lexer.PropertyParsing = false;
1577
1578                 Property prop;
1579                 Pair pair = (Pair) $10;
1580                 
1581                 Accessor get_block = null;
1582                 Accessor set_block = null;
1583                 
1584                 if (pair.First != null){
1585                         get_block = (Accessor) pair.First;
1586                 }
1587                 
1588                 if (pair.Second != null) {
1589                         set_block = (Accessor) pair.Second;
1590                 }
1591                 
1592                 Location loc = lexer.Location;
1593                 
1594                 // Structure members are Public by default                      
1595                 if ((current_container is Struct) && (current_modifiers == 0))
1596                         current_modifiers = Modifiers.PUBLIC;                           
1597                         
1598                 prop = new Property ((Expression) /*$6*/ get_implicit_value_parameter_type, 
1599                                          (string) $2, current_modifiers, get_block, set_block,
1600                                      current_attributes, loc, set_implicit_value_parameter_name, 
1601                                      get_parameters, set_parameters, (Expression) $7);
1602                 
1603                 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1604                 get_implicit_value_parameter_type = null;
1605                 set_implicit_value_parameter_type = null;
1606                 get_parameters = null;
1607                 set_parameters = null;
1608                 current_local_parameters = null;
1609           }
1610         ;
1611
1612 opt_property_parameters
1613         : /* empty */
1614           {
1615                 $$ = Parameters.EmptyReadOnlyParameters;
1616           }
1617         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1618           {
1619                 $$ = $2;
1620           }
1621         ;
1622         
1623 opt_implement_clause
1624         : /* empty */
1625           {
1626                 $$ = null;
1627           }
1628         | IMPLEMENTS qualified_identifier
1629           {
1630                 $$ = DecomposeQI ((string)$2, lexer.Location);
1631           }     
1632         ;
1633         
1634 accessor_declarations
1635         : get_accessor_declaration opt_set_accessor_declaration
1636           { 
1637                 $$ = new Pair ($1, $2);
1638           }
1639         | set_accessor_declaration opt_get_accessor_declaration
1640           {
1641                 $$ = new Pair ($2, $1);
1642           }
1643         ;
1644
1645 opt_get_accessor_declaration
1646         : /* empty */                   { $$ = null; }
1647         | get_accessor_declaration
1648         ;
1649
1650 opt_set_accessor_declaration
1651         : /* empty */                   { $$ = null; }
1652         | set_accessor_declaration
1653         ;
1654
1655 get_accessor_declaration
1656         : opt_attributes GET EOL
1657           {
1658                 if ((current_modifiers & Modifiers.WRITEONLY) != 0)
1659                         Report.Error (30023, "'WriteOnly' properties cannot have a 'Get' accessor");
1660           
1661                 current_local_parameters = get_parameters;
1662                 
1663                 lexer.PropertyParsing = false;
1664                 
1665                 start_block();  
1666                 // Add local var declaration
1667                 // for return value
1668                 ArrayList retval = new ArrayList ();
1669                 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1670                 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);    
1671           }
1672           opt_statement_list
1673           END GET EOL
1674           {
1675                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1676                 current_local_parameters = null;
1677                 lexer.PropertyParsing = true;
1678           }
1679         ;
1680
1681 set_accessor_declaration
1682         : opt_attributes SET opt_set_parameter EOL
1683           {
1684         if ((current_modifiers & Modifiers.READONLY) != 0)
1685                         Report.Error (30022, "'ReadOnly' properties cannot have a 'Set' accessor");
1686                         
1687                 Parameter implicit_value_parameter = new Parameter (
1688                         set_implicit_value_parameter_type, 
1689                         set_implicit_value_parameter_name, 
1690                         Parameter.Modifier.NONE, null);
1691
1692                 current_local_parameters = set_parameters;
1693                 current_local_parameters.AppendParameter (implicit_value_parameter);
1694                 
1695                 start_block();
1696                 lexer.PropertyParsing = false;
1697           }
1698           opt_statement_list
1699           END SET EOL
1700           {
1701                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1702                 current_local_parameters = null;
1703                 lexer.PropertyParsing = true;
1704           }
1705         ;
1706                 
1707 opt_set_parameter
1708         : /* empty */
1709         {
1710                 set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; // TypeManager.system_object_expr;
1711                 set_implicit_value_parameter_name = "Value";
1712         }       
1713         |OPEN_PARENS CLOSE_PARENS
1714         {
1715                 set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type;
1716                 set_implicit_value_parameter_name = "Value";
1717         }       
1718         | OPEN_PARENS opt_parameter_modifier opt_identifier opt_type_spec CLOSE_PARENS
1719         {
1720                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1721                 if ((pm | Parameter.Modifier.VAL) != 0)
1722                         Report.Error (31065, 
1723                                 lexer.Location, 
1724                                 "Set cannot have a paremeter modifier other than 'ByVal'");
1725                                 
1726                 set_implicit_value_parameter_type = (Expression) $4;
1727                 
1728                 if (set_implicit_value_parameter_type != get_implicit_value_parameter_type)
1729                         Report.Error (31064, 
1730                                 lexer.Location, 
1731                                 "Set value parameter type can not be different from property type");
1732                 
1733                 if ($2 != null)
1734                         set_implicit_value_parameter_name = (string) $3;
1735                 else
1736                         set_implicit_value_parameter_name = "Value";
1737         }
1738         ;
1739                         
1740 field_declaration
1741         : opt_dim_stmt 
1742           variable_declarators EOL
1743           {               
1744                 int mod = (int) current_modifiers;
1745                 
1746
1747                 VariableDeclaration.FixupTypes ((ArrayList) $2);
1748                 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1749                 
1750                 if (current_container is Module)
1751                         mod = mod | Modifiers.STATIC;
1752                         
1753                 // Structure members are Public by default                      
1754                 if ((current_container is Struct) && (mod == 0))
1755                         mod = Modifiers.PUBLIC;                 
1756                 
1757                 if ((mod & Modifiers.Accessibility) == 0)
1758                         mod |= Modifiers.PRIVATE;
1759                                         
1760                 foreach (VariableDeclaration var in (ArrayList) $2){
1761                         Location l = var.Location;
1762                         Field field = new Field (var.type, mod, var.identifier, 
1763                                                  var.expression_or_array_initializer, 
1764                                                  (Attributes) null, l);
1765
1766                         CheckDef (current_container.AddField (field), field.Name, l);
1767                 }
1768           }
1769         ;
1770         
1771 withevents_declaration
1772         : opt_dim_stmt WITHEVENTS variable_declarators EOL
1773           {
1774                 // Module members are static by default, but delegates *can't* be declared static
1775                 // so we must fix it, if mbas was the one actually responsible for this
1776                 // instead of triggering an error.
1777                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1778                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1779           
1780                 /* WithEvents Fields must be resolved into properties
1781                    with a bit of magic behind the scenes */
1782                   
1783                 VariableDeclaration.FixupTypes ((ArrayList) $3);
1784                 
1785                 foreach (VariableDeclaration var in (ArrayList) $3) {
1786                         // 1 - We create a private field
1787                         Location l = var.Location;
1788                         Property prop;
1789                         if ((current_modifiers & Modifiers.STATIC) > 0) 
1790                                 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1791                         
1792                         Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, 
1793                                                  var.expression_or_array_initializer, 
1794                                                  (Attributes) null, l);
1795                                                  
1796                         CheckDef (current_container.AddField (field), field.Name, l);   
1797                         
1798                         // 2 - Public property
1799                                 
1800                         prop = BuildSimpleProperty (var.type, (string) var.identifier, 
1801                                                 field, (int) current_modifiers, 
1802                                                 (Attributes) current_attributes, l);
1803                         
1804                         CheckDef (current_container.AddProperty (prop), prop.Name, l);
1805                 }               
1806           }
1807         ;
1808         
1809 opt_dim_stmt 
1810         : /* empty */
1811         | DIM
1812         ; 
1813                 
1814 delegate_declaration
1815         : DELEGATE SUB  
1816           identifier OPEN_PARENS 
1817           opt_formal_parameter_list
1818           CLOSE_PARENS 
1819           EOL
1820           {
1821                 Location l = lexer.Location;
1822                 // Module members are static by default, but delegates *can't* be declared static
1823                 // so we must fix it, if mbas was the one actually responsible for this
1824                 // instead of triggering an error.
1825                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1826                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1827                                         
1828                 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (current_container, 
1829                                                  TypeManager.system_void_expr, 
1830                                              (int) current_modifiers, 
1831                                  MakeName ((string) $3), (Parameters) $5, 
1832                                              (Attributes) current_attributes, l);
1833                                                   
1834                 del.Namespace = current_namespace;
1835                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1836           }     
1837         | DELEGATE FUNCTION       
1838           identifier OPEN_PARENS 
1839           opt_formal_parameter_list
1840           CLOSE_PARENS AS type EOL
1841           {
1842                 Location l = lexer.Location;
1843                 
1844                 // Module members are static by default, but delegates *can't* be declared static
1845                 // so we must fix it, if mbas was the one actually responsible for this
1846                 // instead of triggering an error.
1847                 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1848                         current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1849                         
1850                 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (
1851                         current_container,
1852                         (Expression) $8, (int) current_modifiers, MakeName ((string) $3), 
1853                         (Parameters) $5, (Attributes) current_attributes, l);
1854
1855                 del.Namespace = current_namespace;
1856                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1857           }
1858         ;
1859         
1860 opt_evt_handler
1861         : /* empty */
1862           {     $$ = null; }
1863         | HANDLES qualified_identifier
1864           {
1865                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
1866           }
1867         | HANDLES MYBASE DOT qualified_identifier
1868           {
1869                 // FIXME: this is blatantly wrong and crash-prone
1870                 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
1871           }
1872         ;       
1873
1874 opt_empty_parens
1875         : /* empty */
1876         | OPEN_PARENS CLOSE_PARENS
1877         ;       
1878
1879 constructor_declaration
1880         : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1881           {
1882                 current_local_parameters = (Parameters) $4;
1883                 start_block();
1884                 oob_stack.Push (lexer.Location);
1885
1886                 Location l = (Location) oob_stack.Pop ();
1887                 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1888                 $1 = $$;
1889           }
1890           opt_statement_list
1891           { 
1892                 Constructor c = (Constructor) $1;
1893                 c.Block = (Block) end_block();
1894                 c.ModFlags = (int) current_modifiers;
1895                 c.OptAttributes = current_attributes;
1896                 
1897                 c.Initializer = CheckConstructorInitializer (ref c.Block.statements);
1898
1899                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1900                 current_local_parameters = null;
1901           }
1902           END SUB EOL
1903         ;
1904         
1905 opt_formal_parameter_list
1906         : /* empty */                   
1907           { 
1908                 $$ = Parameters.EmptyReadOnlyParameters; 
1909           }
1910         | formal_parameter_list 
1911           { 
1912                 $$ = $1;        
1913                 //Parameter p = ((Parameters) $1).FixedParameters[0];
1914           }
1915         ;
1916         
1917 formal_parameter_list
1918         : fixed_parameters              
1919           { 
1920                 ArrayList pars_list = (ArrayList) $1;
1921
1922                 Parameter [] pars = new Parameter [pars_list.Count];
1923                 pars_list.CopyTo (pars);
1924                 $$ = new Parameters (pars, null, lexer.Location); 
1925           } 
1926         | fixed_parameters COMMA parameter_array
1927           {
1928                 ArrayList pars_list = (ArrayList) $1;
1929
1930                 Parameter [] pars = new Parameter [pars_list.Count];
1931                 pars_list.CopyTo (pars);
1932
1933                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1934           }
1935         | parameter_array 
1936           {
1937                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1938           }
1939         ;
1940
1941 fixed_parameters
1942         : fixed_parameter       
1943           {
1944                 ArrayList pars = new ArrayList ();
1945
1946                 pars.Add ($1);
1947                 $$ = pars;
1948           }
1949         | fixed_parameters COMMA fixed_parameter
1950           {
1951                 ArrayList pars = (ArrayList) $1;
1952
1953                 pars.Add ($3);
1954                 $$ = $1;
1955           }
1956         ;
1957
1958 fixed_parameter
1959         : opt_attributes
1960           opt_parameter_modifier
1961           identifier opt_type_character opt_rank_specifiers opt_type_spec opt_variable_initializer
1962           {
1963                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1964                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1965                 Expression ptype;
1966                 
1967                 if (opt_parm && ($7 == null))
1968                         Report.Error (999, "Optional parameters must have a default value");
1969                 
1970                 if (opt_parm) {
1971                         if ((pm & Parameter.Modifier.REF) !=0)
1972                                 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1973                         else
1974                                 pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
1975                 }       
1976                 
1977                 if ($4 != null && $6 != null && $4 != $6)
1978                         Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1979
1980                 ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6);
1981                 if ($5 != null) {
1982                         string t = ptype.ToString() + VariableDeclaration.BuildRank ((ArrayList) $5);
1983                         ptype = DecomposeQI (t, lexer.Location);
1984                 }                       
1985                 $$ = new Parameter (ptype, (string) $3, pm,
1986                                         (Attributes) $1, (Expression) $7, opt_parm);
1987           }
1988         ;
1989         
1990 parameter_array
1991         : PARAM_ARRAY identifier opt_parens AS type 
1992           { 
1993                 string s_patype = ((Expression) $5).ToString();
1994                 if ((bool) $3)
1995                         s_patype += "[]";
1996                         
1997                 Expression patype = DecomposeQI (s_patype, Location.Null);
1998                 $$ = new Parameter (patype, (string) $2, Parameter.Modifier.PARAMS, null);
1999                 // note  ("type must be a single-dimension array type"); 
2000           }
2001         ;
2002                 
2003 opt_parens
2004         : /* empty */
2005           {     $$ = false;     }
2006         | OPEN_PARENS CLOSE_PARENS
2007           {     $$ = true;      }
2008         ;
2009         
2010 opt_parameter_modifier
2011         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
2012         | parameter_modifiers   { $$ = $1;                      }
2013         ;
2014
2015 parameter_modifiers
2016         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
2017         | parameter_modifier                            { $$ = $1;      }
2018         ;
2019         
2020 parameter_modifier
2021         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
2022         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
2023         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
2024         ;       
2025
2026 opt_statement_list
2027         : /* empty */
2028         | statement_list end_of_stmt
2029         ;
2030
2031 statement_list
2032         : statement 
2033         | statement_list end_of_stmt statement
2034         ;
2035         
2036 statement : 
2037             declaration_statement
2038             {
2039                 if ($1 != null && (Block) $1 != current_block){
2040                         current_block.AddStatement ((Statement) $1);
2041                         current_block = (Block) $1;
2042                 }
2043             }
2044           | embedded_statement
2045             {
2046                 Statement s = (Statement) $1;
2047
2048                 current_block.AddStatement ((Statement) $1);
2049             } 
2050           | labeled_statement 
2051           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
2052            {
2053                 AddHandler ((Expression) $2, (string) $5);
2054            }
2055           | RAISEEVENT identifier opt_raise_event_args  //OPEN_PARENS opt_argument_list CLOSE_PARENS
2056             {
2057                 RaiseEvent ((string) $2, (ArrayList) $3);
2058             }
2059           /* | array_handling_statement */
2060           /* | empty_statement */
2061           | with_statement 
2062             {
2063                 Statement s = (Statement) $1;
2064
2065                 current_block.AddStatement ((Statement) $1);
2066             }     
2067           ;     
2068           
2069 opt_raise_event_args 
2070         : /* empty */   { $$ = null; }
2071         | OPEN_PARENS opt_argument_list CLOSE_PARENS
2072           {
2073                 $$ = $2;
2074           }
2075         ;
2076
2077 labeled_statement
2078         : identifier COLON end_of_stmt 
2079           {
2080                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
2081
2082                 if (!current_block.AddLabel ((string) $1, labeled)){
2083                         Location l = lexer.Location;
2084                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2085                 }       
2086                 current_block.AddStatement (labeled);
2087           }
2088           statement
2089         ;
2090
2091 embedded_statement
2092         : expression_statement
2093         | selection_statement
2094         | iteration_statement
2095         | try_statement
2096         | jump_statement
2097         | array_handling_statement 
2098         ;
2099 /*        
2100 empty_statement
2101         : end_of_stmt
2102           {
2103                   $$ = new EmptyStatement ();
2104           }
2105         ;        
2106 */
2107
2108 with_statement
2109         : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */
2110           {
2111                 // was : Expression e = DecomposeQI ((string) $2, lexer.Location);
2112                 Expression e = (Expression) $2;
2113                 with_stack.Push(e);
2114                 start_block();
2115           }
2116           opt_statement_list
2117           END WITH
2118           {
2119                 Block b = end_block();
2120                 with_stack.Pop();
2121                 $$ = b;
2122           }
2123         ;
2124         
2125         
2126 array_handling_statement
2127         : redim_statement
2128         | erase_statement
2129         ;
2130         
2131 redim_statement
2132         : REDIM opt_preserve redim_clauses
2133           {
2134                 ArrayList list = (ArrayList) $3;
2135                 ReDim r = new ReDim (list, (bool) $2, lexer.Location);
2136                 $$ = r;
2137
2138           }
2139         ;
2140         
2141 opt_preserve
2142         : /* empty */   { $$ = false; }
2143         | PRESERVE      { $$ = true;  }
2144         ;
2145         
2146 redim_clauses
2147         : redim_clause
2148           {
2149                 ArrayList clauses = new ArrayList ();
2150
2151                 clauses.Add ($1);
2152                 $$ = clauses;
2153           }
2154         | redim_clauses COMMA redim_clause
2155           {
2156                 ArrayList clauses = (ArrayList) ($1);
2157                 clauses.Add ($2);
2158
2159                 $$ = clauses;
2160           }
2161         ;
2162
2163 redim_clause
2164         : invocation_expression
2165           {
2166                 Invocation i = (Invocation) $1;
2167                 RedimClause rc = new RedimClause (i.expr, i.Arguments);
2168                 $$ = rc;
2169           }
2170         ;
2171
2172 erase_statement
2173         : ERASE erase_clauses
2174         {
2175                 ArrayList list = (ArrayList) $2;
2176                 foreach(Expression e in list)
2177                 {
2178                         Erase r = new Erase (e, lexer.Location);
2179                         $$ = r;
2180                 }
2181         }
2182         ;
2183
2184 erase_clauses
2185         : erase_clause
2186           {
2187                 ArrayList clauses = new ArrayList ();
2188
2189                 clauses.Add ($1);
2190                 $$ = clauses;
2191           }
2192         | erase_clauses COMMA erase_clause
2193           {
2194                 ArrayList clauses = (ArrayList) ($1);
2195                 clauses.Add ($2);
2196
2197                 $$ = clauses;
2198           }
2199         ;
2200
2201 erase_clause
2202         : primary_expression
2203         ;       
2204                         
2205 jump_statement
2206         : /*break_statement
2207         | continue_statement
2208         | */return_statement
2209         | goto_statement        
2210         | throw_statement       
2211         | exit_statement
2212         | yield_statement
2213         ;
2214                 
2215 goto_statement
2216         : GOTO identifier  
2217           {
2218                 $$ = new Goto (current_block, (string) $2, lexer.Location);
2219           }
2220         ;
2221         
2222 throw_statement
2223         : THROW opt_expression
2224           {
2225                 $$ = new Throw ((Expression) $2, lexer.Location);
2226           }
2227         ;       
2228                         
2229 exit_statement
2230         : EXIT exit_type
2231           {
2232                 $$ = new Exit ((ExitType)$2, lexer.Location);           
2233           }
2234         ;
2235         
2236 exit_type
2237         : DO            { $$ = ExitType.DO;             }
2238         | FOR           { $$ = ExitType.FOR;            }
2239         | WHILE         { $$ = ExitType.WHILE;          }
2240         | SELECT        { $$ = ExitType.SELECT;         }
2241         | SUB           { $$ = ExitType.SUB;            }
2242         | FUNCTION      { $$ = ExitType.FUNCTION;       }
2243         | PROPERTY      { $$ = ExitType.PROPERTY;       }
2244         | TRY           { $$ = ExitType.TRY;            }
2245         ;
2246 return_statement
2247         : RETURN opt_expression 
2248           {       
2249                 $$ = new Return ((Expression) $2, lexer.Location);
2250           }
2251         ;
2252                 
2253 iteration_statement
2254         : while_statement
2255         | do_statement
2256         | for_statement
2257         | foreach_statement
2258         ;
2259
2260 foreach_statement
2261         : FOR EACH identifier IN 
2262           {
2263                 oob_stack.Push (lexer.Location);
2264           }       
2265           expression end_of_stmt
2266           {
2267                 
2268                 start_block();
2269                 Block foreach_block = current_block;
2270                 Location l = lexer.Location;            
2271                 LocalVariableReference v = null;
2272                 VariableInfo vi;
2273
2274                 vi = foreach_block.GetVariableInfo ((string) $3);
2275                 if (vi != null) {
2276                         // Get a reference to this variable.
2277                         v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2278                 }
2279                 else
2280                         Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2281         
2282                 oob_stack.Push (v);
2283           }       
2284           opt_statement_list
2285           NEXT opt_identifier
2286           {
2287                 Block foreach_block = current_block;
2288                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2289                 Block prev_block = end_block();
2290                 Location l = (Location) oob_stack.Pop ();
2291
2292                 Foreach f = null;
2293                 if (v != null) {
2294                         f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
2295                 }
2296                 
2297                 $$ = f;
2298           }       
2299         ;
2300
2301 yield_statement 
2302         : YIELD expression
2303           {
2304                 if (!UseExtendedSyntax)
2305                 {
2306                         ReportError9998();
2307                         $$ = null;
2308                 }
2309 /*              else
2310                         if (iterator_container == null){
2311                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2312                                 $$ = null;
2313                         } else {
2314                                 iterator_container.SetYields ();
2315                                 $$ = new Yield ((Expression) $2, lexer.Location);
2316                         } */
2317           }
2318         | YIELD STOP
2319           {
2320                 if (!UseExtendedSyntax)
2321                 {
2322                         ReportError9998();
2323                         $$ = null;
2324                 }
2325 /*              else
2326                         if (iterator_container == null){
2327                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2328                                 $$ = null;
2329                         } else {
2330                                 iterator_container.SetYields ();
2331                                 $$ = new YieldBreak (lexer.Location);
2332                         } */
2333           }
2334         ;
2335
2336
2337
2338 try_statement
2339         : try_catch
2340         | try_catch_finally
2341         ;
2342                                 
2343 try_header
2344         : TRY end_of_stmt
2345           {   
2346                 start_block();  
2347           }
2348           opt_statement_list 
2349           opt_catch_clauses
2350           {
2351                 tmp_catch_clauses = (ArrayList) $5;
2352           }
2353         ;
2354                                         
2355 try_catch
2356         : try_header 
2357           END TRY
2358           { 
2359                 Catch g = null;
2360                 ArrayList s = new ArrayList ();
2361
2362                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2363                         if (cc.IsGeneral)
2364                                 g = cc;
2365                         else
2366                                 s.Add (cc);
2367                 }
2368
2369                 // Now s contains the list of specific catch clauses
2370                 // and g contains the general one.
2371                 Block b = end_block();
2372
2373                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2374           }       
2375         ;       
2376           
2377 try_catch_finally
2378         : try_header 
2379           { 
2380                 tmp_block = end_block(); 
2381           }     
2382           FINALLY end_of_stmt
2383           { 
2384                 start_block(); 
2385           }       
2386           opt_statement_list 
2387           END TRY
2388           {
2389                 Catch g = null;
2390                 ArrayList s = new ArrayList ();
2391                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2392
2393                 if (catch_list != null){
2394                         foreach (Catch cc in catch_list) {
2395                                 if (cc.IsGeneral)
2396                                         g = cc;
2397                                 else
2398                                         s.Add (cc);
2399                         }
2400                 }
2401
2402                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2403         
2404           }     
2405           ;             
2406
2407 opt_catch_clauses
2408         : /* empty */  {  $$ = null;  }
2409         | catch_clauses
2410         ;
2411
2412 catch_clauses
2413         : catch_clause 
2414           {
2415                 ArrayList l = new ArrayList ();
2416
2417                 l.Add ($1);
2418                 $$ = l;
2419           }
2420         | catch_clauses catch_clause
2421           {
2422                 ArrayList l = (ArrayList) $1;
2423
2424                 l.Add ($2);
2425                 $$ = l;
2426           }
2427         ;
2428
2429 opt_identifier
2430         : /* empty */   {  $$ = null;  }
2431         | identifier
2432         ;
2433
2434 catch_clause 
2435         : CATCH opt_catch_args end_of_stmt
2436         {
2437                 Expression type = null;
2438                 string id = null;
2439                 
2440                 if ($2 != null) {
2441                         DictionaryEntry cc = (DictionaryEntry) $2;
2442                         type = (Expression) cc.Key;
2443                         id   = (string) cc.Value;
2444                         
2445                         if (id != null){
2446                                 ArrayList one = new ArrayList ();
2447                                 Location loc = lexer.Location;
2448
2449                                 one.Add (new VariableDeclaration (id, type, loc));
2450
2451
2452                                 $1 = current_block;
2453                                 current_block = new Block (current_block);
2454                                 Block b = declare_local_variables (type, one, loc);
2455                                 current_block = b;
2456                         }
2457                 }
2458         
2459         } 
2460         opt_statement_list {
2461                 Expression type = null;
2462                 string id = null;
2463                 Block b_catch = current_block;
2464                 
2465                 if ($2 != null){
2466                         DictionaryEntry cc = (DictionaryEntry) $2;
2467                         type = (Expression) cc.Key;
2468                         id   = (string) cc.Value;
2469                         
2470                         if ($1 != null) {
2471                                 //
2472                                 // FIXME: I can change this for an assignment.
2473                                 //
2474                                 while (current_block != (Block) $1)
2475                                         current_block = current_block.Parent;
2476                         }
2477                 }
2478
2479                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2480         }
2481         ;
2482
2483 opt_catch_args
2484         : /* empty */ {  $$ = null; }
2485         | catch_args
2486         ;         
2487
2488 catch_args 
2489         : identifier AS type
2490         {
2491                  $$ = new DictionaryEntry ($3, $1); 
2492         }
2493         ;
2494         
2495         
2496 do_statement
2497         : DO opt_do_construct end_of_stmt
2498           {
2499                 start_block();
2500                 oob_stack.Push (lexer.Location);
2501           }     
2502           opt_statement_list
2503           LOOP opt_do_construct
2504           {
2505                 Expression t_before = (Expression) $2;
2506                 Expression t_after = (Expression) $7;
2507                 Expression t;
2508
2509                 if  ((t_before != null) && (t_after != null))
2510                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2511
2512                 if ((t_before == null) && (t_after == null))
2513                         t = new BoolLiteral (true);
2514                 else
2515                         t = (t_before != null) ? t_before : t_after;
2516                         
2517                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2518                 
2519                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2520                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2521                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2522                          
2523                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2524           }
2525           ;
2526
2527 opt_do_construct
2528         : /* empty */ { $$ = null; }
2529         | while_or_until boolean_expression
2530           {
2531                 do_type = (DoOptions)$1;
2532                 $$ = (Expression) $2;
2533           }
2534         ;
2535
2536 while_or_until
2537         : WHILE { $$ = DoOptions.WHILE; }
2538         | UNTIL { $$ = DoOptions.UNTIL; }
2539         ;
2540
2541 while_statement
2542         : WHILE
2543         {
2544                 start_block();
2545                 oob_stack.Push (lexer.Location);
2546         }
2547         boolean_expression end_of_stmt
2548         opt_statement_list
2549         END WHILE
2550         {
2551                 Location l = (Location) oob_stack.Pop ();
2552                 Block b = end_block();
2553                 Expression e = (Expression) $3;
2554                 $$ = new While ((Expression) e, (Statement) b, l);
2555         }
2556         ;
2557         
2558                 
2559 for_statement
2560         : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2561           {
2562                 start_block();
2563           }
2564           opt_statement_list
2565           NEXT opt_identifier 
2566           {
2567                 Block statement = end_block();
2568                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2569                 
2570                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2571                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
2572                                                 for_var, (Expression) $6, lexer.Location);
2573                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2574                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
2575                                  
2576                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
2577                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2578                 
2579                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
2580           }       
2581         ;
2582
2583 opt_step
2584         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
2585         | STEP expression       { $$ = $2; }
2586         ;
2587
2588 selection_statement
2589         : if_statement
2590         | select_statement
2591         ;
2592
2593 if_statement
2594         : if_statement_open opt_then if_statement_rest
2595           {
2596                 $$ = $3;
2597           }
2598         | if_statement_open THEN pre_embedded_statement
2599           {
2600                 Location l = (Location) oob_stack.Pop ();
2601                 tmp_expr = (Expression)expr_stack.Pop(); 
2602                 $$ = new If ((Expression) tmp_expr, end_block(), l);
2603           }
2604         ;
2605
2606 pre_embedded_statement
2607         : embedded_statement 
2608           {
2609                 Statement s = (Statement) $1;
2610
2611                 current_block.AddStatement ((Statement) $1);
2612           } 
2613         ;       
2614         
2615 if_statement_open
2616         : IF boolean_expression 
2617           {
2618                 oob_stack.Push (lexer.Location);
2619                 start_block();
2620                 tmp_expr = (Expression) $2;
2621                 expr_stack.Push(tmp_expr);
2622           }
2623          ;
2624
2625 opt_then
2626         : /* empty */
2627         | THEN
2628         ;
2629         
2630 if_statement_rest
2631         : end_of_stmt
2632           opt_statement_list
2633           END IF
2634           { 
2635                 Location l = (Location) oob_stack.Pop ();
2636                 Expression expr = (Expression)expr_stack.Pop(); 
2637                 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2638           }       
2639         | end_of_stmt
2640           opt_statement_list
2641           ELSE end_of_stmt 
2642           { 
2643                 Block bl = end_block(); 
2644                 tmp_blocks.Push(bl); 
2645                 start_block();
2646           }
2647           opt_statement_list
2648           END IF        
2649           {
2650                 Location l = (Location) oob_stack.Pop ();
2651                 tmp_expr = (Expression)expr_stack.Pop(); 
2652                 tmp_block = (Block) tmp_blocks.Pop(); 
2653                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2654           }     
2655         | end_of_stmt
2656           opt_statement_list 
2657           ELSEIF boolean_expression opt_then 
2658           { 
2659                 tmp_expr = (Expression) $4;                                                  
2660                 expr_stack.Push(tmp_expr);                                                 
2661                 tmp_block = end_block();
2662                 tmp_blocks.Push(tmp_block);
2663                 start_block();
2664           }
2665           else_if_statement_rest 
2666           {
2667                 Statement stmt = (Statement) statement_stack.Pop();
2668                 Block bl = (Block) tmp_blocks.Pop();  
2669                 Expression expr =  (Expression)expr_stack.Pop();  
2670                 Location l = (Location) oob_stack.Pop ();
2671                 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l); 
2672           }
2673         ;
2674         
2675         
2676 else_if_statement_rest
2677         : end_of_stmt
2678           opt_statement_list 
2679           END IF
2680           { 
2681                 Location l = (Location) oob_stack.Pop ();
2682                 oob_stack.Push (l);
2683                 Expression expr = (Expression)expr_stack.Pop(); 
2684                 Statement stmt = (Statement) new If ((Expression) expr, (Statement)  end_block(), l);
2685                 statement_stack.Push(stmt);
2686           }
2687         | end_of_stmt
2688           opt_statement_list
2689           ELSE end_of_stmt 
2690           { 
2691                 Block bl = end_block();
2692                 tmp_blocks.Push(bl);
2693                 start_block();
2694           }
2695           opt_statement_list
2696           END IF        
2697           {
2698                 Location l = (Location) oob_stack.Pop ();
2699                 oob_stack.Push (l);
2700                 Expression expr = (Expression)expr_stack.Pop(); 
2701                 Block bl = (Block)tmp_blocks.Pop(); 
2702                 Statement stmt = (Statement) new If ((Expression) expr,  (Statement) bl , (Statement)  end_block(), l);
2703                 statement_stack.Push(stmt);
2704           }     
2705         | end_of_stmt
2706           opt_statement_list 
2707           ELSEIF boolean_expression opt_then 
2708           { 
2709                 expr_stack.Push((Expression) $4);                                                 
2710                 Block bl = end_block();
2711                 tmp_blocks.Push(bl);
2712                 start_block();
2713           }
2714           else_if_statement_rest 
2715           {
2716                 Location l = (Location) oob_stack.Pop ();
2717                 oob_stack.Push (l);
2718                 Statement tmp_stmt = (Statement)statement_stack.Pop();
2719                 Block bl = (Block) tmp_blocks.Pop();  
2720                 Expression expr =  (Expression)expr_stack.Pop();  
2721                 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
2722                 statement_stack.Push(stmt);
2723           }          
2724         ;
2725         
2726 select_statement
2727         : SELECT opt_case expression end_of_stmt
2728           { 
2729                 oob_stack.Push (lexer.Location);
2730                 switch_stack.Push (current_block);
2731           }     
2732           opt_case_sections
2733           END SELECT 
2734           {
2735                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2736                 current_block = (Block) switch_stack.Pop ();
2737           }       
2738         ;
2739
2740 opt_case_sections
2741         : /* empty */   { $$ = null; }
2742         | case_sections { $$ = $1; }
2743         ;
2744         
2745 case_sections
2746         : case_sections case_section
2747           {
2748                 ArrayList sections = (ArrayList) $1;
2749
2750                 sections.Add ($2);
2751                 $$ = sections;
2752           }
2753         | case_section
2754           {
2755                 ArrayList sections = new ArrayList ();
2756
2757                 sections.Add ($1);
2758                 $$ = sections;
2759           }
2760         ;
2761
2762 ends 
2763         : end_of_stmt
2764         | ends end_of_stmt
2765         ;
2766         
2767
2768 case_section
2769         : CASE case_clauses ends
2770           { 
2771                 start_block();
2772           }
2773           opt_statement_list
2774           {
2775                 //Block topmost = current_block;
2776                 Block topmost = end_block();
2777                 
2778                 while (topmost.Implicit)
2779                         topmost = topmost.Parent;
2780                         
2781                 // FIXME: This is a horrible hack which MUST go                 
2782                 topmost.statements.Add (new Break (lexer.Location));
2783                 $$ = new SwitchSection ((ArrayList) $2, topmost);
2784           }
2785           | CASE ELSE ends
2786             /* FIXME: we should somehow flag an error 
2787                (BC30321 'Case' cannot follow a 'Case Else' 
2788                in the same 'Select' statement.) 
2789                if Case Else is not the last of the Case clauses
2790             */
2791           { 
2792                 start_block();
2793           }     
2794           opt_statement_list
2795           { 
2796                 //Block topmost = current_block;
2797                 Block topmost = end_block();
2798
2799                 while (topmost.Implicit)
2800                         topmost = topmost.Parent;
2801                         
2802                 // FIXME: This is a horrible hack which MUST go                 
2803                 topmost.statements.Add (new Break (lexer.Location));
2804                 
2805                 ArrayList a = new ArrayList();
2806                 a.Add (new SwitchLabel (null, lexer.Location));                 
2807                 $$ = new SwitchSection ((ArrayList) a, topmost);                
2808           }
2809         ;         
2810         
2811 case_clauses
2812         : case_clause
2813           {
2814                 ArrayList labels = new ArrayList ();
2815
2816                 labels.Add ($1);
2817                 $$ = labels;
2818           }     
2819         | case_clauses COMMA case_clause
2820           {
2821                 ArrayList labels = (ArrayList) ($1);
2822                 labels.Add ($2);
2823
2824                 $$ = labels;
2825           }     
2826         ;
2827         
2828 case_clause
2829         : opt_is comparison_operator expression
2830         | expression
2831           {
2832                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2833           }
2834         ;
2835         
2836 opt_is 
2837         : /* empty */
2838         | IS
2839         ;
2840
2841 comparison_operator
2842         : OP_LT
2843         | OP_GT
2844         | OP_LE
2845         | OP_NE
2846         /*| OP_EQ */
2847         ;
2848
2849 opt_case
2850         : /* empty */
2851         | CASE
2852         ;
2853
2854 expression_statement
2855         : statement_expression 
2856           {
2857                  $$ = $1; 
2858           }
2859         ;
2860
2861
2862 statement_expression
2863         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2864         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2865         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2866         ;
2867
2868 object_creation_expression
2869         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2870           {
2871                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2872           }
2873         | NEW type
2874           {
2875                 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
2876           }
2877         ;
2878         
2879 array_creation_expression
2880         : object_creation_expression array_initializer
2881           {
2882                 New n = (New) $1;
2883                 ArrayList dims = new ArrayList();
2884                 
2885                 if (n.Arguments != null) {
2886                         foreach (Argument a in n.Arguments) {
2887                                 dims.Add (a.Expr);
2888                         }
2889                 }
2890                         
2891                 Expression atype = n.RequestedType;
2892
2893                 ArrayList init = (ArrayList) $2;
2894                 if (init.Count == 0)
2895                         init = null;
2896         
2897                 if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
2898                         VariableDeclaration.VBFixIndexList (ref dims);
2899                         $$ = new ArrayCreation (atype, dims, "", init, lexer.Location); 
2900                 }
2901                 else
2902                 {
2903                         string rank = VariableDeclaration.BuildRank (dims);
2904                         $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location); 
2905                 }
2906                 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
2907           }
2908         ;       
2909
2910 delegate_creation_expression
2911         : NEW type OPEN_PARENS ADDRESSOF opt_argument_list CLOSE_PARENS
2912           {
2913                 New n = new New ((Expression) $2, (ArrayList) $5, lexer.Location);
2914                 if (n==null)
2915                         Console.WriteLine("empty");
2916                 $$ = n;
2917           }
2918         ;
2919
2920 new_expression
2921         : object_creation_expression
2922         | array_creation_expression
2923         | delegate_creation_expression
2924         ;
2925
2926 declaration_statement
2927         : local_variable_declaration 
2928           {
2929                 if ($1 != null){
2930                         DictionaryEntry de = (DictionaryEntry) $1;
2931
2932                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2933                 }
2934           }
2935         | local_constant_declaration 
2936           {
2937                 if ($1 != null){
2938                         DictionaryEntry de = (DictionaryEntry) $1;
2939
2940                         $$ = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value);
2941                 }
2942           }
2943         ;        
2944         
2945 local_variable_declaration
2946         : DIM variable_declarators
2947           {
2948                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
2949           }
2950         ;
2951
2952         
2953 local_constant_declaration
2954         : CONST constant_declarators
2955           {
2956                 if ($2 != null)
2957                         $$ = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), $2);
2958                 else
2959                         $$ = null;
2960           }
2961         ;        
2962         
2963 constant_declarators
2964         : constant_declarator 
2965           {
2966                 ArrayList decl = new ArrayList ();
2967                 if ($1 != null) 
2968                         decl.Add ($1);
2969                         
2970                 $$ = decl;
2971           }
2972         | constant_declarators COMMA constant_declarator
2973           {
2974                 ArrayList decls = (ArrayList) $1;
2975                 if ($3 != null)
2976                         decls.Add ($3);
2977
2978                 $$ = $1;
2979           }
2980         ;
2981
2982 constant_declarator
2983         : variable_name opt_type_decl opt_variable_initializer
2984           {
2985                 VarName vname = (VarName) $1;
2986                 string varname = (string) vname.Name;
2987                 current_rank_specifiers = (ArrayList) vname.Rank;
2988                 object varinit = $3;
2989                 ArrayList a_dims = null;
2990
2991                 if (varinit == null)
2992                         Report.Error (
2993                                 30438, lexer.Location, "Constant should have a value"
2994                                 );
2995
2996                 if (vname.Type != null && $2 != null)
2997                         Report.Error (
2998                                 30302, lexer.Location, 
2999                                 "Type character cannot be used with explicit type declaration" );
3000
3001                 Expression vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3002
3003                 if (current_rank_specifiers != null) 
3004                 {
3005                         Report.Error (30424, lexer.Location, "Constant doesn't support array");
3006                         $$ = null;
3007                 }
3008                 else
3009                         $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
3010           }
3011         ;               
3012
3013 variable_declarators
3014         : variable_declarator 
3015           {
3016                 ArrayList decl = new ArrayList ();
3017                 decl.AddRange ((ArrayList) $1);
3018                 $$ = decl;
3019           }
3020         | variable_declarators COMMA variable_declarator
3021           {
3022                 ArrayList decls = (ArrayList) $1;
3023                 decls.AddRange ((ArrayList) $3);
3024                 $$ = $1;
3025           }
3026         ;
3027
3028 variable_declarator
3029         : variable_names opt_type_decl opt_variable_initializer
3030           {
3031             ArrayList names = (ArrayList) $1;
3032                 object varinit = $3;
3033                 ArrayList VarDeclarations = new ArrayList();
3034                 Expression vartype;
3035                 ArrayList a_dims = null;
3036
3037                 if ((names.Count > 1) && (varinit != null)) 
3038                         Report.Error (
3039                                 30671, lexer.Location, 
3040                                 "Multiple variables with single type can not have " +
3041                                 "a explicit initialization" );
3042
3043                                 
3044                 foreach (VarName vname in names)
3045                 {
3046                         string varname = (string) vname.Name;
3047                         current_rank_specifiers = (ArrayList) vname.Rank;
3048                         a_dims = null;
3049                         varinit = $3;
3050
3051                         if(vname.Type != null && $2 != null)
3052                                 Report.Error (
3053                                         30302, lexer.Location, 
3054                                         "Type character cannot be used with explicit type declaration" );
3055
3056                         // Some checking is required for particularly weird declarations
3057                         // like Dim a As Integer(,)
3058                         if ($2 is Pair) {
3059                                 vartype = (Expression) ((Pair) $2).First;
3060                                 
3061                                 /*if ($3 != null && $3 is ArrayList)
3062                                         Report.Error (205, "End of statement expected.");*/
3063                                         
3064                                 ArrayList args = (ArrayList) ((Pair) $2).Second;
3065                                 if (current_rank_specifiers != null)
3066                                         Report.Error (31087, lexer.Location,
3067                                                  "Array types specified in too many places");   
3068                                 
3069                                 if (VariableDeclaration.IndexesSpecifiedInRank (args))            
3070                                         Report.Error (30638, "Array bounds cannot appear in type specifiers."); 
3071                                 
3072                                 current_rank_specifiers = new ArrayList ();
3073                                 current_rank_specifiers.Add (args);
3074                                 
3075                                 /*string s_vartype = vartype.ToString();                                
3076                                 s_vartype += "[";
3077                                 if (args != null)
3078                                         for (int x = 0; x < args.Count; x++)
3079                                                 s_vartype += ",";
3080                                         
3081                                 s_vartype += "]";       
3082                                 vartype = DecomposeQI(s_vartype, Location.Null);        */
3083                         }
3084                         else
3085                                 vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3086
3087                         // if the variable is an array with explicit bound
3088                         // and having explicit initialization throw exception
3089                         if (current_rank_specifiers != null && varinit != null) 
3090                         {
3091                                 bool broken = false;
3092                                 foreach (ArrayList exprs in current_rank_specifiers)
3093                                 {
3094                                         foreach (Expression expr in exprs)
3095                                         {
3096                                                 if (!((Expression)expr is EmptyExpression ))
3097                                                 {
3098                                                         Report.Error (
3099                                                                 30672, lexer.Location, 
3100                                                                 "Array declared with explicit bound " +
3101                                                                 " can not have explicit initialization");
3102                                                         broken = true;
3103                                                         break;
3104                                                 }
3105                                         }
3106                                         if (broken)
3107                                                 break;
3108                                 }
3109                         }
3110                         
3111                         /*
3112                         Check for a declaration like Dim a(2) or Dim a(2,3)
3113                         If this is the case, we must generate an ArrayCreationExpression
3114                         and, in case, add the initializer after the array has been created.
3115                         */
3116                         if (VariableDeclaration.IsArrayDecl (this)) {   
3117                                 if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) {   
3118                                         a_dims = (ArrayList) current_rank_specifiers;
3119                                         VariableDeclaration.VBFixIndexLists (ref a_dims);
3120                                         varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
3121                                 }
3122                                 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
3123                         }
3124
3125                         if (vartype is New) {
3126                                 if (varinit != null) {
3127                                         Report.Error (30205, lexer.Location, "End of statement expected");
3128                                         $$ = null;
3129                                 }
3130                                 else
3131                                 {
3132                                         varinit = vartype;
3133                                         vartype = ((New)vartype).RequestedType;
3134                                 }
3135                         }
3136                         VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null));
3137             }// end of for
3138             $$ = VarDeclarations;
3139           } 
3140         ;
3141
3142 variable_names
3143         : variable_name
3144           {
3145                 ArrayList list = new ArrayList ();
3146                 list.Add ($1);
3147                 $$ = list;
3148           }
3149         | variable_names COMMA variable_name
3150           {
3151                 ArrayList list = (ArrayList) $1;
3152                 list.Add ($3);
3153                 $$ = list;
3154           }
3155         ;
3156         
3157 variable_name
3158         : identifier opt_type_character opt_array_name_modifier
3159           {
3160                 $$ = new VarName ($1, $2, $3);
3161           }
3162         ;
3163
3164 opt_type_spec
3165         : /* empty */   
3166           { 
3167                 $$ = null;              
3168           }
3169         | AS type       
3170           { 
3171                 $$ = (Expression) $2;
3172           }
3173         ;
3174                 
3175 opt_type_with_ranks
3176         : opt_type_spec 
3177         | AS type rank_specifiers
3178           {
3179                 $$ = TypeManager.system_object_expr; 
3180           }
3181         ;
3182         
3183 opt_type_decl
3184         : opt_type_spec
3185           {
3186                 $$ = $1;
3187           }
3188         | AS type OPEN_PARENS /*opt_argument_list*/ opt_dim_separators CLOSE_PARENS
3189           {
3190                 $$ = new Pair ($2, $4);
3191           }
3192         | AS NEW type
3193           {
3194                 New n = new New ((Expression)$3, null, lexer.Location);
3195                 $$ = (Expression) n;
3196           }
3197         | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS 
3198           {
3199                 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
3200                 $$ = (Expression) n;
3201           }
3202         | AS NEW type OPEN_PARENS ADDRESSOF opt_argument_list CLOSE_PARENS 
3203           {
3204                 New n = new New ((Expression)$3, (ArrayList) $6, lexer.Location);
3205                 $$ = (Expression) n;
3206           }
3207         ;
3208                 
3209 opt_array_name_modifier
3210         : /* empty */                           { $$ = null; }
3211         | array_type_modifier                   { $$ = $1;   }
3212         ;
3213         
3214 array_type_modifier
3215         : rank_specifiers               { $$ = $1; }
3216         ;
3217         
3218 opt_variable_initializer
3219         : /* empty */                   { $$ = null; }
3220         | ASSIGN variable_initializer   { $$ = $2; }
3221         ;
3222                 
3223 variable_initializer
3224         : expression
3225           {
3226                 $$ = $1;
3227           }
3228         | array_initializer
3229           {
3230                 $$ = $1;
3231           }
3232         
3233         ;       
3234         
3235 array_initializer
3236         : OPEN_BRACE CLOSE_BRACE
3237           {
3238                 ArrayList list = new ArrayList ();
3239                 $$ = list;
3240           }
3241         | OPEN_BRACE variable_initializer_list CLOSE_BRACE
3242           {
3243                 $$ = (ArrayList) $2;
3244           }
3245         ;
3246
3247 variable_initializer_list
3248         : variable_initializer
3249           {
3250                 ArrayList list = new ArrayList ();
3251                 list.Add ($1);
3252                 $$ = list;
3253           }
3254         | variable_initializer_list COMMA variable_initializer
3255           {
3256                 ArrayList list = (ArrayList) $1;
3257                 list.Add ($3);
3258                 $$ = list;
3259           }
3260         ;
3261
3262 opt_rank_specifiers
3263         : /* empty */
3264           {
3265                   // $$ = "";
3266                   $$ = null;
3267           }
3268         | rank_specifiers
3269           {
3270                         $$ = $1;
3271           }
3272         ;      
3273         
3274 rank_specifiers
3275         : rank_specifier
3276           {
3277                   ArrayList rs = new ArrayList();
3278                   rs.Add ($1);
3279                   $$ = rs;
3280           }
3281         | rank_specifiers rank_specifier
3282           {
3283                   ArrayList rs = (ArrayList) $1;
3284                   rs.Add ($2);
3285                   $$ = rs;
3286           }             
3287         ;               
3288         
3289 rank_specifier
3290         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
3291           {
3292                 $$ = $2;
3293           }
3294         ;
3295                 
3296 opt_dim_separators
3297         : /* empty */
3298           {
3299                 ArrayList ds = new ArrayList();
3300                 ds.Add (new EmptyExpression());
3301                 $$ = ds;                
3302           }
3303         | dim_separators
3304           {
3305                 ArrayList ds = (ArrayList) $1;
3306                 ds.Add (new EmptyExpression());
3307                 $$ = ds;        
3308           }     
3309         | dim_specifiers
3310           {
3311                 $$ = $1;
3312           }       
3313         ;
3314
3315 dim_separators
3316         : COMMA
3317           {
3318                 ArrayList ds = new ArrayList();
3319                 ds.Add (new EmptyExpression());
3320                 $$ = ds;
3321           }
3322         | dim_separators COMMA
3323           {
3324                 ArrayList ds = (ArrayList) $1;
3325                 ds.Add (new EmptyExpression());
3326                 $$ = ds;                
3327           }
3328         ;
3329
3330 dim_specifiers
3331         : expression
3332           {
3333                 ArrayList ds = new ArrayList();
3334                 ds.Add ((Expression) $1);
3335                 $$ = ds;
3336           }     
3337         | dim_specifiers COMMA expression
3338           {
3339                 ArrayList ds = (ArrayList) $1;
3340                 ds.Add ((Expression) $3);
3341                 $$ = ds;                
3342           }     
3343         ;
3344         
3345 /* Expressions */
3346 primary_expression
3347         : literal
3348           {
3349                 // 7.5.1: Literals
3350           }
3351
3352         | qualified_identifier
3353           {
3354                 string name = (string) $1;
3355
3356                 $$ = DecomposeQI (name, lexer.Location);
3357           }
3358         | parenthesized_expression
3359         | member_access
3360         | invocation_expression
3361         //| element_access
3362         | this_access
3363         | base_access
3364         | new_expression
3365         | cast_expression
3366         ;
3367
3368 literal
3369         : boolean_literal
3370         | integer_literal
3371         | real_literal
3372         | LITERAL_DATE                  { $$ = new DateLiteral ((DateTime)lexer.Value); }
3373         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
3374         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
3375         | NOTHING                               { $$ = NullLiteral.Null; }
3376         ;
3377
3378 real_literal
3379         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
3380         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
3381         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3382         ;
3383
3384 integer_literal
3385         : LITERAL_INTEGER       {
3386                 object v = lexer.Value;
3387
3388                 if (v is int)
3389                         $$ = new IntLiteral ((Int32)v); 
3390                 else if (v is short)
3391                         $$ = new ShortLiteral ((Int16)v);
3392                 else if (v is long)
3393                         $$ = new LongLiteral ((Int64)v);
3394                 else
3395                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
3396                         
3397           }
3398         ;
3399
3400 boolean_literal
3401         : TRUE                  { $$ = new BoolLiteral (true); }
3402         | FALSE                 { $$ = new BoolLiteral (false); }
3403         ;
3404
3405 parenthesized_expression
3406         : OPEN_PARENS expression CLOSE_PARENS
3407           { $$ = $2; }
3408         ;
3409
3410 member_access
3411         : primary_expression DOT identifier
3412           {
3413                 if ($1 != null) {
3414                         string id_name = (string)$3;
3415                         if (id_name.ToUpper() == "NEW")
3416                                 id_name = ".ctor";
3417                         $$ = new MemberAccess ((Expression) $1, id_name, lexer.Location);
3418                 }
3419                 else
3420                 {
3421                         if (with_stack.Count > 0) {
3422                                 Expression e = (Expression) with_stack.Peek();
3423                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3424                         }
3425                         else
3426                         {
3427                                 // OOps
3428                         }
3429                 }
3430           }
3431 /*      | primary_expression DOT NEW
3432           {
3433                 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3434           }       */
3435         | predefined_type DOT identifier
3436           {
3437                 if ($1 != null)
3438                         $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3439                 else
3440                 {
3441                         if (with_stack.Count > 0) {
3442                                 Expression e = (Expression) with_stack.Peek();
3443                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3444                         }
3445                         else
3446                         {
3447                                 // OOps
3448                         }
3449                 }
3450           }
3451         ;
3452
3453 predefined_type
3454         : builtin_types
3455         ;
3456
3457 invocation_expression
3458         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3459           {
3460                 if ($1 == null) {
3461                         Location l = lexer.Location;
3462                         Report.Error (1, l, "THIS IS CRAZY");
3463                 }
3464                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3465 //              Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3466           } 
3467         ;
3468         
3469 base_access
3470         : MYBASE DOT IDENTIFIER
3471           {
3472                 string id_name = (string) $3;
3473                 if (id_name.ToUpper() == "NEW")
3474                         id_name = "New";
3475                 $$ = new BaseAccess (id_name, lexer.Location);
3476           }
3477 /*      | MYBASE DOT NEW
3478           {
3479                 $$ = new BaseAccess ("New", lexer.Location);
3480           }*/
3481         ;       
3482
3483 opt_argument_list
3484         : argument_list
3485           { 
3486                 /*
3487                    The 'argument' rule returns an 'empty' argument
3488                    of type NoArg (used for default arguments in invocations)
3489                    if no arguments are actually passed.
3490
3491                    If there is only one argument and it is o type NoArg,
3492                    we return a null (empty) list
3493                 */
3494                 ArrayList args = (ArrayList) $1;
3495                 if (args.Count == 1 &&
3496                     ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3497                         $$ = null;
3498                 else
3499                         $$ = $1;
3500           }
3501         ;
3502
3503 argument_list
3504         : argument
3505           {
3506                 ArrayList list = new ArrayList ();
3507                 list.Add ($1);
3508                 $$ = list;
3509           }
3510         | argument_list COMMA argument
3511           {
3512                 ArrayList list = (ArrayList) $1;
3513                 list.Add ($3);
3514                 $$ = list;
3515           }
3516         ;
3517
3518 argument
3519         : expression
3520           {
3521                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3522           }
3523         | BYREF variable_reference
3524           {
3525                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3526           }
3527         | /* empty */
3528           {
3529                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3530           }
3531         ;
3532
3533 variable_reference
3534         : expression {/* note ("section 5.4"); */  $$ = $1;  }
3535         ;
3536
3537 negation_expression
3538         : NOT expression 
3539           {
3540                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3541           }
3542         ;
3543                 
3544 expression
3545         : conditional_expression { $$ = $1; }
3546         | negation_expression
3547         /*| assignment_expression*/
3548         ;
3549
3550 opt_expression
3551         : /* empty */
3552         | expression
3553         ;
3554                 
3555 this_access
3556         : ME
3557           {
3558                 $$ = new This (current_block, lexer.Location);
3559           }
3560         | MYCLASS
3561           {
3562                 // FIXME: This is actually somewhat different from Me
3563                 // because it is for accessing static (classifier) methods/properties/fields
3564                 $$ = new This (current_block, lexer.Location);
3565           }
3566         ;
3567
3568 unary_expression
3569         : primary_expression
3570         /*| NOT prefixed_unary_expression
3571           {
3572                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3573           }
3574         | cast_expression */
3575         ;
3576         
3577 cast_expression
3578         : cast_operator OPEN_PARENS expression CLOSE_PARENS
3579           {
3580                   $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3581           }     
3582         | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3583           {
3584                   $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3585           }                       
3586         ;
3587         
3588 cast_operator
3589         : CBOOL         { $$ = TypeManager.system_boolean_expr;         }
3590         | CBYTE         { $$ = TypeManager.system_byte_expr;            }
3591         | CCHAR         { $$ = TypeManager.system_char_expr;            }
3592         | CDATE         { $$ = TypeManager.system_date_expr;            }
3593         | CDBL          { $$ = TypeManager.system_double_expr;          }
3594         | CDEC          { $$ = TypeManager.system_decimal_expr;         }
3595         | CINT          { $$ = TypeManager.system_int32_expr;           }
3596         | CLNG          { $$ = TypeManager.system_int64_expr;           }
3597         | COBJ          { $$ = TypeManager.system_object_expr;          }
3598         | CSHORT        { $$ = TypeManager.system_int16_expr;           }
3599         | CSNG          { $$ = TypeManager.system_single_expr;          }
3600         | CSTR          { $$ = TypeManager.system_string_expr;  }
3601         ;
3602         
3603         //
3604         // The idea to split this out is from Rhys' grammar
3605         // to solve the problem with casts.
3606         //
3607 prefixed_unary_expression
3608         : unary_expression
3609         | PLUS prefixed_unary_expression
3610           {
3611                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3612           }
3613         | MINUS prefixed_unary_expression
3614           {
3615                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3616           }
3617         ;
3618
3619 multiplicative_expression
3620         : prefixed_unary_expression
3621         | multiplicative_expression STAR prefixed_unary_expression
3622           {
3623                 $$ = new Binary (Binary.Operator.Multiply,
3624                                  (Expression) $1, (Expression) $3, lexer.Location);
3625           }
3626         | multiplicative_expression DIV prefixed_unary_expression
3627           {
3628                 $$ = new Binary (Binary.Operator.Division,
3629                                  (Expression) $1, (Expression) $3, lexer.Location);
3630           }
3631         | multiplicative_expression OP_IDIV prefixed_unary_expression
3632           {
3633                 $$ = new Binary (Binary.Operator.Division,
3634                                  (Expression) $1, (Expression) $3, lexer.Location);
3635           }       
3636         | multiplicative_expression MOD prefixed_unary_expression
3637           {
3638                 $$ = new Binary (Binary.Operator.Modulus,
3639                                  (Expression) $1, (Expression) $3, lexer.Location);
3640           }
3641         ;
3642
3643 additive_expression
3644         : multiplicative_expression
3645         | additive_expression PLUS multiplicative_expression
3646           {
3647                 $$ = new Binary (Binary.Operator.Addition,
3648                                  (Expression) $1, (Expression) $3, lexer.Location);
3649           }
3650         | additive_expression MINUS multiplicative_expression
3651           {
3652                 $$ = new Binary (Binary.Operator.Subtraction,
3653                                  (Expression) $1, (Expression) $3, lexer.Location);
3654           }
3655         | additive_expression OP_CONCAT multiplicative_expression
3656           {
3657                 // FIXME: This should only work for String expressions
3658                 // We probably need to use something from the runtime
3659                 $$ = new Binary (Binary.Operator.Addition,
3660                                  (Expression) $1, (Expression) $3, lexer.Location);
3661           }       
3662         ;
3663
3664 relational_expression
3665         : additive_expression
3666         | relational_expression OP_LT additive_expression
3667           {
3668                 $$ = new Binary (Binary.Operator.LessThan,
3669                                  (Expression) $1, (Expression) $3, lexer.Location);
3670           }
3671         | relational_expression OP_GT additive_expression
3672           {
3673                 $$ = new Binary (Binary.Operator.GreaterThan,
3674                                  (Expression) $1, (Expression) $3, lexer.Location);
3675           }
3676         | relational_expression OP_LE additive_expression
3677           {
3678                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
3679                                  (Expression) $1, (Expression) $3, lexer.Location);
3680           }
3681         | relational_expression OP_GE additive_expression
3682           {
3683                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
3684                                  (Expression) $1, (Expression) $3, lexer.Location);
3685           }
3686         | relational_expression IS unary_expression
3687           {
3688                 $$ = new Binary (Binary.Operator.Equality,
3689                         (Expression) $1, (Expression) $3, lexer.Location);
3690           }
3691         | relational_expression AS type_name
3692           {
3693                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
3694           }
3695         ;
3696
3697 equality_expression
3698         : relational_expression
3699         | equality_expression ASSIGN relational_expression
3700           {
3701                 $$ = new Binary (Binary.Operator.Equality,
3702                                  (Expression) $1, (Expression) $3, lexer.Location);
3703           }
3704         | equality_expression OP_NE relational_expression
3705           {
3706                 $$ = new Binary (Binary.Operator.Inequality, 
3707                                  (Expression) $1, (Expression) $3, lexer.Location);
3708           }       
3709         ;
3710
3711 and_expression
3712         : equality_expression
3713         | and_expression AND equality_expression
3714           {
3715                 $$ = new Binary (Binary.Operator.BitwiseAnd,
3716                                  (Expression) $1, (Expression) $3, lexer.Location);
3717           }
3718         ;
3719
3720 exclusive_or_expression
3721         : and_expression
3722         | exclusive_or_expression OP_XOR and_expression
3723           {
3724                 $$ = new Binary (Binary.Operator.ExclusiveOr,
3725                                  (Expression) $1, (Expression) $3, lexer.Location);
3726           }
3727         ;
3728
3729 conditional_and_expression
3730         : exclusive_or_expression
3731         | conditional_and_expression AND exclusive_or_expression
3732           {
3733                 $$ = new Binary (Binary.Operator.LogicalAnd,
3734                                  (Expression) $1, (Expression) $3, lexer.Location);
3735           }
3736         | conditional_and_expression ANDALSO exclusive_or_expression
3737           {     // FIXME: this is likely to be broken
3738                 $$ = new Binary (Binary.Operator.LogicalAnd,
3739                                  (Expression) $1, (Expression) $3, lexer.Location);
3740           }
3741         ;
3742
3743 conditional_or_expression
3744         : conditional_and_expression
3745         | conditional_or_expression OR conditional_and_expression
3746           {
3747                 $$ = new Binary (Binary.Operator.LogicalOr,
3748                                  (Expression) $1, (Expression) $3, lexer.Location);
3749           }
3750         | conditional_or_expression ORELSE conditional_and_expression
3751           {     // FIXME: this is likely to be broken
3752                 $$ = new Binary (Binary.Operator.LogicalOr,
3753                                  (Expression) $1, (Expression) $3, lexer.Location);
3754           }
3755         ;
3756
3757 conditional_expression
3758         : conditional_or_expression
3759         ;
3760
3761 assignment_expression
3762         : prefixed_unary_expression ASSIGN expression
3763           { 
3764                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3765           }
3766         | prefixed_unary_expression ASSIGN ADDRESSOF expression
3767           { 
3768                         // fixme: this is not working
3769                         // d = AddressOf F
3770                         // type of d has to  get resolved somewhere
3771                         //$$ = new New ((Expression) $1, (ArrayList) $4, lexer.Location);
3772                         $$ = new Assign ((Expression) $1, (Expression) $4, lexer.Location);
3773           }
3774         | prefixed_unary_expression OP_MULT_ASSIGN expression
3775           {
3776                 Location l = lexer.Location;
3777
3778                 $$ = new CompoundAssign (
3779                         Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
3780           }
3781         | prefixed_unary_expression OP_DIV_ASSIGN expression
3782           {
3783                 Location l = lexer.Location;
3784
3785                 $$ = new CompoundAssign (
3786                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3787           }
3788         | prefixed_unary_expression OP_IDIV_ASSIGN expression
3789           {
3790                 Location l = lexer.Location;
3791
3792                 $$ = new CompoundAssign (
3793                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3794           }       
3795         | prefixed_unary_expression OP_ADD_ASSIGN expression
3796           {
3797                 Location l = lexer.Location;
3798
3799                 $$ = new CompoundAssign (
3800                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3801           }
3802         | prefixed_unary_expression OP_SUB_ASSIGN expression
3803           {
3804                 Location l = lexer.Location;
3805
3806                 $$ = new CompoundAssign (
3807                         Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
3808           }
3809         | prefixed_unary_expression OP_CONCAT_ASSIGN expression
3810           {
3811                 Location l = lexer.Location;
3812
3813                 $$ = new CompoundAssign (
3814                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3815           }               
3816         ;
3817
3818 /*constant_expression
3819         : expression
3820         ;
3821 */
3822
3823 boolean_expression
3824         : expression
3825         ;
3826
3827 type
3828         : type_name {   /* class_type */
3829                 /*
3830                    This does interfaces, delegates, struct_types, class_types,
3831                    parent classes, and more! 4.2
3832                  */
3833                 $$ = DecomposeQI ((string) $1, lexer.Location); 
3834           }
3835         | builtin_types 
3836         /*| array_type 
3837          | pointer_type */
3838         ;
3839
3840 type_list
3841         : type
3842           {
3843                 ArrayList types = new ArrayList ();
3844
3845                 types.Add ($1);
3846                 $$ = types;
3847           }
3848         | type_list COMMA type
3849           {
3850                 ArrayList types = (ArrayList) $1;
3851
3852                 types.Add ($3);
3853                 $$ = types;
3854           }
3855         ;
3856
3857 type_name
3858         : namespace_or_type_name
3859         ;
3860         
3861 namespace_or_type_name
3862         : qualified_identifier
3863         ;
3864
3865 /* Built-in / Integral types */
3866 builtin_types
3867         : OBJECT        { $$ = TypeManager.system_object_expr; }
3868         | STRING        { $$ = TypeManager.system_string_expr; }
3869         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
3870         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
3871         | SINGLE        { $$ = TypeManager.system_single_expr; }
3872         | DOUBLE        { $$ = TypeManager.system_double_expr; }
3873         | DATE          { $$ = TypeManager.system_date_expr; }
3874         | integral_type
3875         ;
3876
3877 integral_type
3878         :
3879         | BYTE          { $$ = TypeManager.system_byte_expr; }
3880         | SHORT         { $$ = TypeManager.system_int16_expr; }
3881         | LONG          { $$ = TypeManager.system_int64_expr; }
3882         | INTEGER       { $$ = TypeManager.system_int32_expr; }
3883         | CHAR          { $$ = TypeManager.system_char_expr; }
3884         ;
3885
3886 interface_type
3887         : type_name
3888         ;
3889         
3890 end_of_stmt
3891         : EOL
3892         | COLON
3893         ;       
3894 %%
3895
3896
3897 Tokenizer lexer;
3898
3899 public Tokenizer Lexer {
3900         get {
3901                 return lexer;
3902         }
3903 }                  
3904
3905 public static Expression DecomposeQI (string name, Location loc)
3906 {
3907         Expression o;
3908
3909         if (name.IndexOf ('.') == -1){
3910                 return new SimpleName (name, loc);
3911         } else {
3912                 int pos = name.LastIndexOf (".");
3913                 string left = name.Substring (0, pos);
3914                 string right = name.Substring (pos + 1);
3915
3916                 o = DecomposeQI (left, loc);
3917
3918                 return new MemberAccess (o, right, loc);
3919         }
3920 }
3921
3922 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3923 {
3924         Block implicit_block;
3925         ArrayList inits = null;
3926
3927         //
3928         // We use the `Used' property to check whether statements
3929         // have been added to the current block.  If so, we need
3930         // to create another block to contain the new declaration
3931         // otherwise, as an optimization, we use the same block to
3932         // add the declaration.
3933         //
3934         // FIXME: A further optimization is to check if the statements
3935         // that were added were added as part of the initialization
3936         // below.  In which case, no other statements have been executed
3937         // and we might be able to reduce the number of blocks for
3938         // situations like this:
3939         //
3940         // int j = 1;  int k = j + 1;
3941         //
3942         
3943         VariableDeclaration.FixupTypes (variable_declarators);
3944         
3945         if (current_block.Used) {
3946                 implicit_block = new Block (current_block, true, loc, Location.Null);
3947                 implicit_block.AddChildVariableNames (current_block);
3948         } else
3949                 implicit_block = current_block;
3950
3951         foreach (VariableDeclaration decl in variable_declarators){
3952                 Expression type = decl.type;
3953                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3954                         if (decl.expression_or_array_initializer != null){
3955                                 if (inits == null)
3956                                         inits = new ArrayList ();
3957                                 inits.Add (decl);
3958                         }
3959                 }
3960         }
3961
3962         if (inits == null)
3963                 return implicit_block;
3964
3965         foreach (VariableDeclaration decl in inits){
3966                 Assign assign;
3967                 Expression expr;
3968                 Expression type = decl.type;
3969                 
3970                 if ((decl.expression_or_array_initializer is Expression) || 
3971                     (decl.expression_or_array_initializer is New)) {
3972                         expr = (Expression) decl.expression_or_array_initializer;
3973                 } else {
3974                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3975                         
3976                         expr = new ArrayCreation (type, "", init, decl.Location);
3977                 }
3978
3979                 LocalVariableReference var;
3980                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3981
3982                 assign = new Assign (var, expr, decl.Location);
3983
3984                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3985         }
3986         
3987         return implicit_block;
3988 }
3989
3990 Block declare_local_constant (Expression dummy_type, ArrayList variable_declarators)
3991 {
3992         Block implicit_block;
3993         VariableDeclaration.FixupTypes (variable_declarators);
3994
3995         if (current_block.Used)
3996                 implicit_block = new Block (current_block, true);
3997         else
3998                 implicit_block = current_block;
3999
4000         foreach (VariableDeclaration decl in variable_declarators){
4001                 Expression type = decl.type;
4002                 implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
4003                                           current_local_parameters, decl.Location);
4004         }
4005         
4006         return implicit_block;
4007 }
4008
4009 struct VarName {
4010                 public object Name;
4011                 public object Type;
4012                 public object Rank;
4013                                                                                 
4014                 public VarName (object n, object t, object r)
4015                 {
4016                         Name = n;
4017                         Type = t;
4018                         Rank = r;
4019                 }
4020         }
4021
4022
4023 // <summary>
4024 //   A class used to pass around variable declarations and constants
4025 // </summary>
4026 public class VariableDeclaration {
4027         public string identifier;
4028         public object expression_or_array_initializer;
4029         public Location Location;
4030         public Attributes OptAttributes;
4031         public Expression type;
4032         public ArrayList dims;
4033                 
4034         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
4035         {
4036                 this.identifier = id;
4037                 this.expression_or_array_initializer = eoai;
4038                 this.Location = l;
4039                 this.OptAttributes = opt_attrs;
4040                 this.type = t;
4041                 this.dims = null;
4042         }       
4043
4044         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
4045         {
4046         }
4047         
4048         public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
4049         {
4050         }       
4051         
4052         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
4053                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
4054         {
4055         }       
4056         
4057         public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
4058         {       
4059                 // FIXME : This is broken: only the first rank is parsed
4060                 return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
4061         }
4062         
4063         public static void FixupTypes (ArrayList vars)
4064         {
4065                 int varcount =  vars.Count;
4066                 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
4067                         
4068                 if (last_var.type == null)
4069                         last_var.type = TypeManager.system_object_expr;
4070                         
4071                 Expression cur_type = last_var.type;
4072                 int n = varcount - 1;
4073                 
4074                 while (n >= 0) {
4075                         VariableDeclaration var = (VariableDeclaration) vars[n--];
4076                         if (var.type == null)
4077                                 var.type = cur_type;
4078                         else
4079                                 cur_type = var.type;
4080                 }
4081         }
4082         
4083         public static bool IndexesSpecifiedInRank (ArrayList IndexList)
4084         {
4085                 bool res = false;
4086                 
4087                 if (IndexList != null) {
4088                         foreach (Expression e in IndexList)
4089                                 if (!(e is EmptyExpression)) {
4090                                         res = true;
4091                                         break;
4092                                 }       
4093                 }
4094                 return (res);
4095         }       
4096         
4097         
4098         public static bool IndexesSpecified (ArrayList ranks)
4099         {
4100                 bool res = false;
4101                 
4102                 if (ranks != null) {
4103                         foreach (ArrayList IndexList in ranks) {
4104                                 if (IndexesSpecifiedInRank (IndexList)) {
4105                                         res = true;
4106                                         break;
4107                                 }       
4108                         }       
4109                 }
4110                 return (res);
4111         }
4112         
4113         public static string StripDims (string varname, ref string d)
4114         {
4115                 string res = varname;
4116                 string dres = "";
4117                 
4118                 if (varname.IndexOf("[") >= 0) {
4119                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
4120                         res = varname.Substring(0, varname.IndexOf("["));
4121                 }
4122                 d = dres;
4123                 return (res);
4124         }       
4125         
4126         public static string StripDims (string varname)
4127         {
4128                 string dres = "";
4129                 
4130                 return (StripDims(varname, ref dres));
4131         }       
4132         
4133         public static string StripIndexesFromDims (string dims)
4134         {
4135                 StringBuilder sb = new StringBuilder();
4136
4137                 foreach (char c in dims) 
4138                         if (c == ',' || c == ']' || c == '[')
4139                                 sb.Append (c);
4140                                 
4141                 return sb.ToString();                           
4142         }
4143         
4144         public static string BuildRank (ArrayList rank)
4145         {
4146                 string res = "";
4147
4148                 res += "[";
4149                 for (int x = 0; x < (rank.Count -1 ); x++)
4150                         res += ",";
4151                         
4152                 res += "]";
4153                 return res;
4154         }
4155                 
4156         public static string BuildRanks (Parser t)
4157         {
4158                 string res = "";
4159
4160                 foreach (ArrayList rank in t.current_rank_specifiers)
4161                         res += BuildRank (rank);
4162
4163                 return res;
4164         }       
4165         
4166         public static void VBFixIndexList (ref ArrayList IndexList)
4167         {
4168                 if (IndexList != null) {
4169                         for (int x = 0; x < IndexList.Count; x++) {
4170                                 Expression e = (Expression) IndexList[x];
4171                                 if (!(e is EmptyExpression)) {
4172                                         IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
4173                                 }
4174                         }
4175                 }
4176         }               
4177         
4178         public static bool IsArrayDecl (Parser t)
4179         {
4180                 // return (varname.IndexOf("[") >= 0);
4181                 return (t.current_rank_specifiers != null);
4182         }                       
4183         
4184         public static void VBFixIndexLists (ref ArrayList ranks)
4185         {       
4186                 if (ranks != null) {
4187                         for (int x = 0; x < ranks.Count; x++) {
4188                                 ArrayList IndexList = (ArrayList) ranks[x];
4189                                 VBFixIndexList (ref IndexList);
4190                         }       
4191                 }       
4192         }
4193                 
4194         public static void FixupArrayTypes (ArrayList vars)
4195         {
4196                 int varcount =  vars.Count;
4197                 string dims;
4198                 
4199                 foreach (VariableDeclaration var in vars) {
4200                         if (var.identifier.EndsWith(",")) {
4201                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
4202                                                                 var.identifier.LastIndexOf(",")) + "]";
4203                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
4204                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
4205                         }
4206                 }
4207         }                               
4208 }
4209
4210
4211 public Property BuildSimpleProperty (Expression p_type, string name, 
4212                                         Field p_fld, int mod_flags,
4213                                         Attributes attrs, Location loc) 
4214 {
4215         Property p;
4216         Block get_block, set_block;
4217         Accessor acc_set, acc_get;
4218         StatementExpression a_set;
4219         Statement a_get;
4220         Parameter [] args;
4221         
4222         // Build SET Block
4223         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
4224         args  = new Parameter [1];
4225         args [0] = implicit_value_parameter;
4226                 
4227         Parameters set_params = new Parameters (args, null, loc);
4228         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
4229                             (Expression) new SimpleName("value", loc), loc), loc);
4230                             
4231         set_block = new Block (current_block, set_params, loc, Location.Null);
4232         set_block.AddStatement ((Statement) a_set);                                         
4233         acc_set = new Accessor (set_block, attrs);
4234         
4235         // Build GET Block
4236         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
4237         get_block = new Block (current_block, null, loc, Location.Null);
4238         get_block.AddStatement ((Statement) a_get);                                         
4239         acc_get = new Accessor (get_block, attrs);
4240                 
4241         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
4242         
4243         return (p);
4244 }
4245         
4246 void start_block () 
4247 {
4248         current_block = new Block (current_block, current_local_parameters,
4249                            lexer.Location, Location.Null);
4250
4251
4252 Block end_block ()
4253
4254         Block res;
4255         
4256         while (current_block.Implicit)
4257                 current_block = current_block.Parent;
4258
4259         res = current_block;
4260
4261         current_block.SetEndLocation (lexer.Location);
4262         current_block = current_block.Parent;
4263         
4264         return (res);
4265 }
4266
4267 private void AddHandler (Expression evt_definition, string handler_name)
4268 {
4269         AddHandler (current_block, evt_definition, handler_name);
4270 }
4271
4272 void CheckAttributeTarget (string a)
4273 {
4274         switch (a) {
4275
4276         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
4277                 return;
4278                 
4279         default :
4280                 Location l = lexer.Location;
4281                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
4282                 break;
4283         }
4284 }
4285
4286 private void AddHandler (Block b, Expression evt_id, string handler_name)
4287 {
4288         Location loc = lexer.Location;
4289         string evt_target = evt_id.ToString();
4290         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
4291         Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
4292         b.AddStatement (s);
4293 }
4294
4295 private void RaiseEvent (string evt_name, ArrayList args)
4296 {
4297         Location loc = lexer.Location;
4298         
4299         Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
4300         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); 
4301         current_block.AddStatement (s); 
4302 }
4303
4304 // FIXME: THIS DOES NOT WORK!!!
4305 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
4306 {
4307         Location loc = lexer.Location;
4308         ArrayList neh_args = new ArrayList();
4309         neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
4310         
4311         ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
4312         
4313         CompoundAssign ca = new CompoundAssign (
4314                         Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
4315                         
4316         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
4317         b.AddStatement (s);     
4318 }
4319
4320 // <summary>
4321 //  This method is used to get at the complete string representation of
4322 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
4323 //  This is necessary because local_variable_type admits primary_expression
4324 //  as the type of the variable. So we do some extra checking
4325 // </summary>
4326 string GetQualifiedIdentifier (Expression expr)
4327 {
4328         if (expr is SimpleName)
4329                 return ((SimpleName)expr).Name;
4330         else if (expr is MemberAccess)
4331                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4332         else 
4333                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4334         
4335 }
4336
4337 private void RemoveHandler (Expression evt_definition, string handler_name)
4338 {
4339         RemoveHandler (current_block, evt_definition, handler_name);
4340 }
4341
4342 private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s)
4343 {
4344         ConstructorInitializer ci = null;
4345         
4346         if (s.Count > 0) {
4347                 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4348                         Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4349                         
4350                         if (i.expr is BaseAccess) {
4351                                 BaseAccess ba = (BaseAccess) i.expr;
4352                                 if (ba.member == "New" || ba.member == ".ctor") {
4353                                         ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4354                                         s.RemoveAt(0);
4355                                 }
4356                         }
4357                         if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
4358                                 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location); 
4359                                 s.RemoveAt(0);
4360                         }
4361                 }
4362         }
4363         return ci;
4364 }
4365
4366 void Error_ExpectingTypeName (Location l, Expression expr)
4367 {
4368         if (expr is Invocation){
4369                 Report.Error (1002, l, "; expected");
4370         } else {
4371                 Report.Error (-1, l, "Invalid Type definition");
4372         }
4373 }
4374
4375 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4376         return true;
4377 }
4378
4379 private void ReportError9998()
4380 {
4381         Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4382 }
4383
4384 protected override int parse ()
4385 {
4386         RootContext.InitializeImports(ImportsList);
4387         current_namespace = new Namespace (null, RootContext.RootNamespace);
4388         current_container = RootContext.Tree.Types;
4389         current_container.Namespace = current_namespace;
4390         oob_stack = new Stack ();
4391         switch_stack = new Stack ();
4392         expr_stack = new Stack ();      
4393         tmp_blocks = new Stack(); 
4394         with_stack = new Stack();
4395         statement_stack = new Stack();  
4396
4397         UseExtendedSyntax = name.EndsWith(".mbs");
4398         OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4399         OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4400         OptionCompareBinary = InitialOptionCompareBinary;
4401
4402         lexer = new Tokenizer (input, name, defines);
4403         StringBuilder value = new StringBuilder ();
4404         try {
4405                 if (yacc_verbose_flag)
4406                         yyparse (lexer, new yydebug.yyDebugSimple ());
4407                 else
4408                         yyparse (lexer);
4409         } catch (Exception e) {
4410                 Report.Error (29999, lexer.Location, lexer.location + "\nParsing error in " + lexer.ref_name + "\n" + e.ToString());
4411         }
4412
4413         RootContext.VerifyImports();
4414
4415         return Report.Errors;
4416 }
4417
4418 /* end end end */
4419 }