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