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