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