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