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