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