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