2004-08-14 Bernie Solomon <bernard@ugsolutions.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)$6).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 */
2150           {     $$ = null; }
2151         | HANDLES qualified_identifier
2152           {
2153                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
2154           }
2155         | HANDLES MYBASE DOT qualified_identifier
2156           {
2157                 // FIXME: this is blatantly wrong and crash-prone
2158                 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
2159           }
2160         ;       
2161
2162 constructor_declaration
2163         : SUB NEW opt_params logical_end_of_line
2164           {
2165                 current_local_parameters = (Parameters) $3;
2166                 start_block();
2167                 oob_stack.Push (lexer.Location);
2168
2169                 Location l = (Location) oob_stack.Pop ();
2170                 $$ = new Constructor ((string) "New", (Parameters) $3, (ConstructorInitializer) null, l);
2171                 $1 = $$;
2172           }
2173           opt_statement_list
2174           { 
2175                 Constructor c = (Constructor) $1;
2176                 c.Block = (Block) end_block();
2177                 c.ModFlags = (int) current_modifiers;
2178                 c.OptAttributes = current_attributes;
2179                 
2180                 c.Initializer = CheckConstructorInitializer (ref c.Block.statements);
2181
2182                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
2183                 current_local_parameters = null;
2184           }
2185           END SUB logical_end_of_line
2186         ;
2187         
2188 opt_formal_parameter_list
2189         : /* empty */                   
2190           { 
2191                 $$ = Parameters.EmptyReadOnlyParameters; 
2192           }
2193         | formal_parameter_list 
2194           { 
2195                 $$ = $1;        
2196                 //Parameter p = ((Parameters) $1).FixedParameters[0];
2197           }
2198         ;
2199         
2200 formal_parameter_list
2201         : fixed_parameters              
2202           { 
2203                 ArrayList pars_list = (ArrayList) $1;
2204
2205                 Parameter [] pars = new Parameter [pars_list.Count];
2206                 pars_list.CopyTo (pars);
2207                 $$ = new Parameters (pars, null, lexer.Location); 
2208           } 
2209         | fixed_parameters COMMA parameter_array
2210           {
2211                 ArrayList pars_list = (ArrayList) $1;
2212
2213                 Parameter [] pars = new Parameter [pars_list.Count];
2214                 pars_list.CopyTo (pars);
2215
2216                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
2217           }
2218         | parameter_array 
2219           {
2220                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
2221           }
2222         ;
2223
2224 fixed_parameters
2225         : fixed_parameter       
2226           {
2227                 ArrayList pars = new ArrayList ();
2228
2229                 pars.Add ($1);
2230                 $$ = pars;
2231           }
2232         | fixed_parameters COMMA fixed_parameter
2233           {
2234                 ArrayList pars = (ArrayList) $1;
2235
2236                 pars.Add ($3);
2237                 $$ = $1;
2238           }
2239         ;
2240
2241 fixed_parameter
2242         : opt_attributes
2243           opt_parameter_modifier
2244           identifier opt_type_character opt_rank_specifiers opt_type_spec opt_variable_initializer
2245           {
2246                 Parameter.Modifier pm = (Parameter.Modifier)$2;
2247                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
2248                 Expression ptype;
2249                 
2250                 if (opt_parm && ($7 == null))
2251                         Report.Error (30812, "Optional parameters must have a default value");
2252                 
2253                 if (opt_parm) {
2254                         if ((pm & Parameter.Modifier.REF) !=0)
2255                                 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
2256                         else
2257                                 pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
2258                 }       
2259                 
2260                 if ($4 != null && $6 != null && $4 != $6)
2261                         Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
2262
2263                 ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6);
2264                 if ($5 != null) {
2265                         string t = ptype.ToString() + VariableDeclaration.BuildRank ((ArrayList) $5);
2266                         ptype = DecomposeQI (t, lexer.Location);
2267                 }                       
2268                 $$ = new Parameter (ptype, (string) $3, pm,
2269                                         (Attributes) $1, (Expression) $7, opt_parm);
2270           }
2271         ;
2272         
2273 parameter_array
2274         : PARAM_ARRAY identifier opt_parens AS type 
2275           { 
2276                 string s_patype = ((Expression) $5).ToString();
2277                 if ((bool) $3)
2278                         s_patype += "[]";
2279                         
2280                 Expression patype = DecomposeQI (s_patype, Location.Null);
2281                 $$ = new Parameter (patype, (string) $2, Parameter.Modifier.PARAMS, null);
2282                 // note  ("type must be a single-dimension array type"); 
2283           }
2284         ;
2285                 
2286 opt_parens
2287         : /* empty */
2288           {     $$ = false;     }
2289         | OPEN_PARENS CLOSE_PARENS
2290           {     $$ = true;      }
2291         ;
2292         
2293 opt_parameter_modifier
2294         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
2295         | parameter_modifiers   { $$ = $1;                      }
2296         ;
2297
2298 parameter_modifiers
2299         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
2300         | parameter_modifier                            { $$ = $1;      }
2301         ;
2302         
2303 parameter_modifier
2304         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
2305         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
2306         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
2307         ;       
2308
2309 opt_statement_list
2310         : /* empty */
2311         | statement_list end_of_stmt
2312         ;
2313
2314 statement_list
2315         : statement 
2316         | statement_list end_of_stmt statement
2317         ;
2318         
2319 statement : 
2320             declaration_statement
2321             {
2322                   if ($1 != null && (Block) $1 != current_block){
2323                         current_block.AddStatement ((Statement) $1);
2324                         current_block = (Block) $1;
2325                   }
2326             }
2327           | embedded_statement
2328             {
2329                   Statement s = (Statement) $1;
2330
2331                   current_block.AddStatement ((Statement) $1);
2332             } 
2333           | labeled_statement 
2334           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
2335             {
2336                   AddHandler ((Expression) $2, (string) $5);
2337             }
2338           | REMOVEHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
2339                 {
2340                   RemoveHandler ((Expression) $2, (string) $5);
2341             }
2342           | RAISEEVENT identifier opt_raise_event_args  //OPEN_PARENS opt_argument_list CLOSE_PARENS
2343             {
2344               RaiseEvent ((string) $2, (ArrayList) $3);
2345             }
2346           /* | array_handling_statement */
2347           /* | empty_statement */
2348           | with_statement 
2349             {
2350                   Statement s = (Statement) $1;
2351
2352               current_block.AddStatement ((Statement) $1);
2353             }     
2354           ;     
2355           
2356 opt_raise_event_args 
2357         : /* empty */   { $$ = null; }
2358         | OPEN_PARENS opt_argument_list CLOSE_PARENS
2359           {
2360                 $$ = $2;
2361           }
2362         ;
2363
2364 label_name
2365         : identifier
2366         | LITERAL_INTEGER
2367         {
2368                 $$ = $1.ToString();
2369         }
2370         ;
2371
2372 labeled_statement
2373         : label_name COLON
2374           {
2375                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
2376
2377                 if (!current_block.AddLabel ((string) $1, labeled)){
2378                         Location l = lexer.Location;
2379                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2380                 }       
2381                 current_block.AddStatement (labeled);
2382           }
2383         | label_name COLON
2384           {
2385                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
2386
2387                 if (!current_block.AddLabel ((string) $1, labeled)){
2388                         Location l = lexer.Location;
2389                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2390                 }       
2391                 current_block.AddStatement (labeled);
2392           }
2393           statement
2394         ;
2395
2396 embedded_statement
2397         : expression_statement
2398         | selection_statement
2399         | iteration_statement
2400         | try_statement
2401         | synclock_statement
2402         | jump_statement
2403         | array_handling_statement 
2404         ;
2405 /*        
2406 empty_statement
2407         : end_of_stmt
2408           {
2409                   $$ = new EmptyStatement ();
2410           }
2411         ;        
2412 */
2413
2414 with_statement
2415         : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */
2416           {
2417                 // was : Expression e = DecomposeQI ((string) $2, lexer.Location);
2418                 Expression e = (Expression) $2;
2419                 with_stack.Push(e);
2420                 start_block();
2421           }
2422           opt_statement_list
2423           END WITH
2424           {
2425                 Block b = end_block();
2426                 with_stack.Pop();
2427                 $$ = b;
2428           }
2429         ;
2430         
2431         
2432 array_handling_statement
2433         : redim_statement
2434         | erase_statement
2435         ;
2436         
2437 redim_statement
2438         : REDIM opt_preserve redim_clauses
2439           {
2440                 ArrayList list = (ArrayList) $3;
2441                 ReDim r = new ReDim (list, (bool) $2, lexer.Location);
2442                 $$ = r;
2443
2444           }
2445         ;
2446         
2447 opt_preserve
2448         : /* empty */   { $$ = false; }
2449         | PRESERVE      { $$ = true;  }
2450         ;
2451         
2452 redim_clauses
2453         : redim_clause
2454           {
2455                 ArrayList clauses = new ArrayList ();
2456
2457                 clauses.Add ($1);
2458                 $$ = clauses;
2459           }
2460         | redim_clauses COMMA redim_clause
2461           {
2462                 ArrayList clauses = (ArrayList) ($1);
2463                 clauses.Add ($2);
2464
2465                 $$ = clauses;
2466           }
2467         ;
2468
2469 redim_clause
2470         : invocation_expression
2471           {
2472                 Invocation i = (Invocation) $1;
2473                 RedimClause rc = new RedimClause (i.expr, i.Arguments);
2474                 $$ = rc;
2475           }
2476         ;
2477
2478 erase_statement
2479         : ERASE erase_clauses
2480         {
2481                 ArrayList list = (ArrayList) $2;
2482                 foreach(Expression e in list)
2483                 {
2484                         Erase r = new Erase (e, lexer.Location);
2485                         $$ = r;
2486                 }
2487         }
2488         ;
2489
2490 erase_clauses
2491         : erase_clause
2492           {
2493                 ArrayList clauses = new ArrayList ();
2494
2495                 clauses.Add ($1);
2496                 $$ = clauses;
2497           }
2498         | erase_clauses COMMA erase_clause
2499           {
2500                 ArrayList clauses = (ArrayList) ($1);
2501                 clauses.Add ($2);
2502
2503                 $$ = clauses;
2504           }
2505         ;
2506
2507 erase_clause
2508         : primary_expression
2509         ;       
2510                         
2511 jump_statement
2512         : /*break_statement
2513         | continue_statement
2514         | */return_statement
2515         | goto_statement        
2516         | throw_statement       
2517         | exit_statement
2518         | yield_statement
2519         ;
2520                 
2521 goto_statement
2522         : GOTO label_name  
2523           {
2524                 $$ = new Goto (current_block, (string) $2, lexer.Location);
2525           }
2526         ;
2527         
2528 throw_statement
2529         : THROW opt_expression
2530           {
2531                 $$ = new Throw ((Expression) $2, lexer.Location);
2532           }
2533         ;       
2534                         
2535 exit_statement
2536         : EXIT exit_type
2537           {
2538                 $$ = new Exit ((ExitType)$2, lexer.Location);           
2539           }
2540         ;
2541         
2542 exit_type
2543         : DO            { $$ = ExitType.DO;             }
2544         | FOR           { $$ = ExitType.FOR;            }
2545         | WHILE         { $$ = ExitType.WHILE;          }
2546         | SELECT        { $$ = ExitType.SELECT;         }
2547         | SUB           { $$ = ExitType.SUB;            }
2548         | FUNCTION      { $$ = ExitType.FUNCTION;       }
2549         | PROPERTY      { $$ = ExitType.PROPERTY;       }
2550         | TRY           { $$ = ExitType.TRY;            }
2551         ;
2552 return_statement
2553         : RETURN opt_expression 
2554           {       
2555                 $$ = new Return ((Expression) $2, lexer.Location);
2556           }
2557         ;
2558                 
2559 iteration_statement
2560         : while_statement
2561         | do_statement
2562         | for_statement
2563         | foreach_statement
2564         ;
2565
2566 foreach_statement
2567         : FOR EACH identifier IN 
2568           {
2569                 oob_stack.Push (lexer.Location);
2570           }       
2571           expression end_of_stmt
2572           {
2573                 
2574                 start_block();
2575                 Block foreach_block = current_block;
2576                 Location l = lexer.Location;            
2577                 LocalVariableReference v = null;
2578                 VariableInfo vi;
2579
2580                 vi = foreach_block.GetVariableInfo ((string) $3);
2581                 if (vi != null) {
2582                         // Get a reference to this variable.
2583                         v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2584                 }
2585                 else
2586                         Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2587         
2588                 oob_stack.Push (v);
2589           }       
2590           opt_statement_list
2591           NEXT opt_identifier
2592           {
2593                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2594                 Block foreach_block = end_block();
2595                 Location l = (Location) oob_stack.Pop ();
2596
2597                 Foreach f = null;
2598                 if (v != null) {
2599                         f = new Foreach (null, v, (Expression) $6, foreach_block, l);
2600                 }
2601                 
2602                 $$ = f;
2603           }       
2604         ;
2605
2606 yield_statement 
2607         : YIELD expression
2608           {
2609                 if (!UseExtendedSyntax)
2610                 {
2611                         ReportError9998();
2612                         $$ = null;
2613                 }
2614 /*              else
2615                         if (iterator_container == null){
2616                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2617                                 $$ = null;
2618                         } else {
2619                                 iterator_container.SetYields ();
2620                                 $$ = new Yield ((Expression) $2, lexer.Location);
2621                         } */
2622           }
2623         | YIELD STOP
2624           {
2625                 if (!UseExtendedSyntax)
2626                 {
2627                         ReportError9998();
2628                         $$ = null;
2629                 }
2630 /*              else
2631                         if (iterator_container == null){
2632                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2633                                 $$ = null;
2634                         } else {
2635                                 iterator_container.SetYields ();
2636                                 $$ = new YieldBreak (lexer.Location);
2637                         } */
2638           }
2639         ;
2640
2641 synclock_statement
2642         : SYNCLOCK expression end_of_stmt
2643           {   
2644                 start_block();  
2645           }
2646           opt_statement_list 
2647           END SYNCLOCK
2648           {
2649                 $$ = new Lock ((Expression) $2, (Statement) (Block) end_block(), lexer.Location);
2650           }
2651         ;
2652
2653 try_statement
2654         : try_catch
2655         | try_catch_finally
2656         ;
2657                                 
2658 try_header
2659         : TRY end_of_stmt
2660           {   
2661                 start_block();  
2662           }
2663           opt_statement_list 
2664           opt_catch_clauses
2665           {
2666                 tmp_catch_clauses = (ArrayList) $5;
2667           }
2668         ;
2669                                         
2670 try_catch
2671         : try_header 
2672           END TRY
2673           { 
2674                 Catch g = null;
2675                 ArrayList s = new ArrayList ();
2676
2677                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2678                         if (cc.IsGeneral)
2679                                 g = cc;
2680                         else
2681                                 s.Add (cc);
2682                 }
2683
2684                 // Now s contains the list of specific catch clauses
2685                 // and g contains the general one.
2686                 Block b = end_block();
2687
2688                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2689           }       
2690         ;       
2691           
2692 try_catch_finally
2693         : try_header 
2694           { 
2695                 tmp_block = end_block(); 
2696           }     
2697           FINALLY end_of_stmt
2698           { 
2699                 start_block(); 
2700           }       
2701           opt_statement_list 
2702           END TRY
2703           {
2704                 Catch g = null;
2705                 ArrayList s = new ArrayList ();
2706                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2707
2708                 if (catch_list != null){
2709                         foreach (Catch cc in catch_list) {
2710                                 if (cc.IsGeneral)
2711                                         g = cc;
2712                                 else
2713                                         s.Add (cc);
2714                         }
2715                 }
2716
2717                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2718         
2719           }     
2720           ;             
2721
2722 opt_catch_clauses
2723         : /* empty */  {  $$ = null;  }
2724         | catch_clauses
2725         ;
2726
2727 catch_clauses
2728         : catch_clause 
2729           {
2730                 ArrayList l = new ArrayList ();
2731
2732                 l.Add ($1);
2733                 $$ = l;
2734           }
2735         | catch_clauses catch_clause
2736           {
2737                 ArrayList l = (ArrayList) $1;
2738
2739                 l.Add ($2);
2740                 $$ = l;
2741           }
2742         ;
2743
2744 opt_identifier
2745         : /* empty */   {  $$ = null;  }
2746         | identifier
2747         ;
2748
2749 catch_clause 
2750         : CATCH opt_catch_args end_of_stmt
2751         {
2752                 Expression type = null;
2753                 string id = null;
2754                 
2755                 if ($2 != null) {
2756                         DictionaryEntry cc = (DictionaryEntry) $2;
2757                         type = (Expression) cc.Key;
2758                         id   = (string) cc.Value;
2759                         
2760                         if (id != null){
2761                                 ArrayList one = new ArrayList ();
2762                                 Location loc = lexer.Location;
2763
2764                                 one.Add (new VariableDeclaration (id, type, loc));
2765
2766
2767                                 $1 = current_block;
2768                                 current_block = new Block (current_block);
2769                                 Block b = declare_local_variables (type, one, loc);
2770                                 current_block = b;
2771                         }
2772                 }
2773         
2774         } 
2775         opt_statement_list {
2776                 Expression type = null;
2777                 string id = null;
2778                 Block b_catch = current_block;
2779                 
2780                 if ($2 != null){
2781                         DictionaryEntry cc = (DictionaryEntry) $2;
2782                         type = (Expression) cc.Key;
2783                         id   = (string) cc.Value;
2784                         
2785                         if ($1 != null) {
2786                                 //
2787                                 // FIXME: I can change this for an assignment.
2788                                 //
2789                                 while (current_block != (Block) $1)
2790                                         current_block = current_block.Parent;
2791                         }
2792                 }
2793
2794                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2795         }
2796         ;
2797
2798 opt_catch_args
2799         : /* empty */ {  $$ = null; }
2800         | catch_args
2801         ;         
2802
2803 catch_args 
2804         : identifier AS type
2805         {
2806                  $$ = new DictionaryEntry ($3, $1); 
2807         }
2808         ;
2809         
2810         
2811 do_statement
2812         : DO opt_do_construct end_of_stmt
2813           {
2814                 start_block();
2815                 oob_stack.Push (lexer.Location);
2816           }     
2817           opt_statement_list
2818           LOOP opt_do_construct
2819           {
2820                 Expression t_before = (Expression) $2;
2821                 Expression t_after = (Expression) $7;
2822                 Expression t;
2823
2824                 if  ((t_before != null) && (t_after != null))
2825                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2826
2827                 if ((t_before == null) && (t_after == null))
2828                         t = new BoolLiteral (true);
2829                 else
2830                         t = (t_before != null) ? t_before : t_after;
2831                         
2832                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2833                 
2834                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2835                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2836                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2837                          
2838                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2839           }
2840           ;
2841
2842 opt_do_construct
2843         : /* empty */ { $$ = null; }
2844         | while_or_until boolean_expression
2845           {
2846                 do_type = (DoOptions)$1;
2847                 $$ = (Expression) $2;
2848           }
2849         ;
2850
2851 while_or_until
2852         : WHILE { $$ = DoOptions.WHILE; }
2853         | UNTIL { $$ = DoOptions.UNTIL; }
2854         ;
2855
2856 while_statement
2857         : WHILE
2858         {
2859                 start_block();
2860                 oob_stack.Push (lexer.Location);
2861         }
2862         boolean_expression end_of_stmt
2863         opt_statement_list
2864         END WHILE
2865         {
2866                 Location l = (Location) oob_stack.Pop ();
2867                 Block b = end_block();
2868                 Expression e = (Expression) $3;
2869                 $$ = new While ((Expression) e, (Statement) b, l);
2870         }
2871         ;
2872         
2873                 
2874 for_statement
2875         : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2876           {
2877                 start_block();
2878           }
2879           opt_statement_list
2880           NEXT opt_identifier 
2881           {
2882                 Block statement = end_block();
2883                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2884                 
2885                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2886                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
2887                                                 for_var, (Expression) $6, lexer.Location);
2888                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2889                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
2890                                  
2891                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
2892                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2893                 
2894                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
2895           }       
2896         ;
2897
2898 opt_step
2899         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
2900         | STEP expression       { $$ = $2; }
2901         ;
2902
2903 selection_statement
2904         : if_statement
2905         | select_statement
2906         ;
2907
2908 if_statement
2909         : if_statement_open opt_then if_statement_rest
2910           {
2911                 $$ = $3;
2912           }
2913         | if_statement_open THEN pre_embedded_statement
2914           {
2915                 Location l = (Location) oob_stack.Pop ();
2916                 tmp_expr = (Expression)expr_stack.Pop(); 
2917                 $$ = new If ((Expression) tmp_expr, end_block(), l);
2918           }
2919         ;
2920
2921 pre_embedded_statement
2922         : embedded_statement 
2923           {
2924                 Statement s = (Statement) $1;
2925
2926                 current_block.AddStatement ((Statement) $1);
2927           } 
2928         ;       
2929         
2930 if_statement_open
2931         : IF boolean_expression 
2932           {
2933                 oob_stack.Push (lexer.Location);
2934                 start_block();
2935                 tmp_expr = (Expression) $2;
2936                 expr_stack.Push(tmp_expr);
2937           }
2938          ;
2939
2940 opt_then
2941         : /* empty */
2942         | THEN
2943         ;
2944         
2945 if_statement_rest
2946         : end_of_stmt
2947           opt_statement_list
2948           END IF
2949           { 
2950                 Location l = (Location) oob_stack.Pop ();
2951                 Expression expr = (Expression)expr_stack.Pop(); 
2952                 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2953           }       
2954         | end_of_stmt
2955           opt_statement_list
2956           ELSE end_of_stmt 
2957           { 
2958                 Block bl = end_block(); 
2959                 tmp_blocks.Push(bl); 
2960                 start_block();
2961           }
2962           opt_statement_list
2963           END IF        
2964           {
2965                 Location l = (Location) oob_stack.Pop ();
2966                 tmp_expr = (Expression)expr_stack.Pop(); 
2967                 tmp_block = (Block) tmp_blocks.Pop(); 
2968                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2969           }     
2970         | end_of_stmt
2971           opt_statement_list 
2972           ELSEIF boolean_expression opt_then 
2973           { 
2974                 tmp_expr = (Expression) $4;                                                  
2975                 expr_stack.Push(tmp_expr);                                                 
2976                 tmp_block = end_block();
2977                 tmp_blocks.Push(tmp_block);
2978                 start_block();
2979           }
2980           else_if_statement_rest 
2981           {
2982                 Statement stmt = (Statement) statement_stack.Pop();
2983                 Block bl = (Block) tmp_blocks.Pop();  
2984                 Expression expr =  (Expression)expr_stack.Pop();  
2985                 Location l = (Location) oob_stack.Pop ();
2986                 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l); 
2987           }
2988         ;
2989         
2990         
2991 else_if_statement_rest
2992         : end_of_stmt
2993           opt_statement_list 
2994           END IF
2995           { 
2996                 Location l = (Location) oob_stack.Pop ();
2997                 oob_stack.Push (l);
2998                 Expression expr = (Expression)expr_stack.Pop(); 
2999                 Statement stmt = (Statement) new If ((Expression) expr, (Statement)  end_block(), l);
3000                 statement_stack.Push(stmt);
3001           }
3002         | end_of_stmt
3003           opt_statement_list
3004           ELSE end_of_stmt 
3005           { 
3006                 Block bl = end_block();
3007                 tmp_blocks.Push(bl);
3008                 start_block();
3009           }
3010           opt_statement_list
3011           END IF        
3012           {
3013                 Location l = (Location) oob_stack.Pop ();
3014                 oob_stack.Push (l);
3015                 Expression expr = (Expression)expr_stack.Pop(); 
3016                 Block bl = (Block)tmp_blocks.Pop(); 
3017                 Statement stmt = (Statement) new If ((Expression) expr,  (Statement) bl , (Statement)  end_block(), l);
3018                 statement_stack.Push(stmt);
3019           }     
3020         | end_of_stmt
3021           opt_statement_list 
3022           ELSEIF boolean_expression opt_then 
3023           { 
3024                 expr_stack.Push((Expression) $4);                                                 
3025                 Block bl = end_block();
3026                 tmp_blocks.Push(bl);
3027                 start_block();
3028           }
3029           else_if_statement_rest 
3030           {
3031                 Location l = (Location) oob_stack.Pop ();
3032                 oob_stack.Push (l);
3033                 Statement tmp_stmt = (Statement)statement_stack.Pop();
3034                 Block bl = (Block) tmp_blocks.Pop();  
3035                 Expression expr =  (Expression)expr_stack.Pop();  
3036                 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
3037                 statement_stack.Push(stmt);
3038           }          
3039         ;
3040         
3041 select_statement
3042         : SELECT opt_case expression end_of_stmt
3043           { 
3044                 oob_stack.Push (lexer.Location);
3045                 switch_stack.Push (current_block);
3046           }     
3047           opt_case_sections
3048           END SELECT 
3049           {
3050                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
3051                 current_block = (Block) switch_stack.Pop ();
3052           }       
3053         ;
3054
3055 opt_case_sections
3056         : /* empty */   { $$ = null; }
3057         | case_sections { $$ = $1; }
3058         ;
3059         
3060 case_sections
3061         : case_sections case_section
3062           {
3063                 ArrayList sections = (ArrayList) $1;
3064
3065                 sections.Add ($2);
3066                 $$ = sections;
3067           }
3068         | case_section
3069           {
3070                 ArrayList sections = new ArrayList ();
3071
3072                 sections.Add ($1);
3073                 $$ = sections;
3074           }
3075         ;
3076
3077 ends 
3078         : end_of_stmt
3079         | ends end_of_stmt
3080         ;
3081         
3082
3083 case_section
3084         : CASE case_clauses ends
3085           { 
3086                 start_block();
3087           }
3088           opt_statement_list
3089           {
3090                 //Block topmost = current_block;
3091                 Block topmost = end_block();
3092                 
3093                 while (topmost.Implicit)
3094                         topmost = topmost.Parent;
3095                         
3096                 // FIXME: This is a horrible hack which MUST go                 
3097                 topmost.statements.Add (new Break (lexer.Location));
3098                 $$ = new SwitchSection ((ArrayList) $2, topmost);
3099           }
3100           | CASE ELSE ends
3101             /* FIXME: we should somehow flag an error 
3102                (BC30321 'Case' cannot follow a 'Case Else' 
3103                in the same 'Select' statement.) 
3104                if Case Else is not the last of the Case clauses
3105             */
3106           { 
3107                 start_block();
3108           }     
3109           opt_statement_list
3110           { 
3111                 //Block topmost = current_block;
3112                 Block topmost = end_block();
3113
3114                 while (topmost.Implicit)
3115                         topmost = topmost.Parent;
3116                         
3117                 // FIXME: This is a horrible hack which MUST go                 
3118                 topmost.statements.Add (new Break (lexer.Location));
3119                 
3120                 ArrayList a = new ArrayList();
3121                 a.Add (new SwitchLabel (null, lexer.Location));                 
3122                 $$ = new SwitchSection ((ArrayList) a, topmost);                
3123           }
3124         ;         
3125         
3126 case_clauses
3127         : case_clause
3128           {
3129                 ArrayList labels = new ArrayList ();
3130
3131                 labels.Add ($1);
3132                 $$ = labels;
3133           }     
3134         | case_clauses COMMA case_clause
3135           {
3136                 ArrayList labels = (ArrayList) ($1);
3137                 labels.Add ($2);
3138
3139                 $$ = labels;
3140           }     
3141         ;
3142         
3143 case_clause
3144         : opt_is comparison_operator expression
3145         | expression
3146           {
3147                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
3148           }
3149         ;
3150         
3151 opt_is 
3152         : /* empty */
3153         | IS
3154         ;
3155
3156 comparison_operator
3157         : OP_LT
3158         | OP_GT
3159         | OP_LE
3160         | OP_NE
3161         /*| OP_EQ */
3162         ;
3163
3164 opt_case
3165         : /* empty */
3166         | CASE
3167         ;
3168
3169 expression_statement
3170         : statement_expression 
3171           {
3172                  $$ = $1; 
3173           }
3174         ;
3175
3176
3177 statement_expression
3178         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
3179         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
3180         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
3181         ;
3182
3183 object_creation_expression
3184         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
3185           {
3186                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
3187           }
3188         | NEW type
3189           {
3190                 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
3191           }
3192         ;
3193         
3194 array_creation_expression
3195         : object_creation_expression array_initializer
3196           {
3197                 New n = (New) $1;
3198                 ArrayList dims = new ArrayList();
3199                 
3200                 if (n.Arguments != null) {
3201                         foreach (Argument a in n.Arguments) {
3202                                 dims.Add (a.Expr);
3203                         }
3204                 }
3205                         
3206                 Expression atype = n.RequestedType;
3207
3208                 ArrayList init = (ArrayList) $2;
3209                 if (init.Count == 0)
3210                         init = null;
3211         
3212                 if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
3213                         VariableDeclaration.VBFixIndexList (ref dims);
3214                         $$ = new ArrayCreation (atype, dims, "", init, lexer.Location); 
3215                 }
3216                 else
3217                 {
3218                         string rank = VariableDeclaration.BuildRank (dims);
3219                         $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location); 
3220                 }
3221                 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
3222           }
3223         ;       
3224
3225 new_expression
3226         : object_creation_expression
3227         | array_creation_expression
3228         ;
3229
3230 declaration_statement
3231         : local_variable_declaration 
3232           {
3233                 if ($1 != null){
3234                         DictionaryEntry de = (DictionaryEntry) $1;
3235
3236                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
3237                 }
3238           }
3239         | local_constant_declaration 
3240           {
3241                 if ($1 != null){
3242                         DictionaryEntry de = (DictionaryEntry) $1;
3243
3244                         $$ = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value);
3245                 }
3246           }
3247         ;        
3248         
3249 local_variable_declaration
3250         : DIM variable_declarators
3251           {
3252                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
3253           }
3254         ;
3255
3256         
3257 local_constant_declaration
3258         : CONST constant_declarators
3259           {
3260                 if ($2 != null)
3261                         $$ = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), $2);
3262                 else
3263                         $$ = null;
3264           }
3265         ;        
3266         
3267 constant_declarators
3268         : constant_declarator 
3269           {
3270                 ArrayList decl = new ArrayList ();
3271                 if ($1 != null) 
3272                         decl.Add ($1);
3273                         
3274                 $$ = decl;
3275           }
3276         | constant_declarators COMMA constant_declarator
3277           {
3278                 ArrayList decls = (ArrayList) $1;
3279                 if ($3 != null)
3280                         decls.Add ($3);
3281
3282                 $$ = $1;
3283           }
3284         ;
3285
3286 constant_declarator
3287         : variable_name opt_type_decl opt_variable_initializer
3288           {
3289                 VarName vname = (VarName) $1;
3290                 string varname = (string) vname.Name;
3291                 current_rank_specifiers = (ArrayList) vname.Rank;
3292                 object varinit = $3;
3293                 ArrayList a_dims = null;
3294
3295                 if (varinit == null)
3296                         Report.Error (
3297                                 30438, lexer.Location, "Constant should have a value"
3298                                 );
3299
3300                 if (vname.Type != null && $2 != null)
3301                         Report.Error (
3302                                 30302, lexer.Location, 
3303                                 "Type character cannot be used with explicit type declaration" );
3304
3305                 Expression vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3306
3307                 if (current_rank_specifiers != null) 
3308                 {
3309                         Report.Error (30424, lexer.Location, "Constant doesn't support array");
3310                         $$ = null;
3311                 }
3312                 else
3313                         $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
3314           }
3315         ;               
3316
3317 variable_declarators
3318         : variable_declarator 
3319           {
3320                 ArrayList decl = new ArrayList ();
3321                 decl.AddRange ((ArrayList) $1);
3322                 $$ = decl;
3323           }
3324         | variable_declarators COMMA variable_declarator
3325           {
3326                 ArrayList decls = (ArrayList) $1;
3327                 decls.AddRange ((ArrayList) $3);
3328                 $$ = $1;
3329           }
3330         ;
3331
3332 variable_declarator
3333         : variable_names opt_type_decl opt_variable_initializer
3334           {
3335             ArrayList names = (ArrayList) $1;
3336                 object varinit = $3;
3337                 ArrayList VarDeclarations = new ArrayList();
3338                 Expression vartype;
3339                 ArrayList a_dims = null;
3340
3341                 if ((names.Count > 1) && (varinit != null)) 
3342                         Report.Error (
3343                                 30671, lexer.Location, 
3344                                 "Multiple variables with single type can not have " +
3345                                 "a explicit initialization" );
3346
3347                                 
3348                 foreach (VarName vname in names)
3349                 {
3350                         string varname = (string) vname.Name;
3351                         current_rank_specifiers = (ArrayList) vname.Rank;
3352                         a_dims = null;
3353                         varinit = $3;
3354
3355                         if(vname.Type != null && $2 != null)
3356                                 Report.Error (
3357                                         30302, lexer.Location, 
3358                                         "Type character cannot be used with explicit type declaration" );
3359
3360                         // Some checking is required for particularly weird declarations
3361                         // like Dim a As Integer(,)
3362                         if ($2 is Pair) {
3363                                 vartype = (Expression) ((Pair) $2).First;
3364                                 
3365                                 /*if ($3 != null && $3 is ArrayList)
3366                                         Report.Error (205, "End of statement expected.");*/
3367                                         
3368                                 ArrayList args = (ArrayList) ((Pair) $2).Second;
3369                                 if (current_rank_specifiers != null)
3370                                         Report.Error (31087, lexer.Location,
3371                                                  "Array types specified in too many places");   
3372                                 
3373                                 if (VariableDeclaration.IndexesSpecifiedInRank (args))            
3374                                         Report.Error (30638, "Array bounds cannot appear in type specifiers."); 
3375                                 
3376                                 current_rank_specifiers = new ArrayList ();
3377                                 current_rank_specifiers.Add (args);
3378                                 
3379                                 /*string s_vartype = vartype.ToString();                                
3380                                 s_vartype += "[";
3381                                 if (args != null)
3382                                         for (int x = 0; x < args.Count; x++)
3383                                                 s_vartype += ",";
3384                                         
3385                                 s_vartype += "]";       
3386                                 vartype = DecomposeQI(s_vartype, Location.Null);        */
3387                         }
3388                         else
3389                                 vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
3390
3391                         // if the variable is an array with explicit bound
3392                         // and having explicit initialization throw exception
3393                         if (current_rank_specifiers != null && varinit != null) 
3394                         {
3395                                 bool broken = false;
3396                                 foreach (ArrayList exprs in current_rank_specifiers)
3397                                 {
3398                                         foreach (Expression expr in exprs)
3399                                         {
3400                                                 if (!((Expression)expr is EmptyExpression ))
3401                                                 {
3402                                                         Report.Error (
3403                                                                 30672, lexer.Location, 
3404                                                                 "Array declared with explicit bound " +
3405                                                                 " can not have explicit initialization");
3406                                                         broken = true;
3407                                                         break;
3408                                                 }
3409                                         }
3410                                         if (broken)
3411                                                 break;
3412                                 }
3413                         }
3414                         
3415                         /*
3416                         Check for a declaration like Dim a(2) or Dim a(2,3)
3417                         If this is the case, we must generate an ArrayCreationExpression
3418                         and, in case, add the initializer after the array has been created.
3419                         */
3420                         if (VariableDeclaration.IsArrayDecl (this)) {   
3421                                 if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) {   
3422                                         a_dims = (ArrayList) current_rank_specifiers;
3423                                         VariableDeclaration.VBFixIndexLists (ref a_dims);
3424                                         varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
3425                                 }
3426                                 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
3427                         }
3428
3429                         if (vartype is New) {
3430                                 if (varinit != null) {
3431                                         Report.Error (30205, lexer.Location, "End of statement expected");
3432                                         $$ = null;
3433                                 }
3434                                 else
3435                                 {
3436                                         varinit = vartype;
3437                                         vartype = ((New)vartype).RequestedType;
3438                                 }
3439                         }
3440                         VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null));
3441             }// end of for
3442             $$ = VarDeclarations;
3443           } 
3444         ;
3445
3446 variable_names
3447         : variable_name
3448           {
3449                 ArrayList list = new ArrayList ();
3450                 list.Add ($1);
3451                 $$ = list;
3452           }
3453         | variable_names COMMA variable_name
3454           {
3455                 ArrayList list = (ArrayList) $1;
3456                 list.Add ($3);
3457                 $$ = list;
3458           }
3459         ;
3460         
3461 variable_name
3462         : identifier opt_type_character opt_array_name_modifier
3463           {
3464                 $$ = new VarName ($1, $2, $3);
3465           }
3466         ;
3467
3468 opt_type_spec
3469         : /* empty */   
3470           { 
3471                 $$ = null;              
3472           }
3473         | AS type       
3474           { 
3475                 $$ = (Expression) $2;
3476           }
3477         ;
3478                 
3479 opt_type_with_ranks
3480         : opt_type_spec 
3481         | AS type rank_specifiers
3482           {
3483                 $$ = TypeManager.system_object_expr; 
3484           }
3485         ;
3486         
3487 opt_type_decl
3488         : opt_type_spec
3489           {
3490                 $$ = $1;
3491           }
3492         | AS type OPEN_PARENS /*opt_argument_list*/ opt_dim_separators CLOSE_PARENS
3493           {
3494                 $$ = new Pair ($2, $4);
3495           }
3496         | AS NEW type
3497           {
3498                 New n = new New ((Expression)$3, null, lexer.Location);
3499                 $$ = (Expression) n;
3500           }
3501         | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS 
3502           {
3503                 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
3504                 $$ = (Expression) n;
3505           }
3506         /*| AS NEW type OPEN_PARENS ADDRESSOF expression CLOSE_PARENS 
3507           {
3508             ArrayList args = new ArrayList();
3509                 Argument arg = new Argument ((Expression) $6, Argument.AType.Expression);
3510                 args.Add (arg);
3511                 
3512                 New n = new New ((Expression)$3, (ArrayList) args, lexer.Location);
3513                 $$ = (Expression) n;
3514           }*/
3515         ;
3516                 
3517 opt_array_name_modifier
3518         : /* empty */                           { $$ = null; }
3519         | array_type_modifier                   { $$ = $1;   }
3520         ;
3521         
3522 array_type_modifier
3523         : rank_specifiers               { $$ = $1; }
3524         ;
3525         
3526 opt_variable_initializer
3527         : /* empty */                   { $$ = null; }
3528         | ASSIGN variable_initializer   { $$ = $2; }
3529         ;
3530                 
3531 variable_initializer
3532         : expression
3533           {
3534                 $$ = $1;
3535           }
3536         | array_initializer
3537           {
3538                 $$ = $1;
3539           }
3540         
3541         ;       
3542         
3543 array_initializer
3544         : OPEN_BRACE CLOSE_BRACE
3545           {
3546                 ArrayList list = new ArrayList ();
3547                 $$ = list;
3548           }
3549         | OPEN_BRACE variable_initializer_list CLOSE_BRACE
3550           {
3551                 $$ = (ArrayList) $2;
3552           }
3553         ;
3554
3555 variable_initializer_list
3556         : variable_initializer
3557           {
3558                 ArrayList list = new ArrayList ();
3559                 list.Add ($1);
3560                 $$ = list;
3561           }
3562         | variable_initializer_list COMMA variable_initializer
3563           {
3564                 ArrayList list = (ArrayList) $1;
3565                 list.Add ($3);
3566                 $$ = list;
3567           }
3568         ;
3569
3570 opt_rank_specifiers
3571         : /* empty */
3572           {
3573                   // $$ = "";
3574                   $$ = null;
3575           }
3576         | rank_specifiers
3577           {
3578                         $$ = $1;
3579           }
3580         ;      
3581         
3582 rank_specifiers
3583         : rank_specifier
3584           {
3585                   ArrayList rs = new ArrayList();
3586                   rs.Add ($1);
3587                   $$ = rs;
3588           }
3589         | rank_specifiers rank_specifier
3590           {
3591                   ArrayList rs = (ArrayList) $1;
3592                   rs.Add ($2);
3593                   $$ = rs;
3594           }             
3595         ;               
3596         
3597 rank_specifier
3598         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
3599           {
3600                 $$ = $2;
3601           }
3602         ;
3603                 
3604 opt_dim_separators
3605         : /* empty */
3606           {
3607                 ArrayList ds = new ArrayList();
3608                 ds.Add (new EmptyExpression());
3609                 $$ = ds;                
3610           }
3611         | dim_separators
3612           {
3613                 ArrayList ds = (ArrayList) $1;
3614                 ds.Add (new EmptyExpression());
3615                 $$ = ds;        
3616           }     
3617         | dim_specifiers
3618           {
3619                 $$ = $1;
3620           }       
3621         ;
3622
3623 dim_separators
3624         : COMMA
3625           {
3626                 ArrayList ds = new ArrayList();
3627                 ds.Add (new EmptyExpression());
3628                 $$ = ds;
3629           }
3630         | dim_separators COMMA
3631           {
3632                 ArrayList ds = (ArrayList) $1;
3633                 ds.Add (new EmptyExpression());
3634                 $$ = ds;                
3635           }
3636         ;
3637
3638 dim_specifiers
3639         : expression
3640           {
3641                 ArrayList ds = new ArrayList();
3642                 ds.Add ((Expression) $1);
3643                 $$ = ds;
3644           }     
3645         | dim_specifiers COMMA expression
3646           {
3647                 ArrayList ds = (ArrayList) $1;
3648                 ds.Add ((Expression) $3);
3649                 $$ = ds;                
3650           }     
3651         ;
3652         
3653 primary_expression
3654         : literal
3655           {
3656                 //TODO
3657           }
3658         | parenthesized_expression
3659         | this_access
3660         | base_access
3661         | qualified_identifier
3662           {
3663                 string name = (string) $1;
3664                 $$ = DecomposeQI (name, lexer.Location);
3665           }
3666         //FIXME: address_of_expression is apparently missing here
3667         | get_type_expression
3668         | member_access
3669         | invocation_expression
3670         //| element_access
3671         | new_expression
3672         | cast_expression
3673         ;
3674
3675 literal
3676         : boolean_literal
3677         | integer_literal
3678         | real_literal
3679         | LITERAL_DATE                  { $$ = new DateLiteral ((DateTime)lexer.Value); }
3680         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
3681         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
3682         | NOTHING                               { $$ = NullLiteral.Null; }
3683         ;
3684
3685 real_literal
3686         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
3687         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
3688         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3689         ;
3690
3691 integer_literal
3692         : LITERAL_INTEGER       {
3693                 object v = lexer.Value;
3694
3695                 if (v is int)
3696                         $$ = new IntLiteral ((Int32)v); 
3697                 else if (v is short)
3698                         $$ = new ShortLiteral ((Int16)v);
3699                 else if (v is long)
3700                         $$ = new LongLiteral ((Int64)v);
3701                 else
3702                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
3703                         
3704           }
3705         ;
3706
3707 boolean_literal
3708         : TRUE                  { $$ = new BoolLiteral (true); }
3709         | FALSE                 { $$ = new BoolLiteral (false); }
3710         ;
3711
3712 parenthesized_expression
3713         : OPEN_PARENS expression CLOSE_PARENS
3714           { $$ = $2; }
3715         ;
3716
3717 member_access
3718         : primary_expression DOT identifier
3719           {
3720                 if ($1 != null) {
3721                         string id_name = (string)$3;
3722                         if (id_name.ToUpper() == "NEW")
3723                                 id_name = ".ctor";
3724                         $$ = new MemberAccess ((Expression) $1, id_name, lexer.Location);
3725                 }
3726                 else
3727                 {
3728                         if (with_stack.Count > 0) {
3729                                 Expression e = (Expression) with_stack.Peek();
3730                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3731                         }
3732                         else
3733                         {
3734                                 // OOps
3735                         }
3736                 }
3737           }
3738 /*      | primary_expression DOT NEW
3739           {
3740                 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3741           }       */
3742         | predefined_type DOT identifier
3743           {
3744                 if ($1 != null)
3745                         $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3746                 else
3747                 {
3748                         if (with_stack.Count > 0) {
3749                                 Expression e = (Expression) with_stack.Peek();
3750                                 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3751                         }
3752                         else
3753                         {
3754                                 // OOps
3755                         }
3756                 }
3757           }
3758         ;
3759
3760 predefined_type
3761         : builtin_types
3762         ;
3763
3764 invocation_expression
3765         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3766           {
3767                 if ($1 == null) {
3768                         Location l = lexer.Location;
3769                         Report.Error (1, l, "THIS IS CRAZY");
3770                 }
3771                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3772 //              Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3773           } 
3774         ;
3775         
3776 base_access
3777         : MYBASE DOT IDENTIFIER
3778           {
3779                 string id_name = (string) $3;
3780                 if (id_name.ToUpper() == "NEW")
3781                         id_name = "New";
3782                 $$ = new BaseAccess (id_name, lexer.Location);
3783           }
3784 /*      | MYBASE DOT NEW
3785           {
3786                 $$ = new BaseAccess ("New", lexer.Location);
3787           }*/
3788         ;       
3789
3790 opt_argument_list
3791         : argument_list
3792           { 
3793                 /*
3794                    The 'argument' rule returns an 'empty' argument
3795                    of type NoArg (used for default arguments in invocations)
3796                    if no arguments are actually passed.
3797
3798                    If there is only one argument and it is o type NoArg,
3799                    we return a null (empty) list
3800                 */
3801                 ArrayList args = (ArrayList) $1;
3802                 if (args.Count == 1 &&
3803                     ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3804                         $$ = null;
3805                 else
3806                         $$ = $1;
3807           }
3808         ;
3809
3810 argument_list
3811         : argument
3812           {
3813                 ArrayList list = new ArrayList ();
3814                 list.Add ($1);
3815                 $$ = list;
3816           }
3817         | argument_list COMMA argument
3818           {
3819                 ArrayList list = (ArrayList) $1;
3820                 list.Add ($3);
3821                 $$ = list;
3822           }
3823         ;
3824
3825 argument
3826         : expression
3827           {
3828                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3829           }
3830         | BYREF variable_reference
3831           {
3832                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3833           }
3834         | /* empty */
3835           {
3836                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3837           }
3838         | ADDRESSOF expression
3839           {
3840                 $$ = new Argument ((Expression) $2, Argument.AType.AddressOf);
3841           }
3842         ;
3843
3844 variable_reference
3845         : expression {/* note ("section 5.4"); */  $$ = $1;  }
3846         ;
3847
3848                 
3849 expression
3850         : conditional_xor_expression { $$ = $1; }
3851         /*| assignment_expression*/
3852         ;
3853
3854 opt_expression
3855         : /* empty */
3856         | expression
3857         ;
3858                 
3859 this_access
3860         : ME
3861           {
3862                 $$ = new This (current_block, lexer.Location);
3863           }
3864         | MYCLASS
3865           {
3866                 // FIXME: This is actually somewhat different from Me
3867                 // because it is for accessing static (classifier) methods/properties/fields
3868                 $$ = new This (current_block, lexer.Location);
3869           }
3870         ;
3871
3872 cast_expression
3873         : DIRECTCAST OPEN_PARENS expression COMMA type CLOSE_PARENS
3874           {
3875                 // TODO
3876           } 
3877         | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3878           {
3879                   $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3880           }     
3881         | cast_operator OPEN_PARENS expression CLOSE_PARENS
3882           {
3883                   $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3884           }     
3885         ;
3886         
3887 cast_operator
3888         : CBOOL         { $$ = TypeManager.system_boolean_expr;         }
3889         | CBYTE         { $$ = TypeManager.system_byte_expr;            }
3890         | CCHAR         { $$ = TypeManager.system_char_expr;            }
3891         | CDATE         { $$ = TypeManager.system_date_expr;            }
3892         | CDBL          { $$ = TypeManager.system_double_expr;          }
3893         | CDEC          { $$ = TypeManager.system_decimal_expr;         }
3894         | CINT          { $$ = TypeManager.system_int32_expr;           }
3895         | CLNG          { $$ = TypeManager.system_int64_expr;           }
3896         | COBJ          { $$ = TypeManager.system_object_expr;          }
3897         | CSHORT        { $$ = TypeManager.system_int16_expr;           }
3898         | CSNG          { $$ = TypeManager.system_single_expr;          }
3899         | CSTR          { $$ = TypeManager.system_string_expr;  }
3900         ;
3901
3902 get_type_expression
3903         : GETTYPE OPEN_PARENS type CLOSE_PARENS
3904           {
3905                 $$ = new TypeOf ((Expression) $3, lexer.Location);
3906           }
3907         ;
3908         
3909 exponentiation_expression
3910         : primary_expression
3911         | exponentiation_expression OP_EXP primary_expression
3912           {
3913                 //TODO
3914           }                             
3915         ;
3916         
3917 prefixed_unary_expression
3918         : exponentiation_expression
3919         | PLUS prefixed_unary_expression
3920           {
3921                 //FIXME: Is this rule correctly defined ?
3922                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3923           }
3924         | MINUS prefixed_unary_expression
3925           {
3926                 //FIXME: Is this rule correctly defined ?
3927                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3928           }
3929         ;
3930
3931 multiplicative_expression
3932         : prefixed_unary_expression
3933         | multiplicative_expression STAR prefixed_unary_expression
3934           {
3935                 $$ = new Binary (Binary.Operator.Multiply,
3936                                  (Expression) $1, (Expression) $3, lexer.Location);
3937           }
3938         | multiplicative_expression DIV prefixed_unary_expression
3939           {
3940                 $$ = new Binary (Binary.Operator.Division,
3941                                  (Expression) $1, (Expression) $3, lexer.Location);
3942           }
3943         ;
3944
3945 integer_division_expression
3946         : multiplicative_expression
3947         | integer_division_expression OP_IDIV multiplicative_expression
3948           {
3949                 //FIXME: Is this right ?
3950                 $$ = new Binary (Binary.Operator.Division,
3951                            (Expression) $1, (Expression) $3, lexer.Location);
3952           }
3953         ;
3954
3955 mod_expression
3956         : integer_division_expression
3957         | mod_expression MOD integer_division_expression
3958           {
3959               $$ = new Binary (Binary.Operator.Modulus,
3960                                (Expression) $1, (Expression) $3, lexer.Location);
3961           }
3962         ;
3963         
3964 additive_expression
3965         : mod_expression
3966         | additive_expression PLUS mod_expression
3967           {
3968                 $$ = new Binary (Binary.Operator.Addition,
3969                                  (Expression) $1, (Expression) $3, lexer.Location);
3970           }
3971         | additive_expression MINUS mod_expression
3972           {
3973                 $$ = new Binary (Binary.Operator.Subtraction,
3974                                  (Expression) $1, (Expression) $3, lexer.Location);
3975           }
3976         ;
3977
3978 concat_expression
3979         : additive_expression
3980         | concat_expression OP_CONCAT additive_expression
3981           {
3982               // FIXME: This should only work for String expressions
3983               // We probably need to use something from the runtime
3984               $$ = new Binary (Binary.Operator.Addition,
3985                                (Expression) $1, (Expression) $3, lexer.Location);
3986           }     
3987         ;
3988
3989 shift_expression
3990         : concat_expression
3991         | shift_expression OP_SHIFT_LEFT concat_expression
3992           {
3993                 // TODO
3994           }
3995         | shift_expression OP_SHIFT_RIGHT concat_expression
3996           {
3997                 //TODO
3998           }
3999         ;
4000
4001 relational_expression
4002         : shift_expression
4003         | relational_expression ASSIGN shift_expression
4004           {
4005                 $$ = new Binary (Binary.Operator.Equality,
4006                                  (Expression) $1, (Expression) $3, lexer.Location);
4007           }
4008         | relational_expression OP_NE shift_expression
4009           {
4010                 $$ = new Binary (Binary.Operator.Inequality, 
4011                                  (Expression) $1, (Expression) $3, lexer.Location);
4012           }       
4013         | relational_expression OP_LT shift_expression
4014           {
4015                 $$ = new Binary (Binary.Operator.LessThan,
4016                                  (Expression) $1, (Expression) $3, lexer.Location);
4017           }
4018         | relational_expression OP_GT shift_expression
4019           {
4020                 $$ = new Binary (Binary.Operator.GreaterThan,
4021                                  (Expression) $1, (Expression) $3, lexer.Location);
4022           }
4023         | relational_expression OP_LE shift_expression
4024           {
4025                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
4026                                  (Expression) $1, (Expression) $3, lexer.Location);
4027           }
4028         | relational_expression OP_GE shift_expression
4029           {
4030                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
4031                                  (Expression) $1, (Expression) $3, lexer.Location);
4032           }
4033         | relational_expression IS shift_expression
4034           {
4035                 //FIXME: Should be a different op for reference equality but allows tests to use Is
4036                 $$ = new Binary (Binary.Operator.Equality,
4037                                  (Expression) $1, (Expression) $3, lexer.Location);
4038           }
4039         | TYPEOF shift_expression IS type
4040           {
4041                 //FIXME: Is this rule correctly defined ?
4042                 $$ = new Is ((Expression) $2, (Expression) $4, lexer.Location);
4043           }
4044         ;
4045
4046 negation_expression
4047         : relational_expression
4048         | NOT negation_expression 
4049           {
4050                 //FIXME: Is this rule correctly defined ?
4051                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
4052           }
4053         ;
4054         
4055 conditional_and_expression
4056         : negation_expression
4057         | conditional_and_expression AND negation_expression
4058           {
4059                 $$ = new Binary (Binary.Operator.LogicalAnd,
4060                                  (Expression) $1, (Expression) $3, lexer.Location);
4061           }
4062         | conditional_and_expression ANDALSO negation_expression
4063           {     // FIXME: this is likely to be broken
4064                 $$ = new Binary (Binary.Operator.LogicalAnd,
4065                                  (Expression) $1, (Expression) $3, lexer.Location);
4066           }
4067         ;
4068
4069 conditional_or_expression
4070         : conditional_and_expression
4071         | conditional_or_expression OR conditional_and_expression
4072           {
4073                 $$ = new Binary (Binary.Operator.LogicalOr,
4074                                  (Expression) $1, (Expression) $3, lexer.Location);
4075           }
4076         | conditional_or_expression ORELSE conditional_and_expression
4077           {     // FIXME: this is likely to be broken
4078                 $$ = new Binary (Binary.Operator.LogicalOr,
4079                                  (Expression) $1, (Expression) $3, lexer.Location);
4080           }
4081         ;
4082
4083 conditional_xor_expression
4084         : conditional_or_expression
4085         | conditional_xor_expression XOR conditional_or_expression
4086         {
4087               $$ = new Binary (Binary.Operator.ExclusiveOr,
4088                                (Expression) $1, (Expression) $3, lexer.Location);
4089         }
4090         ;
4091
4092 assignment_expression
4093         : prefixed_unary_expression ASSIGN expression
4094           { 
4095                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
4096           }
4097         | prefixed_unary_expression ASSIGN ADDRESSOF expression
4098           { 
4099             ArrayList args = new ArrayList();
4100                 Argument arg = new Argument ((Expression) $4, Argument.AType.Expression);
4101                 args.Add (arg);
4102                 
4103                 New n = new New ((Expression) $1, (ArrayList) args, lexer.Location);
4104                 n.isDelegate = true;
4105                 $$ = new Assign ((Expression) $1, (Expression) n, lexer.Location);
4106           }
4107         ;
4108
4109 constant_expression
4110         : expression
4111         ;
4112
4113 boolean_expression
4114         : expression
4115         ;
4116
4117 type
4118         : namespace_or_type_name 
4119           {     
4120                 $$ = DecomposeQI ((string) $1, lexer.Location); 
4121           }
4122         | builtin_types 
4123         //| array_type 
4124         ;
4125
4126 type_list
4127         : type
4128           {
4129                 ArrayList types = new ArrayList ();
4130
4131                 types.Add ($1);
4132                 $$ = types;
4133           }
4134         | type_list COMMA type
4135           {
4136                 ArrayList types = (ArrayList) $1;
4137
4138                 types.Add ($3);
4139                 $$ = types;
4140           }
4141         ;
4142
4143 namespace_or_type_name
4144         : qualified_identifier
4145         ;
4146
4147 builtin_types
4148         : OBJECT        { $$ = TypeManager.system_object_expr; }
4149         | primitive_type
4150         ;
4151
4152 primitive_type
4153         : numeric_type
4154         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
4155         | DATE          { $$ = TypeManager.system_date_expr; }
4156         | CHAR          { $$ = TypeManager.system_char_expr; }
4157         | STRING        { $$ = TypeManager.system_string_expr; }
4158         ;
4159         
4160
4161 numeric_type
4162         : integral_type
4163         | floating_point_type
4164         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
4165         ;
4166
4167 integral_type
4168         :
4169         | BYTE          { $$ = TypeManager.system_byte_expr; }
4170         | SHORT         { $$ = TypeManager.system_int16_expr; }
4171         | INTEGER       { $$ = TypeManager.system_int32_expr; }
4172         | LONG          { $$ = TypeManager.system_int64_expr; }
4173         ;
4174         
4175 floating_point_type
4176         : SINGLE        { $$ = TypeManager.system_single_expr; }
4177         | DOUBLE        { $$ = TypeManager.system_double_expr; }
4178         ;
4179
4180 pp_directive
4181         : HASH IDENTIFIER OPEN_PARENS LITERAL_STRING COMMA LITERAL_INTEGER CLOSE_PARENS EOL
4182           { 
4183                 if(tokenizerController.IsAcceptingTokens)
4184                 {
4185                         if(in_external_source) 
4186                                 Report.Error (30580, lexer.Location, "#ExternalSource directives may not be nested");
4187                         else {
4188                                 in_external_source = true;
4189                         
4190                                 lexer.EffectiveSource = (string) $4;
4191                                 lexer.EffectiveLine = (int) $6;
4192                         }
4193                 }
4194           }
4195         | HASH IDENTIFIER LITERAL_STRING EOL
4196           {
4197                 if(tokenizerController.IsAcceptingTokens) 
4198                 {
4199                         string id = ($2 as string);
4200                 
4201                         if(!($2 as string).ToLower().Equals("region"))
4202                                 Report.Error (30205, lexer.Location, "Invalid Pre-processor directive");
4203                         else
4204                         {
4205                                 ++in_marked_region;
4206                         }
4207                 }
4208           }
4209         | HASH END IDENTIFIER EOL
4210           {
4211                 if(tokenizerController.IsAcceptingTokens)
4212                 {
4213                         if( ($3 as string).ToLower().Equals("externalsource")) {
4214                                 if(!in_external_source)
4215                                         Report.Error (30578, lexer.Location, "'#End ExternalSource' must be preceded by a matching '#ExternalSource'");
4216                                 else {
4217                                         in_external_source = false;
4218                                         lexer.EffectiveSource = lexer.Source;
4219                                         lexer.EffectiveLine = lexer.Line;
4220                                 }
4221                         }
4222                         else if(($3 as string).ToLower().Equals("region")) {
4223                                 if(in_marked_region > 0)
4224                                         --in_marked_region;
4225                                 else
4226                                         Report.Error (30205, lexer.Location, "'#End Region' must be preceded  by a matching '#Region'");
4227                         }
4228                         else {
4229                                 Report.Error (29999, lexer.Location, "Unrecognized Pre-Processor statement");
4230                         }       
4231                 }
4232           }
4233         | HASH CONST IDENTIFIER ASSIGN boolean_literal EOL
4234           {
4235                 if(tokenizerController.IsAcceptingTokens)
4236                 {
4237                         //TODO;
4238                 }
4239           }
4240         | HASH IF 
4241           {
4242                 IfElseStateMachine.Token tok = IfElseStateMachine.Token.IF;
4243
4244                 try {
4245                         ifElseStateMachine.HandleToken(tok);
4246                 }
4247                 catch(ApplicationException) {
4248                         throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
4249                 }
4250           }
4251            boolean_literal opt_then  EOL 
4252           {
4253                 HandleConditionalDirective(IfElseStateMachine.Token.IF, (BoolLiteral)$4);
4254           }
4255         | HASH ELSEIF 
4256           {
4257                       IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSEIF;
4258                       try {
4259                               ifElseStateMachine.HandleToken(tok);
4260                       }
4261                       catch(ApplicationException) {
4262                               throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
4263                       }
4264           }
4265            boolean_literal opt_then  EOL 
4266           { 
4267                   HandleConditionalDirective(IfElseStateMachine.Token.ELSEIF, (BoolLiteral)$4);
4268           }
4269         | HASH ELSE  
4270           {
4271                     IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSE;
4272                     try {
4273                             ifElseStateMachine.HandleToken(tok);
4274                     }
4275                     catch(ApplicationException) {
4276                             throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
4277                     }
4278           }
4279           EOL 
4280           { 
4281                 HandleConditionalDirective(IfElseStateMachine.Token.ELSE, new BoolLiteral(true));
4282           }
4283         | HASH END IF  
4284           {
4285                   IfElseStateMachine.Token tok = IfElseStateMachine.Token.ENDIF;
4286                   try {
4287                           ifElseStateMachine.HandleToken(tok);
4288                   }
4289                   catch(ApplicationException) {
4290                           throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
4291                   }
4292           }
4293           EOL 
4294           { 
4295                 HandleConditionalDirective(IfElseStateMachine.Token.ENDIF, new BoolLiteral(false));
4296           }
4297         | HASH error EOL          
4298         {
4299                 if(tokenizerController.IsAcceptingTokens)
4300                         Report.Error(2999, lexer.Location, "Unrecognized Pre-Processor statement");
4301                 else
4302                         Report.Warning (9999, lexer.Location,   "Unrecognized Pre-Processor statement");
4303         }
4304           
4305         ;               
4306
4307 %%
4308
4309
4310 Tokenizer lexer;
4311
4312 public Tokenizer Lexer {
4313         get {
4314                 return lexer;
4315         }
4316 }                  
4317
4318 public static Expression DecomposeQI (string name, Location loc)
4319 {
4320         Expression o;
4321
4322         if (name.IndexOf ('.') == -1){
4323                 return new SimpleName (name, loc);
4324         } else {
4325                 int pos = name.LastIndexOf (".");
4326                 string left = name.Substring (0, pos);
4327                 string right = name.Substring (pos + 1);
4328
4329                 o = DecomposeQI (left, loc);
4330
4331                 return new MemberAccess (o, right, loc);
4332         }
4333 }
4334
4335 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
4336 {
4337         Block implicit_block;
4338         ArrayList inits = null;
4339
4340         //
4341         // We use the `Used' property to check whether statements
4342         // have been added to the current block.  If so, we need
4343         // to create another block to contain the new declaration
4344         // otherwise, as an optimization, we use the same block to
4345         // add the declaration.
4346         //
4347         // FIXME: A further optimization is to check if the statements
4348         // that were added were added as part of the initialization
4349         // below.  In which case, no other statements have been executed
4350         // and we might be able to reduce the number of blocks for
4351         // situations like this:
4352         //
4353         // int j = 1;  int k = j + 1;
4354         //
4355         
4356         VariableDeclaration.FixupTypes (variable_declarators);
4357         
4358         if (current_block.Used) {
4359                 implicit_block = new Block (current_block, true, loc, Location.Null);
4360                 implicit_block.AddChildVariableNames (current_block);
4361         } else
4362                 implicit_block = current_block;
4363
4364         foreach (VariableDeclaration decl in variable_declarators){
4365                 Expression type = decl.type;
4366                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
4367                         if (decl.expression_or_array_initializer != null){
4368                                 if (inits == null)
4369                                         inits = new ArrayList ();
4370                                 inits.Add (decl);
4371                         }
4372                 }
4373         }
4374
4375         if (inits == null)
4376                 return implicit_block;
4377
4378         foreach (VariableDeclaration decl in inits){
4379                 Assign assign;
4380                 Expression expr;
4381                 Expression type = decl.type;
4382                 
4383                 if ((decl.expression_or_array_initializer is Expression) || 
4384                     (decl.expression_or_array_initializer is New)) {
4385                         expr = (Expression) decl.expression_or_array_initializer;
4386                 } else {
4387                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
4388                         
4389                         expr = new ArrayCreation (type, "", init, decl.Location);
4390                 }
4391
4392                 LocalVariableReference var;
4393                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
4394
4395                 assign = new Assign (var, expr, decl.Location);
4396
4397                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
4398         }
4399         
4400         return implicit_block;
4401 }
4402
4403 Block declare_local_constant (Expression dummy_type, ArrayList variable_declarators)
4404 {
4405         Block implicit_block;
4406         VariableDeclaration.FixupTypes (variable_declarators);
4407
4408         if (current_block.Used)
4409                 implicit_block = new Block (current_block, true);
4410         else
4411                 implicit_block = current_block;
4412
4413         foreach (VariableDeclaration decl in variable_declarators){
4414                 Expression type = decl.type;
4415                 implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
4416                                           current_local_parameters, decl.Location);
4417         }
4418         
4419         return implicit_block;
4420 }
4421
4422 struct VarName {
4423                 public object Name;
4424                 public object Type;
4425                 public object Rank;
4426                                                                                 
4427                 public VarName (object n, object t, object r)
4428                 {
4429                         Name = n;
4430                         Type = t;
4431                         Rank = r;
4432                 }
4433         }
4434
4435
4436 // <summary>
4437 //   A class used to pass around variable declarations and constants
4438 // </summary>
4439 public class VariableDeclaration {
4440         public string identifier;
4441         public object expression_or_array_initializer;
4442         public Location Location;
4443         public Attributes OptAttributes;
4444         public Expression type;
4445         public ArrayList dims;
4446                 
4447         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
4448         {
4449                 this.identifier = id;
4450                 this.expression_or_array_initializer = eoai;
4451                 this.Location = l;
4452                 this.OptAttributes = opt_attrs;
4453                 this.type = t;
4454                 this.dims = null;
4455         }       
4456
4457         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
4458         {
4459         }
4460         
4461         public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
4462         {
4463         }       
4464         
4465         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
4466                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
4467         {
4468         }       
4469         
4470         public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
4471         {       
4472                 // FIXME : This is broken: only the first rank is parsed
4473                 return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
4474         }
4475         
4476         public static void FixupTypes (ArrayList vars)
4477         {
4478                 int varcount =  vars.Count;
4479                 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
4480                         
4481                 if (last_var.type == null)
4482                         last_var.type = TypeManager.system_object_expr;
4483                         
4484                 Expression cur_type = last_var.type;
4485                 int n = varcount - 1;
4486                 
4487                 while (n >= 0) {
4488                         VariableDeclaration var = (VariableDeclaration) vars[n--];
4489                         if (var.type == null)
4490                                 var.type = cur_type;
4491                         else
4492                                 cur_type = var.type;
4493                 }
4494         }
4495         
4496         public static bool IndexesSpecifiedInRank (ArrayList IndexList)
4497         {
4498                 bool res = false;
4499                 
4500                 if (IndexList != null) {
4501                         foreach (Expression e in IndexList)
4502                                 if (!(e is EmptyExpression)) {
4503                                         res = true;
4504                                         break;
4505                                 }       
4506                 }
4507                 return (res);
4508         }       
4509         
4510         
4511         public static bool IndexesSpecified (ArrayList ranks)
4512         {
4513                 bool res = false;
4514                 
4515                 if (ranks != null) {
4516                         foreach (ArrayList IndexList in ranks) {
4517                                 if (IndexesSpecifiedInRank (IndexList)) {
4518                                         res = true;
4519                                         break;
4520                                 }       
4521                         }       
4522                 }
4523                 return (res);
4524         }
4525         
4526         public static string StripDims (string varname, ref string d)
4527         {
4528                 string res = varname;
4529                 string dres = "";
4530                 
4531                 if (varname.IndexOf("[") >= 0) {
4532                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
4533                         res = varname.Substring(0, varname.IndexOf("["));
4534                 }
4535                 d = dres;
4536                 return (res);
4537         }       
4538         
4539         public static string StripDims (string varname)
4540         {
4541                 string dres = "";
4542                 
4543                 return (StripDims(varname, ref dres));
4544         }       
4545         
4546         public static string StripIndexesFromDims (string dims)
4547         {
4548                 StringBuilder sb = new StringBuilder();
4549
4550                 foreach (char c in dims) 
4551                         if (c == ',' || c == ']' || c == '[')
4552                                 sb.Append (c);
4553                                 
4554                 return sb.ToString();                           
4555         }
4556         
4557         public static string BuildRank (ArrayList rank)
4558         {
4559                 string res = "";
4560
4561                 res += "[";
4562                 for (int x = 0; x < (rank.Count -1 ); x++)
4563                         res += ",";
4564                         
4565                 res += "]";
4566                 return res;
4567         }
4568                 
4569         public static string BuildRanks (Parser t)
4570         {
4571                 string res = "";
4572
4573                 foreach (ArrayList rank in t.current_rank_specifiers)
4574                         res += BuildRank (rank);
4575
4576                 return res;
4577         }       
4578         
4579         public static void VBFixIndexList (ref ArrayList IndexList)
4580         {
4581                 if (IndexList != null) {
4582                         for (int x = 0; x < IndexList.Count; x++) {
4583                                 Expression e = (Expression) IndexList[x];
4584                                 if (!(e is EmptyExpression)) {
4585                                         IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
4586                                 }
4587                         }
4588                 }
4589         }               
4590         
4591         public static bool IsArrayDecl (Parser t)
4592         {
4593                 // return (varname.IndexOf("[") >= 0);
4594                 return (t.current_rank_specifiers != null);
4595         }                       
4596         
4597         public static void VBFixIndexLists (ref ArrayList ranks)
4598         {       
4599                 if (ranks != null) {
4600                         for (int x = 0; x < ranks.Count; x++) {
4601                                 ArrayList IndexList = (ArrayList) ranks[x];
4602                                 VBFixIndexList (ref IndexList);
4603                         }       
4604                 }       
4605         }
4606                 
4607         public static void FixupArrayTypes (ArrayList vars)
4608         {
4609                 int varcount =  vars.Count;
4610                 string dims;
4611                 
4612                 foreach (VariableDeclaration var in vars) {
4613                         if (var.identifier.EndsWith(",")) {
4614                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
4615                                                                 var.identifier.LastIndexOf(",")) + "]";
4616                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
4617                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
4618                         }
4619                 }
4620         }                               
4621 }
4622
4623
4624 public Property BuildSimpleProperty (Expression p_type, string name, 
4625                                         Field p_fld, int mod_flags,
4626                                         Attributes attrs, Location loc) 
4627 {
4628         Property p;
4629         Block get_block, set_block;
4630         Accessor acc_set, acc_get;
4631         StatementExpression a_set;
4632         Statement a_get;
4633         Parameter [] args;
4634         
4635         // Build SET Block
4636         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
4637         args  = new Parameter [1];
4638         args [0] = implicit_value_parameter;
4639                 
4640         Parameters set_params = new Parameters (args, null, loc);
4641         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
4642                             (Expression) new SimpleName("value", loc), loc), loc);
4643                             
4644         set_block = new Block (current_block, set_params, loc, Location.Null);
4645         set_block.AddStatement ((Statement) a_set);                                         
4646         acc_set = new Accessor (set_block, attrs);
4647         
4648         // Build GET Block
4649         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
4650         get_block = new Block (current_block, null, loc, Location.Null);
4651         get_block.AddStatement ((Statement) a_get);                                         
4652         acc_get = new Accessor (get_block, attrs);
4653                 
4654         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
4655         
4656         return (p);
4657 }
4658         
4659 void start_block () 
4660 {
4661         current_block = new Block (current_block, current_local_parameters,
4662                            lexer.Location, Location.Null);
4663
4664
4665 Block end_block ()
4666
4667         Block res;
4668         
4669         while (current_block.Implicit)
4670                 current_block = current_block.Parent;
4671
4672         res = current_block;
4673
4674         current_block.SetEndLocation (lexer.Location);
4675         current_block = current_block.Parent;
4676         
4677         return (res);
4678 }
4679
4680 private void AddHandler (Expression evt_definition, string handler_name)
4681 {
4682         AddHandler (current_block, evt_definition, handler_name);
4683 }
4684
4685 void CheckAttributeTarget (string a)
4686 {
4687         switch (a) {
4688
4689         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
4690                 return;
4691                 
4692         default :
4693                 Location l = lexer.Location;
4694                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
4695                 break;
4696         }
4697 }
4698
4699 private void AddHandler (Block b, Expression evt_id, string handler_name)
4700 {
4701         Location loc = lexer.Location;
4702         string evt_target = evt_id.ToString();
4703         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
4704         Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
4705         b.AddStatement (s);
4706 }
4707
4708 private void RaiseEvent (string evt_name, ArrayList args)
4709 {
4710         Location loc = lexer.Location;
4711         
4712         Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
4713         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); 
4714         current_block.AddStatement (s); 
4715 }
4716
4717 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
4718 {
4719         Location loc = lexer.Location;
4720         string evt_target = evt_definition.ToString();
4721         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
4722         Statement s = (Statement) new RemoveHandler (evt_definition, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
4723         b.AddStatement (s);
4724 }
4725
4726 // <summary>
4727 //  This method is used to get at the complete string representation of
4728 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
4729 //  This is necessary because local_variable_type admits primary_expression
4730 //  as the type of the variable. So we do some extra checking
4731 // </summary>
4732 string GetQualifiedIdentifier (Expression expr)
4733 {
4734         if (expr is SimpleName)
4735                 return ((SimpleName)expr).Name;
4736         else if (expr is MemberAccess)
4737                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4738         else 
4739                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4740         
4741 }
4742
4743 private void RemoveHandler (Expression evt_definition, string handler_name)
4744 {
4745         RemoveHandler (current_block, evt_definition, handler_name);
4746 }
4747
4748 private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s)
4749 {
4750         ConstructorInitializer ci = null;
4751         
4752         if (s.Count > 0) {
4753                 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4754                         Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4755                         
4756                         if (i.expr is BaseAccess) {
4757                                 BaseAccess ba = (BaseAccess) i.expr;
4758                                 if (ba.member == "New" || ba.member == ".ctor") {
4759                                         ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4760                                         s.RemoveAt(0);
4761                                 }
4762                         }
4763                         if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
4764                                 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location); 
4765                                 s.RemoveAt(0);
4766                         }
4767                 }
4768         }
4769         return ci;
4770 }
4771
4772 void Error_ExpectingTypeName (Location l, Expression expr)
4773 {
4774         if (expr is Invocation){
4775                 Report.Error (1002, l, "; expected");
4776         } else {
4777                 Report.Error (-1, l, "Invalid Type definition");
4778         }
4779 }
4780
4781 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4782         return true;
4783 }
4784
4785 private void ReportError9998()
4786 {
4787         Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4788 }
4789
4790 protected override int parse ()
4791 {
4792         RootContext.InitializeImports(ImportsList);
4793         current_namespace = new Namespace (null, RootContext.RootNamespace);
4794         current_container = RootContext.Tree.Types;
4795         current_container.Namespace = current_namespace;
4796         oob_stack = new Stack ();
4797         switch_stack = new Stack ();
4798         expr_stack = new Stack ();      
4799         tmp_blocks = new Stack(); 
4800         with_stack = new Stack();
4801         statement_stack = new Stack();  
4802
4803         UseExtendedSyntax = name.EndsWith(".mbs");
4804         OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4805         OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4806         OptionCompareBinary = InitialOptionCompareBinary;
4807
4808         lexer = new Tokenizer (input, name, defines);
4809         
4810         ifElseStateMachine = new IfElseStateMachine();
4811         tokenizerController = new TokenizerController(lexer);
4812         
4813         StringBuilder value = new StringBuilder ();
4814         try {
4815                 if (yacc_verbose_flag)
4816                         yyparse (lexer, new yydebug.yyDebugSimple ());
4817                 else {
4818                         yyparse (lexer);
4819                         cleanup();
4820                 }
4821         } 
4822         catch(MBASException e) {
4823                 Report.Error(e.code, e.loc, e.Message);
4824         }
4825         catch (Exception e) {
4826                 Report.Error (29999, lexer.Location, "Parsing error");
4827         }
4828
4829         RootContext.VerifyImports();
4830
4831         return Report.Errors;
4832 }
4833
4834 void cleanup()
4835 {
4836         try {
4837                 ifElseStateMachine.HandleToken(IfElseStateMachine.Token.EOF);
4838         }
4839         catch(ApplicationException) {
4840                 throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
4841         }
4842
4843         if(in_external_source) 
4844                 Report.Error (30579, lexer.Location, "'#ExternalSource' directives must end with matching '#End ExternalSource'");
4845
4846         if(in_marked_region > 0)
4847                 Report.Error (30205, lexer.Location, "'#Region' directive must be followed by a matching '#End Region'");
4848 }
4849
4850 void HandleConditionalDirective(IfElseStateMachine.Token tok, BoolLiteral expr)
4851 {
4852         try {
4853                 tokenizerController.PositionTokenizerCursor(tok, expr);
4854         }
4855         catch(ApplicationException) {
4856                 tok = IfElseStateMachine.Token.EOF;
4857                 try {
4858                         ifElseStateMachine.HandleToken(tok);
4859                 }
4860                 catch(ApplicationException) {
4861                         throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
4862                 }
4863         }
4864 }
4865 /* end end end */
4866 }