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