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