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