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