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