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