* WebServiceHandler.cs: Fixed Invoke(). ParameterInfo.Position is now
[mono.git] / mcs / mbas / mb-parser.jay
1 %{
2 //
3 // Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler
4 //
5 // Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // Copyright (C) 2001 A Rafael D Teixeira
10 //
11 // TODO:
12 //      Nearly everything
13 //
14
15 namespace Mono.MonoBASIC
16 {
17         using System.Text;
18         using System;
19         using System.Reflection;
20         using System.Collections;
21         using Mono.Languages;
22         using Mono.CSharp;
23
24         /// <summary>
25         ///    The MonoBASIC Parser
26         /// </summary>
27         public class Parser : GenericParser
28         {
29         
30
31                 /// <summary>
32                 ///   Current block is used to add statements as we find
33                 ///   them.  
34                 /// </summary>
35                 Block      current_block;
36                 
37                 /// <summary>
38                 ///   Tmp block is used to store block endings in if/select's
39                 /// </summary>
40                 Block      tmp_block;           
41
42                 /// <summary>
43                 ///   Tmp block is used to store tmp copies of expressions
44                 /// </summary>
45                 Expression      tmp_expr;       
46                 
47                 /// <summary>
48                 ///   Tmp catch is used to store catch clauses in try..catch..finally
49                 /// </summary>
50                 ArrayList      tmp_catch_clauses;                       
51                 
52                 /// <summary>
53                 ///   Current interface is used by the various declaration
54                 ///   productions in the interface declaration to "add"
55                 ///   the interfaces as we find them.
56                 /// </summary>
57                 Interface  current_interface;
58
59                 /// <summary>
60                 ///   This is used by the unary_expression code to resolve
61                 ///   a name against a parameter.  
62                 /// </summary>
63                 Parameters current_local_parameters;
64                 
65                 /// <summary>
66                 ///   This are used when parsing parameters in property
67                 ///   declarations.
68                 /// </summary>          
69                 Parameters set_parameters;
70                 Parameters get_parameters;
71                 
72                 /// <summary>
73                 ///   This is used by the sub_header parser to store modifiers
74                 ///   to be passed to sub/constructor  
75                 /// </summary>
76                 int current_modifiers;          
77                 
78                 /// <summary>
79                 ///   This is used by the sub_header parser to store attributes
80                 ///   to be passed to sub/constructor  
81                 /// </summary>
82                 Attributes current_attributes;                          
83
84                 /// <summary>
85                 ///   Using during property parsing to describe the implicit
86                 ///   value parameter that is passed to the "set" accessor
87                 ///   method
88                 /// </summary>
89                 string get_implicit_value_parameter_name;
90                 
91                 // <summary>
92                 //   Using during property parsing to describe the implicit
93                 //   value parameter that is passed to the "set" and "get"accesor
94                 //   methods (properties and indexers).
95                 // </summary>
96                 Expression get_implicit_value_parameter_type;
97                 
98                 /// <summary>
99                 ///   Using during property parsing to describe the implicit
100                 ///   value parameter that is passed to the "set" accessor
101                 ///   method
102                 /// </summary>
103                 string set_implicit_value_parameter_name;
104                 
105                 // <summary>
106                 //   Using during property parsing to describe the implicit
107                 //   value parameter that is passed to the "set" and "get"accesor
108                 //   methods (properties and indexers).
109                 // </summary>
110                 Expression set_implicit_value_parameter_type;           
111                 
112                 // An out-of-band stack.
113                 //
114                 Stack oob_stack;
115                 
116                 ArrayList current_rank_specifiers;
117
118                 DoOptions do_type;
119                 //
120                 // Switch stack.
121                 //
122                 Stack switch_stack;
123                 
124                 // Expression stack for nested ifs
125                 Stack expr_stack; 
126                 
127                 Stack tmp_blocks;
128             Stack statement_stack;
129
130
131                 
132                 static public bool InitialOptionExplicit = false;
133                 static public bool InitialOptionStrict = false;
134                 static public bool InitialOptionCompareBinary = true;
135
136                 bool OptionExplicit;
137                 bool OptionStrict;
138                 bool OptionCompareBinary;
139
140                 static public bool UseExtendedSyntax; // for ".mbs" files
141
142                 public override string[] extensions()
143                 {
144                         string [] list = { ".vb", ".mbs" };
145                         return list;
146                 }
147
148 %}
149
150 %token EOF
151 %token NONE   /* This token is never returned by our lexer */
152 %token ERROR  // This is used not by the parser, but by the tokenizer.
153               // do not remove.
154
155 /*
156  *These are the MonoBASIC keywords
157  */
158 %token ADDHANDLER
159 %token ADDRESSOF
160 %token ALIAS
161 %token AND
162 %token ANDALSO
163 %token ANSI
164 %token AS
165 %token ASSEMBLY
166 %token AUTO
167 %token BINARY
168 %token BOOLEAN  
169 %token BYREF
170 %token BYTE
171 %token BYVAL    
172 %token CALL
173 %token CASE     
174 %token CATCH    
175 %token CBOOL
176 %token CBYTE
177 %token CCHAR    
178 %token CDATE
179 %token CDEC
180 %token CDBL
181 %token CHAR     
182 %token CINT
183 %token CLASS
184 %token CLNG
185 %token COBJ
186 %token COMPARE  
187 %token CONST    
188 %token CSHORT   
189 %token CSNG
190 %token CSTR
191 %token CTYPE
192 //%token DATE
193 %token DECIMAL  
194 %token DECLARE
195 %token DEFAULT  
196 %token DELEGATE 
197 %token DIM
198 %token DO       
199 %token DOUBLE   
200 %token EACH     
201 %token ELSE
202 %token ELSEIF
203 %token END      
204 %token ENUM     
205 %token EOL
206 %token ERASE
207 %token ERROR
208 %token EVENT
209 %token EXIT     
210 %token EXPLICIT 
211 %token FALSE    
212 %token FINALLY  
213 %token FOR      
214 %token FRIEND
215 %token FUNCTION
216 %token GET
217 //%token GETTYPE
218 %token GOTO     
219 %token HANDLES
220 %token IF       
221 %token IMPLEMENTS
222 %token IMPORTS  
223 %token IN       
224 %token INHERITS
225 %token INTEGER  
226 %token INTERFACE
227 %token IS
228 %token LET
229 %token LIB      
230 %token LIKE     
231 %token LONG     
232 %token LOOP
233 %token ME
234 %token MOD
235 %token MODULE
236 %token MUSTINHERIT      
237 %token MUSTOVERRIDE
238 %token MYBASE
239 %token MYCLASS
240 %token NAMESPACE
241 %token NEW
242 %token NEXT     
243 %token NOT
244 %token NOTHING
245 %token NOTINHERITABLE
246 %token NOTOVERRIDABLE
247 %token OBJECT   
248 %token OFF
249 %token ON
250 %token OPTION   
251 %token OPTIONAL 
252 %token OR
253 %token ORELSE
254 %token OVERLOADS
255 %token OVERRIDABLE      
256 %token OVERRIDES        
257 %token PARAM_ARRAY
258 %token PRESERVE
259 %token PRIVATE  
260 %token PROPERTY
261 %token PROTECTED
262 %token PUBLIC
263 %token RAISEEVENT
264 %token READONLY 
265 %token REDIM
266 %token REM
267 %token REMOVEHANDLER
268 %token RESUME   
269 %token RETURN
270 %token SELECT
271 %token SET
272 %token SHADOWS
273 %token SHARED
274 %token SHORT    
275 %token SINGLE
276 %token SIZEOF   
277 %token STATIC   
278 %token STEP
279 %token STOP
280 %token STRICT   
281 %token STRING
282 %token STRUCTURE
283 %token SUB
284 %token SYNCLOCK
285 %token TEXT
286 %token THEN
287 %token THROW
288 %token TO
289 %token TRUE     
290 %token TRY      
291 %token TYPEOF   
292 %token UNICODE
293 %token UNTIL
294 %token VARIANT  
295 %token WHEN     
296 %token WHILE    
297 %token WITH
298 %token WITHEVENTS
299 %token WRITEONLY
300 %token XOR
301 %token YIELD // MonoBASIC extension
302
303 /* MonoBASIC single character operators/punctuation. */
304
305 %token OPEN_BRACKET  "["
306 %token CLOSE_BRACKET "]"
307 %token OPEN_PARENS   "("
308 %token OPEN_BRACE    "{"
309 %token CLOSE_BRACE   "}"
310 %token CLOSE_PARENS  ")"
311 %token DOT           "."
312 %token COMMA         ","
313 %token COLON         ":"
314
315 %token PLUS           "+"
316 %token MINUS          "-"
317 %token ASSIGN         "="
318 %token OP_LT          "<"
319 %token OP_GT          ">"
320 %token STAR           "*"
321 %token PERCENT        "%"
322 %token DIV            "/"
323 %token OP_EXP         "^"
324 %token INTERR         "?"
325 %token OP_IDIV        "\\"
326 %token OP_CONCAT      "&"
327 %token ATTR_ASSIGN ":="
328
329 /* MonoBASIC multi-character operators. */
330 %token OP_LE                  "<="
331 %token OP_GE                  ">="
332 //%token OP_EQ                  "=="
333 %token OP_NE                  "<>"
334 //%token OP_AND                 "and"
335 //%token OP_OR                  "or"
336 %token OP_XOR                 "xor"
337 //%token OP_MODULUS             //"mod"
338 %token OP_MULT_ASSIGN         "*="
339 %token OP_DIV_ASSIGN          "/="
340 %token OP_IDIV_ASSIGN         "\\="
341 %token OP_ADD_ASSIGN          "+="
342 %token OP_SUB_ASSIGN          "-="
343 %token OP_CONCAT_ASSIGN       "&="
344 %token OP_EXP_ASSIGN          "^="
345
346 /* Numbers */
347 %token LITERAL_INTEGER           "int literal"
348 %token LITERAL_SINGLE            "float literal"
349 %token LITERAL_DOUBLE            "double literal"
350 %token LITERAL_DECIMAL           "decimal literal"
351 %token LITERAL_CHARACTER         "character literal"
352 %token LITERAL_STRING            "string literal"
353
354 %token IDENTIFIER
355
356 /* Add precedence rules to solve dangling else s/r conflict */
357 %nonassoc LOWPREC
358 %nonassoc IF
359 %nonassoc ELSE
360 %right ASSIGN
361 %left OP_OR
362 %left OP_AND
363 %left BITWISE_OR
364 %left BITWISE_AND
365 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
366 %left PLUS MINUS
367 %left STAR DIV PERCENT
368 %right BITWISE_NOT CARRET UMINUS
369 %nonassoc OP_INC OP_DEC
370 %left OPEN_PARENS
371 %left OPEN_BRACKET OPEN_BRACE
372 %left DOT
373 %right NOT
374 %nonassoc HIGHPREC
375
376 %start compilation_unit
377 %%
378
379 compilation_unit
380         : opt_option_directives
381           opt_imports_directives 
382           opt_attributes
383           opt_declarations 
384           EOF
385           {
386                 $$ = $4;
387           }
388         ;
389           
390 opt_option_directives
391         : /* empty */
392         | option_directives
393         ;
394         
395 option_directives
396         : option_directive
397         | option_directives option_directive
398         ;
399         
400 option_directive
401         : option_explicit_directive
402         | option_strict_directive
403         | option_compare_directive
404         ;
405         
406 on_off
407         : /* empty */
408           {
409                   $$ = (object)true;
410           }
411         | ON
412           {
413                   $$ = (object)true;
414           }
415         | OFF
416           {
417                   $$ = (object)false;
418           }
419         ;
420           
421 text_or_binary
422         : BINARY
423           {
424                   $$ = (object)true;
425           }
426         | TEXT
427           {
428                   $$ = (object)false;
429           }
430         ;
431           
432 option_explicit_directive
433         : OPTION EXPLICIT on_off EOL
434           {
435                 if (!UseExtendedSyntax)
436                         OptionExplicit = (bool)$3;
437                 else
438                         Report.Warning (
439                                 9999, lexer.Location, 
440                                 "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");
441           }
442         ;
443           
444                         
445 option_strict_directive
446         : OPTION STRICT on_off EOL
447           {
448                 if (!UseExtendedSyntax)
449                         OptionStrict = (bool)$3;
450                 else
451                         Report.Warning (
452                                 9999, lexer.Location, 
453                                 "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");
454           }
455         ;
456           
457 option_compare_directive
458         : OPTION COMPARE text_or_binary EOL
459           {
460                 OptionCompareBinary = (bool)$3;
461           }
462         ;
463
464 opt_declarations
465         : /* empty */
466         | declarations
467         ;
468
469 declarations
470         : declaration
471         | declarations declaration
472         ;
473         
474 declaration
475         : namespace_declaration
476         | type_declaration
477           {
478                 string name = "";
479                 int mod_flags;
480
481                 if ($1 is Class){
482                         Class c = (Class) $1;
483                         mod_flags = c.ModFlags;
484                         name = c.Name;
485                 } else if ($1 is Struct){
486                         Struct s = (Struct) $1;
487                         mod_flags = s.ModFlags;
488                         name = s.Name;
489                 } else if ($1 is Module){
490                         Module m = (Module) $1;
491                         mod_flags = m.ModFlags;
492                         name = m.Name;                  
493                 } else
494                         break;
495
496                 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
497                         Report.Error (
498                                 1527, lexer.Location, 
499                                 "Namespace elements cannot be explicitly " +
500                                 "declared private or protected in '" + name + "'");
501                 }
502           }
503         ;
504
505 identifier
506         : IDENTIFIER
507         | BINARY
508         | TEXT
509         | COMPARE
510         | EXPLICIT
511         | OFF
512         ;
513           
514 qualified_identifier
515         : identifier
516         | qualified_identifier DOT identifier 
517           { 
518             $$ = (($1).ToString ()) + "." + ($3.ToString ()); 
519           }
520         ;
521 opt_imports_directives
522         : /* empty */
523         | imports_directives
524         ;
525
526 imports_directives
527         : imports_directive 
528         | imports_directives imports_directive 
529         ;
530
531 imports_directive
532         : IMPORTS imports_terms EOL
533         ;
534
535 imports_terms
536         : imports_term
537         | imports_terms COMMA imports_terms
538         ;
539         
540 imports_term
541         : qualified_identifier
542           {
543                 current_namespace.Using ((string) $1, lexer.Location);
544           }
545         | qualified_identifier ASSIGN qualified_identifier
546           {
547                 current_namespace.UsingAlias ((string) $1, (string) $3, lexer.Location);
548           }
549         ;
550
551 opt_attributes
552         : /* empty */
553         | attribute_sections    { $$ = $1; }
554         ;
555
556 attribute_sections
557         : attribute_section
558           { 
559                 AttributeSection sect = (AttributeSection) $1;
560
561                 if (sect.Target == "assembly") 
562                         RootContext.AddGlobalAttributeSection (current_container, sect);
563                 
564                 $$ = new Attributes ((AttributeSection) $1, lexer.Location);
565                 
566           }     
567           /* 
568              FIXME: we should check if extended syntax is enabled;
569                     otherwise an exception should be thrown since VB.NET 
570                     only allows one attribute section 
571           */  
572         | attribute_sections attribute_section
573           {
574                 Attributes attrs = null;
575                 AttributeSection sect = (AttributeSection) $2;
576
577                 if (sect.Target == "assembly")
578                         RootContext.AddGlobalAttributeSection (current_container, sect);
579
580                 if ($1 != null) {
581                         attrs = (Attributes) $1;
582                         attrs.AddAttributeSection (sect);
583                 }
584                 
585                 $$ = attrs;
586           }     
587         ;
588         
589 attribute_section
590         : OP_LT attribute_target_specifier attribute_list OP_GT
591           { 
592                 string target = null;
593                 
594                 if ($2 != null)
595                         target = (string) $2;
596                 
597                 $$ = new AttributeSection (target, (ArrayList) $3);
598           }     
599         | OP_LT attribute_list OP_GT
600           {
601                 $$ = new AttributeSection (null, (ArrayList) $2);
602           }     
603         ; 
604
605 attribute_target_specifier
606         : attribute_target COLON
607           {
608                 $$ = $1;
609           }
610         ;
611
612 attribute_target
613         : identifier
614           {
615                 CheckAttributeTarget ((string) $1);
616                 $$ = $1;
617           }
618         | EVENT  { $$ = "event"; }        
619         | RETURN { $$ = "return"; }
620         ;
621         
622 attribute_list
623         : attribute 
624           {
625                 ArrayList attrs = new ArrayList ();
626                 attrs.Add ($1);
627
628                 $$ = attrs;
629                
630           }     
631         | attribute_list COMMA attribute
632           {
633                 ArrayList attrs = (ArrayList) $1;
634                 attrs.Add ($3);
635
636                 $$ = attrs;
637           }     
638         ;
639         
640 attribute 
641         : attribute_name
642           {
643                 $$ = lexer.Location;
644           }
645           opt_attribute_arguments
646           {
647                 $$ = new Mono.CSharp.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
648           }       
649         ;
650         
651 attribute_name
652         : type_name 
653         ;
654                         
655 opt_attribute_arguments
656         : /* empty */   { $$ = null; }
657         | OPEN_PARENS attribute_arguments CLOSE_PARENS
658           {
659                 $$ = $2;
660           }     
661         ;
662         
663 attribute_arguments
664         : opt_positional_argument_list
665           {
666                 if ($1 == null)
667                         $$ = null;
668                 else {
669                         ArrayList args = new ArrayList ();
670                         args.Add ($1);
671                 
672                         $$ = args;
673                 }
674           }
675         | positional_argument_list COMMA named_argument_list
676           {
677                 ArrayList args = new ArrayList ();
678                 args.Add ($1);
679                 args.Add ($3);
680
681                 $$ = args;
682           }
683         | named_argument_list
684           {
685                 ArrayList args = new ArrayList ();
686                 args.Add (null);
687                 args.Add ($1);
688                 
689                 $$ = args;
690           }
691         ;
692
693
694 opt_positional_argument_list
695         : /* empty */           { $$ = null; } 
696         | positional_argument_list
697         ;
698
699 positional_argument_list
700         : expression
701           {
702                 ArrayList args = new ArrayList ();
703                 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
704
705                 $$ = args;
706           }
707         | positional_argument_list COMMA expression
708          {
709                 ArrayList args = (ArrayList) $1;
710                 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
711
712                 $$ = args;
713          }
714         ;
715
716 named_argument_list
717         : named_argument
718           {
719                 ArrayList args = new ArrayList ();
720                 args.Add ($1);
721
722                 $$ = args;
723           }
724         | named_argument_list COMMA named_argument
725           {       
726                 ArrayList args = (ArrayList) $1;
727                 args.Add ($3);
728
729                 $$ = args;
730           }
731         ;
732
733 named_argument
734         : identifier ATTR_ASSIGN expression
735           {
736                 $$ = new DictionaryEntry (
737                         (string) $1, 
738                         new Argument ((Expression) $3, Argument.AType.Expression));
739           }
740         ;
741                                 
742 namespace_declaration
743         : opt_attributes NAMESPACE qualified_identifier EOL
744           {
745                 Attributes attrs = (Attributes) $1;
746
747                 if (attrs != null) {
748                         foreach (AttributeSection asec in attrs.AttributeSections)
749                                 if (asec.Target == "assembly")
750                                         RootContext.AddGlobalAttributeSection (current_container, asec);
751                 }
752                           
753                 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$3);
754           } 
755           opt_imports_directives
756           opt_declarations
757           END NAMESPACE EOL
758           { 
759                 current_namespace = current_namespace.Parent;
760           }
761         ;
762
763 type_declaration
764         : opt_attributes 
765           opt_modifiers 
766           { 
767                 current_attributes = (Attributes) $1; 
768                 current_modifiers = (int) $2; 
769           }       
770           type_spec_declaration
771         ;
772
773 type_spec_declaration
774         : class_declaration
775         | module_declaration
776         | interface_declaration
777         | delegate_declaration
778         | struct_declaration
779         | enum_declaration
780         ;
781
782 class_declaration
783         : CLASS identifier EOL opt_class_base
784           {
785                 Class new_class;
786                 string name;
787                 
788                 name = MakeName ((string) $2);
789                 new_class = new Class (current_container, name, current_modifiers, 
790                                        (Attributes) current_attributes, lexer.Location);
791
792                 current_container = new_class;
793                 current_container.Namespace = current_namespace;
794                 RootContext.Tree.RecordDecl (name, new_class);
795           }
796           opt_class_member_declarations
797           END CLASS EOL
798           {
799                 Class new_class = (Class) current_container;
800                 new_class.Bases = (ArrayList) $4;       
801         
802                 current_container = current_container.Parent;
803                 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
804
805                 $$ = new_class;
806           }
807         ;
808
809 opt_class_base
810         : /* empty */           { $$ = null; }
811         | class_base            { $$ = $1; }
812         ;
813
814 class_base
815         : inherits_or_implements type_list EOL { $$ = $2; }
816         ;
817
818 inherits_or_implements
819         : INHERITS
820         | IMPLEMENTS
821         ;
822         
823 opt_modifiers
824         : /* empty */           { $$ = (int) 0; current_modifiers = 0; }
825         | modifiers             { $$ = $1; current_modifiers = (int) $1; }
826         ;
827         
828 modifiers
829         : modifier
830         | modifiers modifier
831           { 
832                 int m1 = (int) $1;
833                 int m2 = (int) $2;
834
835                 if ((m1 & m2) != 0) {
836                         Location l = lexer.Location;
837                         Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
838                 }
839                 $$ = (int) (m1 | m2);
840           }
841         ;
842
843 modifier
844         : PUBLIC                { $$ = Modifiers.PUBLIC; }
845         | PROTECTED             { $$ = Modifiers.PROTECTED; }
846         | PRIVATE               { $$ = Modifiers.PRIVATE; }
847         | SHARED                { $$ = Modifiers.STATIC; }
848         | FRIEND                { $$ = Modifiers.INTERNAL; }
849         | OVERRIDES             { $$ = Modifiers.OVERRIDE; }
850         | OVERRIDABLE           { $$ = Modifiers.VIRTUAL; }
851         | NOTOVERRIDABLE        { $$ = 0; }
852         | OVERLOADS             { $$ = 0; }
853         | MUSTINHERIT           { $$ = Modifiers.ABSTRACT; }
854         ;
855
856 module_declaration
857         : MODULE identifier EOL
858           { 
859                 Module new_module;
860                 string name;
861                 name = MakeName((string) $2);
862                 new_module = new Module(current_container, 
863                                                                 name, 
864                                                                 current_modifiers, // already checks then
865                                                                 (Attributes) current_attributes,
866                                                                 lexer.Location);
867                 current_container = new_module;
868                 current_container.Namespace = current_namespace;
869                 RootContext.Tree.RecordDecl(name, new_module);
870           }
871           opt_module_member_declarations
872           END MODULE EOL
873           {
874                 Module new_module = (Module)current_container;
875
876                 current_container = current_container.Parent;
877                 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
878
879                 $$ = new_module;
880           }
881         ;
882
883 opt_module_member_declarations
884         : /* empty */
885         | module_member_declarations
886         ;
887
888 module_member_declarations
889         : module_member_declaration
890         | module_member_declarations module_member_declaration
891         ;
892
893 module_member_declaration
894         :  opt_attributes
895            opt_modifiers
896            { 
897                 current_attributes = (Attributes) $1;
898                 current_modifiers = (int) $2 | (int)Modifiers.STATIC; // FIXME: for type_declaration it can result in trouble
899            }
900            module_member_declarator
901            {
902                 $$ = $3;
903            }
904         ;
905
906 module_member_declarator
907         :  static_constructor_declaration
908         |  method_declaration
909            { 
910                 Method method = (Method) $1;
911                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
912            }    
913         |  field_declaration
914         |  withevents_declaration       /* This is a field but must be treated specially, see below */
915         |  constant_declaration
916         |  property_declaration                 
917         |  event_declaration    
918         |  type_declaration                     
919         ;
920         
921 constant_declaration // TODO: implement truly the logic
922         : CONST identifier ASSIGN primary_expression EOL
923         | CONST identifier AS type ASSIGN constant_expression EOL
924         ;
925            
926 opt_class_member_declarations
927         : /* empty */
928         | class_member_declarations
929         ;
930
931 class_member_declarations
932         : class_member_declaration
933         | class_member_declarations class_member_declaration
934         ;
935
936 class_member_declaration
937         :  opt_attributes
938            opt_modifiers
939            { 
940                 current_attributes = (Attributes) $1;
941                 current_modifiers = (int) $2; 
942            }
943            class_member_declarator
944            {
945                 $$ = $3;
946            }
947         ;
948
949 class_member_declarator
950         :  constructor_declaration
951         |  method_declaration
952            { 
953                 Method method = (Method) $1;
954                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
955            }    
956         |  field_declaration
957         |  constant_declaration
958         |  property_declaration                 
959         |  event_declaration    
960         |  withevents_declaration       /* This is a field but must be treated specially, see below */
961         /*|  type_declaration  */
962         |  class_declaration            
963         |  enum_declaration             
964         ;
965         
966         
967 method_declaration
968         : sub_declaration
969         | func_declaration 
970         | must_override_declaration
971         ;
972         
973 must_override_declaration
974         : must_override_sub_declaration
975         | must_override_func_declaration        
976         ;
977         
978 must_override_sub_declaration
979         : MUSTOVERRIDE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
980           {     
981                 if (current_container is Module)
982                         Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
983                         
984                 if (current_container is Struct)
985                         Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
986                 
987                 current_modifiers |= Modifiers.ABSTRACT;
988                                         
989                 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3,
990                                             (Parameters) $5, null, null, lexer.Location);
991                                             
992                 if (!(current_container is Class))
993                         Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");               
994                         
995                 // FIXME ASAP: This will crash the compiler at resolution time                  
996                 $$ = method;                        
997           }
998         ;
999         
1000 must_override_func_declaration
1001         : MUSTOVERRIDE FUNCTION identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type EOL
1002           {     
1003                 if (current_container is Module)
1004                         Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
1005                         
1006                 if (current_container is Struct)
1007                         Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1008                                 
1009                 current_modifiers |= Modifiers.ABSTRACT;
1010                                                         
1011                 Method method = new Method ((Expression) $8, (int) current_modifiers, (string) $3,
1012                                             (Parameters) $5, null, null, lexer.Location);
1013                                             
1014                 if (!(current_container is Class))
1015                         Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1016                         
1017                 // FIXME ASAP: This will crash the compiler at resolution time                  
1018                 $$ = method;                                    
1019           }     
1020         ;
1021         
1022 sub_declaration
1023         : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
1024           { 
1025                 current_local_parameters = (Parameters) $4;
1026                 start_block(); 
1027
1028                 /* This is WEIRD: declaring a method (sub) in a module as static will
1029                    trigger a syntax error, but the same methods MUST be static in order
1030                    to be properly called
1031                 */
1032                 /* THIS SHOULD NOT BE NEEDED ANYMORE
1033                 if (current_container is Module) {
1034                         if ((current_modifiers & Modifiers.STATIC) != 0) {
1035                                 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1036                         }
1037                         else
1038                         {
1039                                 current_modifiers = Modifiers.STATIC;
1040                         }
1041                 
1042                 }
1043                 */
1044                 // Structure members are Public by default                      
1045                 if ((current_container is Struct) && (current_modifiers == 0))
1046                         current_modifiers = Modifiers.PUBLIC;                   
1047           }
1048           opt_statement_list 
1049           END SUB EOL
1050           {
1051                 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
1052                                             (Parameters) current_local_parameters, null, (Expression) $7, 
1053                                             lexer.Location);
1054         
1055                 method.Block = (Block) end_block();
1056                 $$ = method;
1057
1058                 if ($6 != null) { /* we have an event handler to take care of */
1059                         // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
1060                         string evt_def = ((MemberAccess)$6).ToString();
1061                         int pos = evt_def.LastIndexOf (".");
1062                         string evt_target = ((string) $2).Substring (0, pos);
1063
1064                         foreach (Property p in current_container.Properties) {
1065                                 if (p.Name == evt_target) {
1066                                         // FIXME: See below 
1067                                         // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
1068                                         AddHandler (p.Set.Block, (Expression)$6, (string) $2);
1069                                         break;
1070                                 }
1071                         }                               
1072                 }       
1073           }       
1074         ;
1075         
1076 func_declaration
1077         : FUNCTION identifier 
1078           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type opt_implement_clause EOL
1079           { 
1080                 
1081                 current_local_parameters = (Parameters) $4;
1082                 start_block(); 
1083         
1084                 /* This is WEIRD: declaring a method (sub) in a module as static will
1085                    trigger a syntax error, but the same methods MUST be static in order
1086                    to be properly called
1087                 */
1088                 /* THIS SHOULD NOT BE NEEDED ANYMORE
1089                 if (current_container is Module) {
1090                         if ((current_modifiers & Modifiers.STATIC) != 0) {
1091                                 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1092                         }
1093                         else
1094                         {
1095                                 current_modifiers |= Modifiers.STATIC;
1096                         }                       
1097                 }
1098                 */
1099                 // Structure members are Public by default                      
1100                 if ((current_container is Struct) && (current_modifiers == 0))
1101                         current_modifiers = Modifiers.PUBLIC;                           
1102                 // Add local var declaration
1103                 // for return value
1104                 ArrayList retval = new ArrayList ();
1105                 retval.Add (new VariableDeclaration ((string) $2, (Expression) $7, lexer.Location));
1106                 declare_local_variables ((Expression) $7, retval, lexer.Location);
1107           }       
1108           opt_statement_list
1109           END FUNCTION EOL
1110           {
1111                 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
1112                                             (Parameters) current_local_parameters, null, 
1113                                             (Expression) $7, lexer.Location);
1114                 method.Block = end_block();
1115                 $$ = method;
1116         /*Console.WriteLine ("Declaring Function '{0}' with {1} statements and {2} arguments", 
1117                                 current_container.Name + "." + (string) $2, 
1118                                 method.Block.statements.Count,
1119                                 current_local_parameters.FixedParameters != null ? current_local_parameters.FixedParameters.Length : 0);
1120 */
1121           }       
1122         ;               
1123
1124 struct_declaration
1125         : STRUCTURE identifier EOL
1126           opt_implement_clause
1127           {
1128                 Struct new_struct;
1129                 string full_struct_name = MakeName ((string) $2);
1130
1131                 new_struct = new Struct (current_container, full_struct_name, 
1132                                          (int) current_modifiers,
1133                                          (Attributes) current_attributes, lexer.Location);
1134                 current_container = new_struct;
1135                 current_container.Namespace = current_namespace;
1136                 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1137           }
1138           opt_struct_member_declarations
1139           {
1140                 Struct new_struct = (Struct) current_container;
1141
1142                 if ($4 != null)
1143                         new_struct.Bases = (ArrayList) $4;
1144
1145                 current_container = current_container.Parent;
1146                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1147                 $$ = new_struct;
1148           }
1149           END STRUCTURE EOL
1150         ;
1151         
1152 opt_struct_member_declarations
1153         : /* empty */
1154         | struct_member_declarations
1155         ;
1156
1157 struct_member_declarations
1158         : struct_member_declaration
1159         | struct_member_declarations struct_member_declaration
1160         ;
1161
1162 struct_member_declaration
1163         : opt_modifiers
1164           struct_member_declarator
1165         ;
1166 struct_member_declarator        
1167         : field_declaration
1168         //| constant_declaration
1169         | method_declaration
1170         | property_declaration
1171         | event_declaration
1172         | constructor_declaration
1173         | type_declaration
1174
1175         /*
1176          * This is only included so we can flag error 575:
1177          * destructors only allowed on class types
1178          */
1179         //| destructor_declaration
1180         ;
1181         
1182 event_declaration
1183         : EVENT identifier AS type EOL
1184           {
1185                 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1186
1187                 Event e = new Event ((Expression) $4, var.identifier, 
1188                                      null, current_modifiers, null, null, 
1189                                      current_attributes, lexer.Location);
1190
1191                 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1192
1193           }
1194 //      | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1195 //        {
1196 //              throw new NotSupportedException();
1197 //        }
1198         ;       
1199
1200 enum_declaration
1201         : ENUM identifier opt_type_spec EOL
1202           opt_enum_member_declarations
1203           { 
1204                 Location enum_location = lexer.Location;
1205                 string full_name = MakeName ((string) $2);
1206                 Expression enum_type = ($3 == null) ? TypeManager.system_int32_expr : (Expression) $3;
1207                 ArrayList enum_members = (ArrayList) $5;
1208                 
1209                 Mono.CSharp.Enum e = new Mono.CSharp.Enum (current_container, enum_type, 
1210                                         (int) current_modifiers, full_name, 
1211                                         (Attributes) current_attributes, enum_location);
1212                 
1213                 foreach (VariableDeclaration ev in enum_members) {
1214                         Location loc = (Location) ev.Location;
1215
1216                         CheckDef (e.AddEnumMember (ev.identifier, 
1217                                                    (Expression) ev.expression_or_array_initializer,
1218                                                    loc, ev.OptAttributes), ev.identifier, loc);
1219                 }
1220
1221                 e.Namespace = current_namespace;
1222
1223                 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1224                 RootContext.Tree.RecordDecl (full_name, e);
1225
1226           }
1227           END ENUM EOL
1228         ;
1229
1230 opt_enum_member_declarations
1231         : /* empty */                   { $$ = new ArrayList (); }
1232         | enum_member_declarations      { $$ = $1; }
1233         ;
1234
1235 enum_member_declarations
1236         : enum_member_declaration 
1237           {
1238                 ArrayList l = new ArrayList ();
1239
1240                 l.Add ($1);
1241                 $$ = l;
1242           }
1243         | enum_member_declarations  enum_member_declaration
1244           {
1245                 ArrayList l = (ArrayList) $1;
1246
1247                 l.Add ($2);
1248
1249                 $$ = l;
1250           }
1251         ;
1252
1253 enum_member_declaration
1254         : opt_attributes identifier EOL
1255           {
1256                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1257           }
1258         | opt_attributes identifier
1259           {
1260                   $$ = lexer.Location;
1261           }
1262           ASSIGN expression EOL
1263           { 
1264                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1265           }
1266         ;
1267                 
1268 interface_declaration
1269         : INTERFACE identifier EOL
1270           {
1271                 Interface new_interface;
1272                 string full_interface_name = MakeName ((string) $2);
1273
1274                 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1275                                                (Attributes) current_attributes, lexer.Location);
1276                 if (current_interface != null) {
1277                         Location l = lexer.Location;
1278                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
1279                 }
1280                 current_interface = new_interface;
1281                 new_interface.Namespace = current_namespace;
1282                 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1283           }
1284           opt_interface_base
1285           interface_body
1286           { 
1287                 Interface new_interface = (Interface) current_interface;
1288
1289                 if ($5 != null)
1290                         new_interface.Bases = (ArrayList) $5;
1291
1292                 current_interface = null;
1293                 CheckDef (current_container.AddInterface (new_interface),
1294                           new_interface.Name, new_interface.Location);
1295
1296           }
1297           END INTERFACE EOL
1298         ;
1299
1300 opt_interface_base
1301         : /* empty */                     { $$ = null; }
1302         | interface_base
1303         ;
1304
1305 interface_base
1306         : INHERITS interface_type_list    { $$ = $2; }
1307         ;
1308
1309 interface_type_list
1310         : interface_type
1311           {
1312                 ArrayList interfaces = new ArrayList ();
1313
1314                 interfaces.Add ($1);
1315                 $$ = interfaces;
1316           }
1317         | interface_type_list COMMA interface_type
1318           {
1319                 ArrayList interfaces = (ArrayList) $1;
1320                 interfaces.Add ($3);
1321                 $$ = interfaces;
1322           }
1323         ;
1324
1325 interface_body
1326         : opt_interface_member_declarations
1327         ;
1328
1329 opt_interface_member_declarations
1330         : /* empty */
1331         | interface_member_declarations
1332         ;
1333
1334 interface_member_declarations
1335         : interface_member_declaration
1336         | interface_member_declarations interface_member_declaration
1337         ;
1338
1339 interface_member_declaration
1340         : interface_method_declaration          
1341           { 
1342                 InterfaceMethod m = (InterfaceMethod) $1;
1343
1344                 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1345           }
1346         | interface_property_declaration        
1347           { 
1348                 InterfaceProperty p = (InterfaceProperty) $1;
1349                 
1350                 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1351           }
1352         | interface_event_declaration 
1353           { 
1354                 InterfaceEvent e = (InterfaceEvent) $1;
1355
1356                 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1357           }
1358         ;
1359
1360 opt_new
1361         : /* empty */   { $$ = false; }
1362         | NEW           { $$ = true; }
1363         ;
1364         
1365 interface_method_declaration
1366         : SUB identifier
1367           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1368           {
1369                 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1370                                           (Parameters) $4, current_attributes, lexer.Location);
1371           }
1372         | FUNCTION identifier
1373           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1374           {
1375                 $$ = new InterfaceMethod (
1376                                           (Expression) $7, (string) $2, false, (Parameters) $4,
1377                                           current_attributes, lexer.Location);
1378           }
1379         ;
1380
1381 interface_property_declaration
1382         : PROPERTY identifier
1383           OPEN_PARENS
1384           opt_formal_parameter_list
1385           CLOSE_PARENS opt_type_spec EOL
1386           {
1387                 // FIXME we MUST pass property parameters
1388                 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1389                                             true, true, current_attributes,
1390                                             lexer.Location);
1391           }
1392         ;
1393         
1394 opt_access_specifier
1395         : /* empty */
1396         | READONLY      { $$ = Modifiers.READONLY; }
1397         | WRITEONLY     { $$ = 0; }
1398         | DEFAULT       { $$ = 0; }
1399         ;       
1400
1401 interface_event_declaration
1402         : opt_attributes opt_new EVENT type identifier EOL
1403           {
1404                 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1405                                          lexer.Location);
1406           }
1407         ;
1408
1409 property_declaration
1410           : opt_access_specifier opt_modifiers PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
1411           {
1412                 get_implicit_value_parameter_type = (Expression) $7;
1413                 get_implicit_value_parameter_name = (string) $4;
1414                 
1415                 current_modifiers = (int) $2; 
1416                 
1417                 current_local_parameters = (Parameters) $5;
1418                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
1419                         get_parameters = current_local_parameters.Copy (lexer.Location);
1420                         set_parameters = current_local_parameters.Copy (lexer.Location);
1421                 }
1422                 else
1423                 {
1424                         get_parameters = Parameters.EmptyReadOnlyParameters;
1425                         set_parameters = new Parameters (null, null ,lexer.Location);           
1426                 }
1427                 lexer.PropertyParsing = true;
1428
1429                 $$ = lexer.Location;
1430           }
1431           accessor_declarations 
1432           END PROPERTY EOL
1433           {
1434                 lexer.PropertyParsing = false;
1435
1436                 Property prop;
1437                 Pair pair = (Pair) $11;
1438                 Accessor get_block = (Accessor) pair.First;
1439                 Accessor set_block = (Accessor) pair.Second;
1440
1441                 Location loc = lexer.Location;
1442                 
1443                 // Structure members are Public by default                      
1444                 if ((current_container is Struct) && (current_modifiers == 0))
1445                         current_modifiers = Modifiers.PUBLIC;                           
1446                         
1447                 prop = new Property ((Expression) $7, (string) $4, current_modifiers, get_block, set_block,
1448                                      current_attributes, loc, set_implicit_value_parameter_name, 
1449                                      get_parameters, set_parameters, (Expression) $8);
1450                 
1451                 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1452                 get_implicit_value_parameter_type = null;
1453                 set_implicit_value_parameter_type = null;
1454                 get_parameters = null;
1455                 set_parameters = null;
1456                 current_local_parameters = null;
1457           }
1458         ;
1459
1460 opt_property_parameters
1461         : /* empty */
1462           {
1463                 $$ = Parameters.EmptyReadOnlyParameters;
1464           }
1465         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1466           {
1467                 $$ = $2;
1468           }
1469         ;
1470         
1471 opt_implement_clause
1472         : /* empty */
1473           {
1474                 $$ = null;
1475           }
1476         | IMPLEMENTS qualified_identifier
1477           {
1478                 $$ = DecomposeQI ((string)$2, lexer.Location);
1479           }     
1480         ;
1481         
1482 accessor_declarations
1483         : get_accessor_declaration opt_set_accessor_declaration
1484           { 
1485                 $$ = new Pair ($1, $2);
1486           }
1487         | set_accessor_declaration opt_get_accessor_declaration
1488           {
1489                 $$ = new Pair ($2, $1);
1490           }
1491         ;
1492
1493 opt_get_accessor_declaration
1494         : /* empty */                   { $$ = null; }
1495         | get_accessor_declaration
1496         ;
1497
1498 opt_set_accessor_declaration
1499         : /* empty */                   { $$ = null; }
1500         | set_accessor_declaration
1501         ;
1502
1503 get_accessor_declaration
1504         : opt_attributes GET EOL
1505           {
1506                 current_local_parameters = get_parameters;
1507                 
1508                 lexer.PropertyParsing = false;
1509                 
1510                 start_block();  
1511                 // Add local var declaration
1512                 // for return value
1513                 ArrayList retval = new ArrayList ();
1514                 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1515                 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);    
1516                 
1517           }
1518           opt_statement_list
1519           END GET EOL
1520           {
1521                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1522                 current_local_parameters = null;
1523                 lexer.PropertyParsing = true;
1524           }
1525         ;
1526
1527 set_accessor_declaration
1528         : opt_attributes SET opt_set_parameter EOL
1529           {
1530                 Parameter implicit_value_parameter = new Parameter (
1531                         set_implicit_value_parameter_type, 
1532                         set_implicit_value_parameter_name, 
1533                         Parameter.Modifier.NONE, null);
1534
1535                 current_local_parameters = set_parameters;
1536                 current_local_parameters.AppendParameter (implicit_value_parameter);
1537                 
1538                 start_block();
1539                 lexer.PropertyParsing = false;
1540           }
1541           opt_statement_list
1542           END SET EOL
1543           {
1544                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1545                 current_local_parameters = null;
1546                 lexer.PropertyParsing = true;
1547           }
1548         ;
1549                 
1550 opt_set_parameter
1551         : /* empty */
1552         {
1553                 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
1554                 set_implicit_value_parameter_name = "Value";
1555         }       
1556         | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
1557         {
1558                 /* FIXME: possible syntax error which must be caught
1559                    Set ( As <type>) is currently (and wrongly so) legal
1560                 */
1561                 set_implicit_value_parameter_type = (Expression) $3;
1562                 if ($2 != null)
1563                         set_implicit_value_parameter_name = (string) $2;
1564                 else
1565                         set_implicit_value_parameter_name = "Value";
1566         }
1567         ;
1568                         
1569 field_declaration
1570         : opt_dim_stmt 
1571           variable_declarators EOL
1572           {               
1573                 int mod = (int) current_modifiers;
1574                 
1575
1576                 VariableDeclaration.FixupTypes ((ArrayList) $2);
1577                 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1578                 
1579                 if (current_container is Module)
1580                         mod = mod | Modifiers.STATIC;
1581                         
1582                 // Structure members are Public by default                      
1583                 if ((current_container is Struct) && (mod == 0))
1584                         mod = Modifiers.PUBLIC;                 
1585                                         
1586                 foreach (VariableDeclaration var in (ArrayList) $2){
1587                         Location l = var.Location;
1588
1589                         Field field = new Field (var.type, mod, var.identifier, 
1590                                                  var.expression_or_array_initializer, 
1591                                                  (Attributes) null, l);
1592
1593                         CheckDef (current_container.AddField (field), field.Name, l);
1594                 }
1595           }
1596         ;
1597         
1598 withevents_declaration
1599         : WITHEVENTS variable_declarators EOL
1600           {
1601                 /* WithEvents Fields must be resolved into properties
1602                    with a bit of magic behind the scenes */
1603                   
1604                 VariableDeclaration.FixupTypes ((ArrayList) $2);
1605                 
1606                 foreach (VariableDeclaration var in (ArrayList) $2) {
1607                         // 1 - We create a private field
1608                         Location l = var.Location;
1609                         Property prop;
1610                         if ((current_modifiers & Modifiers.STATIC) > 0) 
1611                                 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1612                         
1613                         Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, 
1614                                                  var.expression_or_array_initializer, 
1615                                                  (Attributes) null, l);
1616
1617                         CheckDef (current_container.AddField (field), field.Name, l);   
1618                         
1619                         // 2 - Public property
1620                                 
1621                         prop = BuildSimpleProperty (var.type, (string) var.identifier, 
1622                                                 field, (int) current_modifiers, 
1623                                                 (Attributes) current_attributes, l);
1624                         
1625                         CheckDef (current_container.AddProperty (prop), prop.Name, l);
1626                 }               
1627           }
1628         ;
1629         
1630 opt_dim_stmt 
1631         : /* empty */
1632         | DIM
1633         ; 
1634                 
1635 delegate_declaration
1636         : DELEGATE SUB  
1637           identifier OPEN_PARENS 
1638           opt_formal_parameter_list
1639           CLOSE_PARENS 
1640           EOL
1641           {
1642                 Location l = lexer.Location;
1643                 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr, 
1644                                              (int) current_modifiers, 
1645                                              MakeName ((string) $3), (Parameters) $5, 
1646                                              (Attributes) current_attributes, l);
1647                                                   
1648                 del.Namespace = current_namespace;
1649                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1650           }     
1651         | DELEGATE FUNCTION       
1652           identifier OPEN_PARENS 
1653           opt_formal_parameter_list
1654           CLOSE_PARENS AS type
1655           {
1656                 Location l = lexer.Location;
1657                 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
1658                         current_container,
1659                         (Expression) $8, (int) current_modifiers, MakeName ((string) $3), 
1660                         (Parameters) $5, (Attributes) current_attributes, l);
1661
1662                 del.Namespace = current_namespace;
1663                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1664           }
1665         ;
1666         
1667 opt_evt_handler
1668         : /* empty */
1669           {     $$ = null; }
1670         | HANDLES qualified_identifier
1671           {
1672                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
1673           }
1674         | HANDLES MYBASE DOT qualified_identifier
1675           {
1676                 // FIXME: this is blatantly wrong and crash-prone
1677                 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
1678           }
1679         ;       
1680
1681 opt_empty_parens
1682         : /* empty */
1683         | OPEN_PARENS CLOSE_PARENS
1684         ;       
1685         
1686 static_constructor_declaration
1687         : SHARED SUB NEW opt_empty_parens EOL
1688           {
1689                 current_local_parameters = Parameters.EmptyReadOnlyParameters;
1690                 start_block();
1691                 oob_stack.Push (lexer.Location);
1692
1693                 Location l = (Location) oob_stack.Pop ();
1694                 $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
1695           }
1696           opt_statement_list
1697           { 
1698                 Constructor c = (Constructor) $1;
1699                 c.Block = (Block) end_block();
1700                 c.ModFlags = (int) current_modifiers;
1701                 c.OptAttributes = current_attributes;
1702                 
1703                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1704                 current_local_parameters = null;
1705           }
1706           END SUB EOL
1707         
1708 constructor_declaration
1709         : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1710           {
1711                 current_local_parameters = (Parameters) $4;
1712                 start_block();
1713                 oob_stack.Push (lexer.Location);
1714
1715                 Location l = (Location) oob_stack.Pop ();
1716                 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1717                 $1 = $$;
1718           }
1719           opt_statement_list
1720           { 
1721                 Constructor c = (Constructor) $1;
1722                 c.Block = (Block) end_block();
1723                 c.ModFlags = (int) current_modifiers;
1724                 c.OptAttributes = current_attributes;
1725                 
1726                 // FIXME: This should happen at grammar level, but doing it
1727                 // triggers a lot of conflicts/problems.
1728                 c.Initializer = FixConstructorInitializer (ref c.Block.statements);
1729
1730                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1731                 current_local_parameters = null;
1732           }
1733           END SUB EOL
1734         ;
1735         
1736 opt_formal_parameter_list
1737         : /* empty */                   
1738           { 
1739                 $$ = Parameters.EmptyReadOnlyParameters; 
1740           }
1741         | formal_parameter_list 
1742           { 
1743                 $$ = $1;        
1744                 //Parameter p = ((Parameters) $1).FixedParameters[0];
1745           }
1746         ;
1747         
1748 formal_parameter_list
1749         : fixed_parameters              
1750           { 
1751                 ArrayList pars_list = (ArrayList) $1;
1752
1753                 Parameter [] pars = new Parameter [pars_list.Count];
1754                 pars_list.CopyTo (pars);
1755                 $$ = new Parameters (pars, null, lexer.Location); 
1756           } 
1757         | fixed_parameters COMMA parameter_array
1758           {
1759                 ArrayList pars_list = (ArrayList) $1;
1760
1761                 Parameter [] pars = new Parameter [pars_list.Count];
1762                 pars_list.CopyTo (pars);
1763
1764                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1765           }
1766         | parameter_array 
1767           {
1768                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1769           }
1770         ;
1771
1772 fixed_parameters
1773         : fixed_parameter       
1774           {
1775                 ArrayList pars = new ArrayList ();
1776
1777                 pars.Add ($1);
1778                 $$ = pars;
1779           }
1780         | fixed_parameters COMMA fixed_parameter
1781           {
1782                 ArrayList pars = (ArrayList) $1;
1783
1784                 pars.Add ($3);
1785                 $$ = $1;
1786           }
1787         ;
1788
1789 fixed_parameter
1790         : opt_attributes
1791           opt_parameter_modifier
1792           identifier opt_rank_specifiers opt_type_spec opt_variable_initializer
1793           {
1794                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1795                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1796                 Expression ptype;
1797                 
1798                 if (opt_parm && ($6 == null))
1799                         Report.Error (999, "Optional parameters must have a default value");
1800                 
1801                 if (opt_parm) {
1802                         if ((pm & Parameter.Modifier.REF) !=0)
1803                                 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1804                         else
1805                                 pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
1806                 }       
1807                 
1808                 if ($4 == null)
1809                         ptype = (Expression) $5;
1810                 else
1811                 {
1812                         //string t = ((Expression) $5).ToString() + (string) $4;
1813                         string t = ((Expression) $5).ToString() + VariableDeclaration.BuildRank ((ArrayList) $4);
1814                         ptype = DecomposeQI (t, lexer.Location);
1815                 }                       
1816                 $$ = new Parameter (ptype, (string) $3, pm,
1817                                         (Attributes) $1, (Expression) $6, opt_parm);
1818           }
1819         ;
1820         
1821 parameter_array
1822         : PARAM_ARRAY identifier opt_parens AS type 
1823           { 
1824                 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1825                 // note  ("type must be a single-dimension array type"); 
1826           }
1827         ;
1828                 
1829 opt_parens
1830         : /* empty */
1831         | OPEN_PARENS CLOSE_PARENS
1832         ;
1833         
1834 opt_parameter_modifier
1835         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
1836         | parameter_modifiers   { $$ = $1;                      }
1837         ;
1838
1839 parameter_modifiers
1840         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1841         | parameter_modifier                            { $$ = $1;      }
1842         ;
1843         
1844 parameter_modifier
1845         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1846         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
1847         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
1848         ;       
1849
1850 opt_statement_list
1851         : /* empty */
1852         | statement_list end_of_stmt
1853         ;
1854
1855 statement_list
1856         : statement 
1857         | statement_list end_of_stmt statement
1858         ;
1859         
1860 statement : 
1861             declaration_statement
1862             {
1863                 if ($1 != null && (Block) $1 != current_block){
1864                         current_block.AddStatement ((Statement) $1);
1865                         current_block = (Block) $1;
1866                 }
1867             }
1868           | embedded_statement 
1869             {
1870                 Statement s = (Statement) $1;
1871
1872                 current_block.AddStatement ((Statement) $1);
1873             } 
1874           | labeled_statement 
1875           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1876            {
1877                 AddHandler ((Expression) $2, (string) $5);
1878            }
1879           | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1880             {
1881                 RaiseEvent ((string) $2, (ArrayList) $4);
1882             }
1883           | array_handling_statement
1884           /* | empty_statement */
1885           ;     
1886
1887 labeled_statement
1888         : identifier COLON end_of_stmt 
1889           {
1890                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1891
1892                 if (!current_block.AddLabel ((string) $1, labeled)){
1893                         Location l = lexer.Location;
1894                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1895                 }       
1896                 current_block.AddStatement (labeled);
1897           }
1898           statement
1899         ;
1900
1901 embedded_statement
1902         : expression_statement
1903         | selection_statement
1904         | iteration_statement
1905         | try_statement
1906         | jump_statement 
1907         ;
1908 /*        
1909 empty_statement
1910         : end_of_stmt
1911           {
1912                   $$ = new EmptyStatement ();
1913           }
1914         ;        
1915 */
1916         
1917 array_handling_statement
1918         : redim_statement
1919         | erase_statement
1920         ;
1921         
1922 redim_statement
1923         : REDIM opt_preserve invocation_expression opt_array_initializer
1924           {
1925                 Invocation i = (Invocation) $3;
1926                 ReDim r = new ReDim (i.expr, i.Arguments, (bool) $2, (ArrayList) $4, lexer.Location);
1927                 current_block.AddStatement (r); 
1928           }
1929         ;       
1930         
1931 opt_preserve
1932         : /* empty */   { $$ = false; }
1933         | PRESERVE      { $$ = true;  }
1934         ;
1935         
1936 redim_clauses
1937         : redim_clause
1938           {
1939                 ArrayList clauses = new ArrayList ();
1940
1941                 clauses.Add ($1);
1942                 $$ = clauses;
1943           }     
1944         | redim_clauses COMMA redim_clause
1945           {
1946                 ArrayList clauses = (ArrayList) ($1);
1947                 clauses.Add ($2);
1948
1949                 $$ = clauses;
1950           }     
1951         ;
1952
1953 redim_clause
1954         : invocation_expression
1955         /* : identifier OPEN_PARENS expression_list CLOSE_PARENS opt_array_initializer */
1956         ;
1957
1958 opt_array_initializer
1959         : /* empty */
1960         | array_initializer
1961         ;
1962                         
1963 erase_statement
1964         : ERASE primary_expression
1965         ;       
1966                         
1967 jump_statement
1968         : /*break_statement
1969         | continue_statement
1970         | */return_statement
1971         | goto_statement        
1972         | throw_statement       
1973         | exit_statement
1974         | yield_statement
1975         ;
1976                 
1977 goto_statement
1978         : GOTO identifier  
1979           {
1980                 $$ = new Goto (current_block, (string) $2, lexer.Location);
1981           }
1982         ;
1983         
1984 throw_statement
1985         : THROW opt_expression
1986           {
1987                 $$ = new Throw ((Expression) $2, lexer.Location);
1988           }
1989         ;       
1990                         
1991 exit_statement
1992         : EXIT exit_type
1993           {
1994                 $$ = new Exit ((ExitType)$2, lexer.Location);           
1995           }
1996         ;
1997         
1998 exit_type
1999         : DO            { $$ = ExitType.DO;             }
2000         | FOR           { $$ = ExitType.FOR;            }
2001         | WHILE         { $$ = ExitType.WHILE;          }
2002         | SELECT        { $$ = ExitType.SELECT;         }
2003         | SUB           { $$ = ExitType.SUB;            }
2004         | FUNCTION      { $$ = ExitType.FUNCTION;       }
2005         | PROPERTY      { $$ = ExitType.PROPERTY;       }
2006         | TRY           { $$ = ExitType.TRY;            }
2007         ;
2008 return_statement
2009         : RETURN opt_expression 
2010           {       
2011                 $$ = new Return ((Expression) $2, lexer.Location);
2012           }
2013         ;
2014                 
2015 iteration_statement
2016         : while_statement
2017         | do_statement
2018         | for_statement
2019         | foreach_statement
2020         ;
2021
2022 foreach_statement
2023         : FOR EACH identifier IN 
2024           {
2025                 oob_stack.Push (lexer.Location);
2026           }       
2027           expression end_of_stmt
2028           {
2029                 
2030                 start_block();
2031                 Block foreach_block = current_block;
2032                 Location l = lexer.Location;            
2033                 LocalVariableReference v = null;
2034                 VariableInfo vi;
2035
2036                 vi = foreach_block.GetVariableInfo ((string) $3);
2037                 if (vi != null) {
2038                         // Get a reference to this variable.
2039                         v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2040                 }
2041                 else
2042                         Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2043         
2044                 oob_stack.Push (v);
2045           }       
2046           opt_statement_list
2047           NEXT opt_identifier
2048           {
2049                 Block foreach_block = current_block;
2050                 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2051                 Block prev_block = end_block();
2052                 Location l = (Location) oob_stack.Pop ();
2053
2054                 Foreach f = null;
2055                 if (v != null) {
2056                         f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
2057                 }
2058                 
2059                 $$ = f;
2060           }       
2061         ;
2062
2063 yield_statement 
2064         : YIELD expression
2065           {
2066                 if (!UseExtendedSyntax)
2067                 {
2068                         ReportError9998();
2069                         $$ = null;
2070                 }
2071 /*              else
2072                         if (iterator_container == null){
2073                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2074                                 $$ = null;
2075                         } else {
2076                                 iterator_container.SetYields ();
2077                                 $$ = new Yield ((Expression) $2, lexer.Location);
2078                         } */
2079           }
2080         | YIELD STOP
2081           {
2082                 if (!UseExtendedSyntax)
2083                 {
2084                         ReportError9998();
2085                         $$ = null;
2086                 }
2087 /*              else
2088                         if (iterator_container == null){
2089                                 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2090                                 $$ = null;
2091                         } else {
2092                                 iterator_container.SetYields ();
2093                                 $$ = new YieldBreak (lexer.Location);
2094                         } */
2095           }
2096         ;
2097
2098
2099
2100 try_statement
2101         : try_catch
2102         | try_catch_finally
2103         ;
2104                                 
2105 try_header
2106         : TRY end_of_stmt
2107           {   
2108                 start_block();  
2109           }
2110           opt_statement_list 
2111           opt_catch_clauses
2112           {
2113                 tmp_catch_clauses = (ArrayList) $5;
2114           }
2115         ;
2116                                         
2117 try_catch
2118         : try_header 
2119           END TRY
2120           { 
2121                 Catch g = null;
2122                 ArrayList s = new ArrayList ();
2123
2124                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2125                         if (cc.IsGeneral)
2126                                 g = cc;
2127                         else
2128                                 s.Add (cc);
2129                 }
2130
2131                 // Now s contains the list of specific catch clauses
2132                 // and g contains the general one.
2133                 Block b = end_block();
2134
2135                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2136           }       
2137         ;       
2138           
2139 try_catch_finally
2140         : try_header 
2141           { 
2142                 tmp_block = end_block(); 
2143           }     
2144           FINALLY end_of_stmt
2145           { 
2146                 start_block(); 
2147           }       
2148           opt_statement_list 
2149           END TRY
2150           {
2151                 Catch g = null;
2152                 ArrayList s = new ArrayList ();
2153                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2154
2155                 if (catch_list != null){
2156                         foreach (Catch cc in catch_list) {
2157                                 if (cc.IsGeneral)
2158                                         g = cc;
2159                                 else
2160                                         s.Add (cc);
2161                         }
2162                 }
2163
2164                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2165         
2166           }     
2167           ;             
2168
2169 opt_catch_clauses
2170         : /* empty */  {  $$ = null;  }
2171         | catch_clauses
2172         ;
2173
2174 catch_clauses
2175         : catch_clause 
2176           {
2177                 ArrayList l = new ArrayList ();
2178
2179                 l.Add ($1);
2180                 $$ = l;
2181           }
2182         | catch_clauses catch_clause
2183           {
2184                 ArrayList l = (ArrayList) $1;
2185
2186                 l.Add ($2);
2187                 $$ = l;
2188           }
2189         ;
2190
2191 opt_identifier
2192         : /* empty */   {  $$ = null;  }
2193         | identifier
2194         ;
2195
2196 catch_clause 
2197         : CATCH opt_catch_args end_of_stmt
2198         {
2199                 Expression type = null;
2200                 string id = null;
2201                 
2202                 if ($2 != null) {
2203                         DictionaryEntry cc = (DictionaryEntry) $2;
2204                         type = (Expression) cc.Key;
2205                         id   = (string) cc.Value;
2206                         
2207                         if (id != null){
2208                                 ArrayList one = new ArrayList ();
2209                                 Location loc = lexer.Location;
2210
2211                                 one.Add (new VariableDeclaration (id, type, loc));
2212
2213
2214                                 $1 = current_block;
2215                                 current_block = new Block (current_block);
2216                                 Block b = declare_local_variables (type, one, loc);
2217                                 current_block = b;
2218                         }
2219                 }
2220         
2221         } 
2222         opt_statement_list {
2223                 Expression type = null;
2224                 string id = null;
2225                 Block b_catch = current_block;
2226                 
2227                 if ($2 != null){
2228                         DictionaryEntry cc = (DictionaryEntry) $2;
2229                         type = (Expression) cc.Key;
2230                         id   = (string) cc.Value;
2231                         
2232                         if ($1 != null) {
2233                                 //
2234                                 // FIXME: I can change this for an assignment.
2235                                 //
2236                                 while (current_block != (Block) $1)
2237                                         current_block = current_block.Parent;
2238                         }
2239                 }
2240
2241                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2242         }
2243         ;
2244
2245 opt_catch_args
2246         : /* empty */ {  $$ = null; }
2247         | catch_args
2248         ;         
2249
2250 catch_args 
2251         : identifier AS type
2252         {
2253                  $$ = new DictionaryEntry ($3, $1); 
2254         }
2255         ;
2256         
2257         
2258 do_statement
2259         : DO opt_do_construct end_of_stmt
2260           {
2261                 start_block();
2262                 oob_stack.Push (lexer.Location);
2263           }     
2264           opt_statement_list
2265           LOOP opt_do_construct
2266           {
2267                 Expression t_before = (Expression) $2;
2268                 Expression t_after = (Expression) $7;
2269                 Expression t;
2270
2271                 if  ((t_before != null) && (t_after != null))
2272                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2273
2274                 if ((t_before == null) && (t_after == null))
2275                         t = new BoolLiteral (true);
2276                 else
2277                         t = (t_before != null) ? t_before : t_after;
2278                         
2279                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2280                 
2281                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2282                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2283                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2284                          
2285                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2286           }
2287           ;
2288
2289 opt_do_construct
2290         : /* empty */ { $$ = null; }
2291         | while_or_until boolean_expression
2292           {
2293                 do_type = (DoOptions)$1;
2294                 $$ = (Expression) $2;
2295           }
2296         ;
2297
2298 while_or_until
2299         : WHILE { $$ = DoOptions.WHILE; }
2300         | UNTIL { $$ = DoOptions.UNTIL; }
2301         ;
2302
2303 while_statement
2304         : WHILE
2305         {
2306                 start_block();
2307                 oob_stack.Push (lexer.Location);
2308         }
2309         boolean_expression end_of_stmt
2310         opt_statement_list
2311         END WHILE
2312         {
2313                 Location l = (Location) oob_stack.Pop ();
2314                 Block b = end_block();
2315                 Expression e = (Expression) $3;
2316                 $$ = new While ((Expression) e, (Statement) b, l);
2317         }
2318         ;
2319         
2320                 
2321 for_statement
2322         : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2323           {
2324                 start_block();
2325           }
2326           opt_statement_list
2327           NEXT opt_identifier 
2328           {
2329                 Block statement = end_block();
2330                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2331                 
2332                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2333                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
2334                                                 for_var, (Expression) $6, lexer.Location);
2335                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2336                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
2337                                  
2338                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
2339                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2340                 
2341                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
2342           }       
2343         ;
2344
2345 opt_step
2346         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
2347         | STEP expression       { $$ = $2; }
2348         ;
2349
2350 opt_next_identifier
2351         : /* empty */
2352         | qualified_identifier
2353         ;
2354
2355 selection_statement
2356         : if_statement
2357         | select_statement
2358         ;
2359
2360 if_statement
2361         : if_statement_open opt_then if_statement_rest
2362           {
2363                 $$ = $3;
2364           }
2365         | if_statement_open THEN pre_embedded_statement
2366           {
2367                 Location l = (Location) oob_stack.Pop ();
2368                 tmp_expr = (Expression)expr_stack.Pop(); 
2369                 $$ = new If ((Expression) tmp_expr, end_block(), l);
2370           }
2371         ;
2372
2373 pre_embedded_statement
2374         : embedded_statement 
2375           {
2376                 Statement s = (Statement) $1;
2377
2378                 current_block.AddStatement ((Statement) $1);
2379           } 
2380         ;       
2381         
2382 if_statement_open
2383         : IF boolean_expression 
2384           {
2385                 oob_stack.Push (lexer.Location);
2386                 start_block();
2387                 tmp_expr = (Expression) $2;
2388                 expr_stack.Push(tmp_expr);
2389           }
2390          ;
2391
2392 opt_then
2393         : /* empty */
2394         | THEN
2395         ;
2396         
2397 if_statement_rest
2398         : end_of_stmt
2399           opt_statement_list
2400           END IF
2401           { 
2402                 Location l = (Location) oob_stack.Pop ();
2403                 Expression expr = (Expression)expr_stack.Pop(); 
2404                 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2405           }       
2406         | end_of_stmt
2407           opt_statement_list
2408           ELSE end_of_stmt 
2409           { 
2410                 Block bl = end_block(); 
2411                 tmp_blocks.Push(bl); 
2412                 start_block();
2413           }
2414           opt_statement_list
2415           END IF        
2416           {
2417                 Location l = (Location) oob_stack.Pop ();
2418                 tmp_expr = (Expression)expr_stack.Pop(); 
2419                 tmp_block = (Block) tmp_blocks.Pop(); 
2420                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2421           }     
2422         | end_of_stmt
2423           opt_statement_list 
2424           ELSEIF boolean_expression opt_then 
2425           { 
2426                 tmp_expr = (Expression) $4;                                                  
2427                 expr_stack.Push(tmp_expr);                                                 
2428                 tmp_block = end_block();
2429                 tmp_blocks.Push(tmp_block);
2430                 start_block();
2431           }
2432           else_if_statement_rest 
2433           {
2434                 Statement stmt = (Statement) statement_stack.Pop();
2435                 Block bl = (Block) tmp_blocks.Pop();  
2436                 Expression expr =  (Expression)expr_stack.Pop();  
2437                 Location l = (Location) oob_stack.Pop ();
2438                 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l); 
2439           }
2440         ;
2441         
2442         
2443 else_if_statement_rest
2444         : end_of_stmt
2445           opt_statement_list 
2446           END IF
2447           { 
2448                 Location l = (Location) oob_stack.Pop ();
2449                 oob_stack.Push (l);
2450                 Expression expr = (Expression)expr_stack.Pop(); 
2451                 Statement stmt = (Statement) new If ((Expression) expr, (Statement)  end_block(), l);
2452                 statement_stack.Push(stmt);
2453           }
2454         | end_of_stmt
2455           opt_statement_list
2456           ELSE end_of_stmt 
2457           { 
2458                 Block bl = end_block();
2459                 tmp_blocks.Push(bl);
2460                 start_block();
2461           }
2462           opt_statement_list
2463           END IF        
2464           {
2465                 Location l = (Location) oob_stack.Pop ();
2466                 oob_stack.Push (l);
2467                 Expression expr = (Expression)expr_stack.Pop(); 
2468                 Block bl = (Block)tmp_blocks.Pop(); 
2469                 Statement stmt = (Statement) new If ((Expression) expr,  (Statement) bl , (Statement)  end_block(), l);
2470                 statement_stack.Push(stmt);
2471           }     
2472         | end_of_stmt
2473           opt_statement_list 
2474           ELSEIF boolean_expression opt_then 
2475           { 
2476                 expr_stack.Push((Expression) $4);                                                 
2477                 Block bl = end_block();
2478                 tmp_blocks.Push(bl);
2479                 start_block();
2480           }
2481           else_if_statement_rest 
2482           {
2483                 Location l = (Location) oob_stack.Pop ();
2484                 oob_stack.Push (l);
2485                 Statement tmp_stmt = (Statement)statement_stack.Pop();
2486                 Block bl = (Block) tmp_blocks.Pop();  
2487                 Expression expr =  (Expression)expr_stack.Pop();  
2488                 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
2489                 statement_stack.Push(stmt);
2490           }          
2491         ;
2492         
2493 select_statement
2494         : SELECT opt_case expression end_of_stmt
2495           { 
2496                 oob_stack.Push (lexer.Location);
2497                 switch_stack.Push (current_block);
2498           }     
2499           opt_case_sections
2500           END SELECT 
2501           {
2502                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2503                 current_block = (Block) switch_stack.Pop ();
2504           }       
2505         ;
2506
2507 opt_case_sections
2508         : /* empty */   { $$ = null; }
2509         | case_sections { $$ = $1; }
2510         ;
2511         
2512 case_sections
2513         : case_sections case_section
2514           {
2515                 ArrayList sections = (ArrayList) $1;
2516
2517                 sections.Add ($2);
2518                 $$ = sections;
2519           }
2520         | case_section
2521           {
2522                 ArrayList sections = new ArrayList ();
2523
2524                 sections.Add ($1);
2525                 $$ = sections;
2526           }
2527         ;
2528
2529 case_section
2530         : CASE case_clauses end_of_stmt
2531           { 
2532                 start_block();
2533           }
2534           opt_statement_list
2535           {
2536                 Block topmost = current_block;
2537
2538                 while (topmost.Implicit)
2539                         topmost = topmost.Parent;
2540                         
2541                 // FIXME: This is a horrible hack which MUST go                 
2542                 topmost.statements.Add (new Break (lexer.Location));
2543                 $$ = new SwitchSection ((ArrayList) $2, topmost);
2544           }
2545           | CASE ELSE end_of_stmt
2546             /* FIXME: we should somehow flag an error 
2547                (BC30321 'Case' cannot follow a 'Case Else' 
2548                in the same 'Select' statement.) 
2549                if Case Else is not the last of the Case clauses
2550             */
2551           { 
2552                 start_block();
2553           }     
2554           opt_statement_list
2555           { 
2556                 Block topmost = current_block;
2557
2558                 while (topmost.Implicit)
2559                         topmost = topmost.Parent;
2560                         
2561                 // FIXME: This is a horrible hack which MUST go                 
2562                 topmost.statements.Add (new Break (lexer.Location));
2563                 
2564                 ArrayList a = new ArrayList();
2565                 a.Add (new SwitchLabel (null, lexer.Location));                 
2566                 $$ = new SwitchSection ((ArrayList) a, topmost);                
2567           }
2568         ;         
2569         
2570 case_clauses
2571         : case_clause
2572           {
2573                 ArrayList labels = new ArrayList ();
2574
2575                 labels.Add ($1);
2576                 $$ = labels;
2577           }     
2578         | case_clauses COMMA case_clause
2579           {
2580                 ArrayList labels = (ArrayList) ($1);
2581                 labels.Add ($2);
2582
2583                 $$ = labels;
2584           }     
2585         ;
2586         
2587 case_clause
2588         : opt_is comparison_operator expression
2589         | expression
2590           {
2591                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2592           }
2593         ;
2594         
2595 opt_is 
2596         : /* empty */
2597         | IS
2598         ;
2599
2600 comparison_operator
2601         : OP_LT
2602         | OP_GT
2603         | OP_LE
2604         | OP_NE
2605         /*| OP_EQ */
2606         ;
2607
2608 opt_case
2609         : /* empty */
2610         | CASE
2611         ;
2612
2613 expression_statement
2614         : statement_expression 
2615           {
2616                  $$ = $1; 
2617           }
2618         ;
2619
2620
2621 statement_expression
2622         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2623         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2624         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2625         ;
2626
2627 object_creation_expression
2628         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2629           {
2630                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2631           }
2632         | NEW type
2633           {
2634                 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
2635           }
2636         ;
2637         
2638 array_creation_expression
2639         : object_creation_expression array_initializer
2640           {
2641                 New n = (New) $1;
2642                 ArrayList dims = new ArrayList();
2643                 
2644                 if (n.Arguments != null) {
2645                         foreach (Argument a in n.Arguments) {
2646                                 dims.Add (a.Expr);
2647                         }
2648                 }
2649                         
2650                 Expression atype = n.RequestedType;
2651         
2652                 if (VariableDeclaration.IndexesSpecified(this)) {
2653                         $$ = new ArrayCreation (atype, dims, "", (ArrayList) $2, lexer.Location); 
2654                 }
2655                 else
2656                 {
2657                         string rank = VariableDeclaration.BuildRank (dims);
2658                         $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location); 
2659                 }
2660                 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
2661           }
2662         ;       
2663
2664 new_expression
2665         : object_creation_expression
2666         | array_creation_expression
2667         ;
2668
2669 declaration_statement
2670         : local_variable_declaration 
2671           {
2672                 if ($1 != null){
2673                         DictionaryEntry de = (DictionaryEntry) $1;
2674
2675                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2676                 }
2677           }
2678
2679         | local_constant_declaration 
2680           {
2681                 if ($1 != null){
2682                         DictionaryEntry de = (DictionaryEntry) $1;
2683
2684                         $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
2685                 }
2686           }
2687         ;        
2688         
2689 local_variable_declaration
2690         : DIM variable_declarators
2691           {
2692                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
2693           }
2694         ;
2695
2696         
2697 local_constant_declaration
2698         : CONST constant_declarator
2699           {
2700                 if ($2 != null)
2701                         $$ = new DictionaryEntry ($1, $2);
2702                 else
2703                         $$ = null;
2704           }
2705         ;        
2706         
2707 constant_declarator
2708         : identifier ASSIGN constant_expression
2709           {
2710                 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
2711           }
2712         ;               
2713
2714 variable_declarators
2715         : variable_declarator 
2716           {
2717                 ArrayList decl = new ArrayList ();
2718                 decl.Add ($1);
2719                 $$ = decl;
2720           }
2721         | variable_declarators COMMA variable_declarator
2722           {
2723                 ArrayList decls = (ArrayList) $1;
2724                 decls.Add ($3);
2725                 $$ = $1;
2726           }
2727         ;
2728
2729 variable_declarator
2730         : variable_identifier opt_type_decl opt_variable_initializer
2731           {
2732                 string varname = (string)$1;
2733                 object varinit = $3;
2734                 Expression vartype;
2735                 ArrayList a_dims = null;
2736                 
2737                 // Some checking is required for particularly weird declarations
2738                 // like Dim a As Integer(,)
2739                 if ($2 is Pair) {
2740                         vartype = (Expression) ((Pair) $2).First;
2741                         if ($3 != null && $3 is ArrayList)
2742                                 Report.Error (205, "End of statement expected.");
2743                                 
2744                         ArrayList args = (ArrayList) ((Pair) $2).Second;
2745                         if (VariableDeclaration.HasExplicitIndexes (args))        
2746                                 Report.Error (638, "Array bounds cannot appear in type specifiers.");   
2747         
2748                         string s_vartype = vartype.ToString();                          
2749                         s_vartype += "[";
2750                         if (args != null)
2751                                 for (int x = 0; x < args.Count; x++)
2752                                         s_vartype += ",";
2753                                 
2754                         s_vartype += "]";       
2755                         vartype = DecomposeQI(s_vartype, Location.Null);                                                
2756                 }
2757                 else
2758                         vartype = (Expression) $2;
2759                                         
2760                 /*
2761                    Check for a declaration like Dim a(2) or Dim a(2,3)
2762                    If this is the case, we must generate an ArrayCreationExpression
2763                    and, in case, add the initializer after the array has been created.
2764                 */
2765                 if (VariableDeclaration.IsArrayDecl (this)) {   
2766                         if (VariableDeclaration.IndexesSpecified(this)) {   
2767                                 a_dims = (ArrayList) current_rank_specifiers;
2768                                 //varinit = new ArrayCreation (vartype, a_dims, "", (ArrayList) varinit, lexer.Location);
2769                                 varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
2770                         }
2771
2772                         vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
2773                 }
2774
2775                 if (vartype is New) {
2776                         if (varinit != null) {
2777                                 Report.Error (30205, lexer.Location, "End of statement expected");
2778                                 $$ = null;
2779                         }
2780                         else
2781                         {
2782                                 varinit = vartype;
2783                                 vartype = ((New)vartype).RequestedType;
2784                         }
2785                 }
2786                 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
2787                 //Console.WriteLine ("varname: {0} - vartype: {1} - init: {2}", varname, vartype, varinit);
2788           }
2789         ;
2790
2791 variable_identifier
2792         : identifier opt_array_name_modifier 
2793           {
2794                 $$ = $1; 
2795                 current_rank_specifiers = (ArrayList) $2;
2796           }
2797         ;               
2798                 
2799 opt_type_spec
2800         : /* empty */   
2801           { 
2802                 $$ = null;              
2803           }
2804         | AS type       
2805           { 
2806                 $$ = (Expression) $2;
2807           }
2808         ;
2809                         
2810 opt_type_decl
2811         : opt_type_spec
2812           {
2813                 $$ = $1;
2814           }
2815         | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS
2816           {
2817                 $$ = new Pair ($2, $4);;
2818           }
2819         | AS NEW type
2820           {
2821                 New n = new New ((Expression)$3, null, lexer.Location);
2822                 $$ = (Expression) n;
2823           }
2824         | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS 
2825           {
2826                 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
2827                 $$ = (Expression) n;
2828           }
2829         ;
2830                 
2831 opt_array_name_modifier
2832         : /* empty */                           { $$ = null; }
2833         | array_type_modifier                   { $$ = $1;   }
2834         ;
2835         
2836 array_type_modifier
2837         : rank_specifiers               { $$ = $1; }
2838         ;
2839         
2840 opt_variable_initializer
2841         : /* empty */                   { $$ = null; }
2842         | ASSIGN variable_initializer   { $$ = $2; }
2843         ;
2844                 
2845 variable_initializer
2846         : expression
2847           {
2848                 $$ = $1;
2849           }
2850         | array_initializer
2851           {
2852                 $$ = $1;
2853           }
2854         
2855         ;       
2856         
2857 array_initializer
2858         : OPEN_BRACE CLOSE_BRACE
2859           {
2860                 ArrayList list = new ArrayList ();
2861                 $$ = list;
2862           }
2863         | OPEN_BRACE variable_initializer_list CLOSE_BRACE
2864           {
2865                 $$ = (ArrayList) $2;
2866           }
2867         ;
2868
2869 variable_initializer_list
2870         : variable_initializer
2871           {
2872                 ArrayList list = new ArrayList ();
2873                 list.Add ($1);
2874                 $$ = list;
2875           }
2876         | variable_initializer_list COMMA variable_initializer
2877           {
2878                 ArrayList list = (ArrayList) $1;
2879                 list.Add ($3);
2880                 $$ = list;
2881           }
2882         ;       
2883                 
2884 /* 
2885  * The following is from Rhys' grammar:
2886  * > Types in local variable declarations must be recognized as 
2887  * > expressions to prevent reduce/reduce errors in the grammar.
2888  * > The expressions are converted into types during semantic analysis.
2889  */
2890 local_variable_type
2891         : primary_expression opt_rank_specifiers
2892           { 
2893                 // FIXME: Do something smart here regarding the composition of the type.
2894
2895                 // Ok, the above "primary_expression" is there to get rid of
2896                 // both reduce/reduce and shift/reduces in the grammar, it should
2897                 // really just be "type_name".  If you use type_name, a reduce/reduce
2898                 // creeps up.  If you use qualified_identifier (which is all we need
2899                 // really) two shift/reduces appear.
2900                 // 
2901
2902                 // So the super-trick is that primary_expression
2903                 // can only be either a SimpleName or a MemberAccess. 
2904                 // The MemberAccess case arises when you have a fully qualified type-name like :
2905                 // Foo.Bar.Blah i;
2906                 // SimpleName is when you have
2907                 // Blah i;
2908                   
2909                 Expression expr = (Expression) $1;  
2910                 if (!(expr is SimpleName || expr is MemberAccess)) {
2911                         Error_ExpectingTypeName (lexer.Location, expr);
2912                         $$ = null;
2913                 } else {
2914                         //
2915                         // So we extract the string corresponding to the SimpleName
2916                         // or MemberAccess
2917                         // 
2918                         if ((string) $2 == "")
2919                                 $$ = $1;
2920                         else
2921                                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2922                 }
2923           }
2924         | builtin_types opt_rank_specifiers
2925           {
2926                 if ((string) $2 == "")
2927                         $$ = $1;
2928                 else
2929                         $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2930           }
2931         ;
2932                         
2933 opt_rank_specifiers
2934         : /* empty */
2935           {
2936                   // $$ = "";
2937                   $$ = null;
2938           }
2939         | rank_specifiers
2940           {
2941                         $$ = $1;
2942           }
2943         ;      
2944         
2945 rank_specifiers
2946         : rank_specifier
2947           {
2948                   ArrayList rs = new ArrayList();
2949                   rs.Add ($1);
2950                   $$ = rs;
2951           }
2952         | rank_specifiers rank_specifier
2953           {
2954                   ArrayList rs = (ArrayList) $1;
2955                   rs.Add ($2);
2956                   $$ = rs;
2957           }             
2958         ;               
2959         
2960 rank_specifier
2961         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
2962           {
2963                 $$ = $2;
2964           }
2965         ;
2966                 
2967 opt_dim_separators
2968         : /* empty */
2969           {
2970                 ArrayList ds = new ArrayList();
2971                 ds.Add (new EmptyExpression());
2972                 $$ = ds;                
2973           }
2974         | dim_separators
2975           {
2976                 ArrayList ds = (ArrayList) $1;
2977                 ds.Add (new EmptyExpression());
2978                 $$ = ds;        
2979           }     
2980         | dim_specifiers
2981           {
2982                 $$ = $1;
2983           }       
2984         ;
2985
2986 dim_separators
2987         : COMMA
2988           {
2989                 ArrayList ds = new ArrayList();
2990                 ds.Add (new EmptyExpression());
2991                 $$ = ds;
2992           }
2993         | dim_separators COMMA
2994           {
2995                 ArrayList ds = (ArrayList) $1;
2996                 ds.Add (new EmptyExpression());
2997                 $$ = ds;                
2998           }
2999         ;
3000
3001 dim_specifiers
3002         : expression
3003           {
3004                 ArrayList ds = new ArrayList();
3005                 ds.Add ((Expression) $1);
3006                 $$ = ds;
3007           }     
3008         | dim_specifiers COMMA expression
3009           {
3010                 ArrayList ds = (ArrayList) $1;
3011                 ds.Add ((Expression) $3);
3012                 $$ = ds;                
3013           }     
3014         ;
3015         
3016 /* Expressions */
3017 primary_expression
3018         : literal
3019           {
3020                 // 7.5.1: Literals
3021           }
3022
3023         | qualified_identifier
3024           {
3025                 string name = (string) $1;
3026
3027                 $$ = DecomposeQI (name, lexer.Location);
3028           }
3029         | parenthesized_expression
3030         | member_access
3031         | invocation_expression
3032         //| element_access
3033         | this_access
3034         | base_access
3035         | new_expression
3036         | cast_expression
3037         ;
3038
3039 literal
3040         : boolean_literal
3041         | integer_literal
3042         | real_literal
3043         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
3044         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
3045         | NOTHING                       { $$ = NullLiteral.Null; }
3046         ;
3047
3048 real_literal
3049         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
3050         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
3051         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3052         ;
3053
3054 integer_literal
3055         : LITERAL_INTEGER       {
3056                 object v = lexer.Value;
3057
3058                 if (v is int)
3059                         $$ = new IntLiteral ((Int32) v); 
3060                 else if (v is uint)
3061                         $$ = new UIntLiteral ((UInt32) v);
3062                 else if (v is long)
3063                         $$ = new LongLiteral ((Int64) v);
3064                 else if (v is ulong)
3065                         $$ = new ULongLiteral ((UInt64) v);
3066                 else
3067                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
3068                         
3069           }
3070         ;
3071
3072 boolean_literal
3073         : TRUE                  { $$ = new BoolLiteral (true); }
3074         | FALSE                 { $$ = new BoolLiteral (false); }
3075         ;
3076
3077 parenthesized_expression
3078         : OPEN_PARENS expression CLOSE_PARENS
3079           { $$ = $2; }
3080         ;
3081
3082 member_access
3083         : primary_expression DOT identifier
3084           {
3085                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3086           }
3087         | primary_expression DOT NEW
3088           {
3089                 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3090           }       
3091         | predefined_type DOT identifier
3092           {
3093                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3094           }
3095         ;
3096
3097 predefined_type
3098         : builtin_types
3099         ;
3100
3101 invocation_expression
3102         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3103           {
3104                 if ($1 == null) {
3105                         Location l = lexer.Location;
3106                         Report.Error (1, l, "THIS IS CRAZY");
3107                 }
3108                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3109 //              Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3110           } 
3111         ;
3112         
3113 base_access
3114         : MYBASE DOT IDENTIFIER
3115           {
3116                 $$ = new BaseAccess ((string) $3, lexer.Location);
3117           }
3118         | MYBASE DOT NEW
3119           {
3120                 $$ = new BaseAccess ("New", lexer.Location);
3121           }
3122         ;       
3123
3124 opt_argument_list
3125         : argument_list
3126           { 
3127                 /*
3128                    The 'argument' rule returns an 'empty' argument
3129                    of type NoArg (used for default arguments in invocations)
3130                    if no arguments are actually passed.
3131
3132                    If there is only one argument and it is o type NoArg,
3133                    we return a null (empty) list
3134                 */
3135                 ArrayList args = (ArrayList) $1;
3136                 if (args.Count == 1 &&
3137                     ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3138                         $$ = null;
3139                 else
3140                         $$ = $1;
3141           }
3142         ;
3143
3144 argument_list
3145         : argument
3146           {
3147                 ArrayList list = new ArrayList ();
3148                 list.Add ($1);
3149                 $$ = list;
3150           }
3151         | argument_list COMMA argument
3152           {
3153                 ArrayList list = (ArrayList) $1;
3154                 list.Add ($3);
3155                 $$ = list;
3156           }
3157         ;
3158
3159 argument
3160         : expression
3161           {
3162                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3163           }
3164         | BYREF variable_reference
3165           {
3166                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3167           }
3168         | /* empty */
3169           {
3170                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3171           }
3172         ;
3173
3174 variable_reference
3175         : expression {/* note ("section 5.4"); */  $$ = $1;  }
3176         ;
3177
3178 negation_expression
3179         : NOT expression 
3180           {
3181                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3182           }
3183         ;
3184                 
3185 expression
3186         : conditional_expression { $$ = $1; }
3187         | negation_expression
3188         /*| assignment_expression*/
3189         ;
3190
3191 opt_expression
3192         : /* empty */
3193         | expression
3194         ;
3195         
3196 expression_list
3197         : expression
3198           {
3199                 ArrayList list = new ArrayList ();
3200                 list.Add ($1);
3201                 $$ = list;
3202           }
3203         | expression_list COMMA expression
3204           {
3205                 ArrayList list = (ArrayList) $1;
3206                 list.Add ($3);
3207                 $$ = list;
3208           }
3209         ;
3210
3211 opt_expression_list
3212         : /*empty */ { $$ = null; }
3213         | expression_list
3214         ;
3215         
3216 this_access
3217         : ME
3218           {
3219                 $$ = new This (current_block, lexer.Location);
3220           }
3221         | MYCLASS
3222           {
3223                 // FIXME: This is actually somewhat different from Me
3224                 $$ = new This (current_block, lexer.Location);
3225           }
3226         ;
3227
3228 unary_expression
3229         : primary_expression
3230         /*| NOT prefixed_unary_expression
3231           {
3232                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3233           }
3234         | cast_expression */
3235         ;
3236         
3237 cast_expression
3238         : cast_operator OPEN_PARENS expression CLOSE_PARENS
3239           {
3240                   $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3241           }     
3242         | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3243           {
3244                   $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3245           }                       
3246         ;
3247         
3248 cast_operator
3249         : CBOOL         { $$ = TypeManager.system_boolean_expr;         }
3250         | CBYTE         { $$ = TypeManager.system_byte_expr;            }
3251         | CCHAR         { $$ = TypeManager.system_char_expr;            }
3252         | CDATE         { $$ = TypeManager.system_decimal_expr;         } //FIXME
3253         | CDBL          { $$ = TypeManager.system_double_expr;          }
3254         | CDEC          { $$ = TypeManager.system_decimal_expr;         }
3255         | CINT          { $$ = TypeManager.system_int32_expr;           }
3256         | CLNG          { $$ = TypeManager.system_int64_expr;           }
3257         | COBJ          { $$ = TypeManager.system_object_expr;          }
3258         | CSHORT        { $$ = TypeManager.system_int16_expr;           }
3259         | CSNG          { $$ = TypeManager.system_single_expr;          }
3260         | CSTR          { $$ = TypeManager.system_string_expr;  }
3261         ;
3262         
3263         //
3264         // The idea to split this out is from Rhys' grammar
3265         // to solve the problem with casts.
3266         //
3267 prefixed_unary_expression
3268         : unary_expression
3269         | PLUS prefixed_unary_expression
3270           {
3271                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3272           }
3273         | MINUS prefixed_unary_expression
3274           {
3275                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3276           }
3277         | ADDRESSOF prefixed_unary_expression
3278           {
3279                 // FIXME: We should generate an error if AddressOf is NOT used
3280                 // during delegate creation
3281                 $$ = $2;
3282           }       
3283         ;
3284
3285 multiplicative_expression
3286         : prefixed_unary_expression
3287         | multiplicative_expression STAR prefixed_unary_expression
3288           {
3289                 $$ = new Binary (Binary.Operator.Multiply,
3290                                  (Expression) $1, (Expression) $3, lexer.Location);
3291           }
3292         | multiplicative_expression DIV prefixed_unary_expression
3293           {
3294                 $$ = new Binary (Binary.Operator.Division,
3295                                  (Expression) $1, (Expression) $3, lexer.Location);
3296           }
3297         | multiplicative_expression OP_IDIV prefixed_unary_expression
3298           {
3299                 $$ = new Binary (Binary.Operator.Division,
3300                                  (Expression) $1, (Expression) $3, lexer.Location);
3301           }       
3302         | multiplicative_expression MOD prefixed_unary_expression
3303           {
3304                 $$ = new Binary (Binary.Operator.Modulus,
3305                                  (Expression) $1, (Expression) $3, lexer.Location);
3306           }
3307         ;
3308
3309 additive_expression
3310         : multiplicative_expression
3311         | additive_expression PLUS multiplicative_expression
3312           {
3313                 $$ = new Binary (Binary.Operator.Addition,
3314                                  (Expression) $1, (Expression) $3, lexer.Location);
3315           }
3316         | additive_expression MINUS multiplicative_expression
3317           {
3318                 $$ = new Binary (Binary.Operator.Subtraction,
3319                                  (Expression) $1, (Expression) $3, lexer.Location);
3320           }
3321         | additive_expression OP_CONCAT multiplicative_expression
3322           {
3323                 // FIXME: This should only work for String expressions
3324                 // We probably need to use something from the runtime
3325                 $$ = new Binary (Binary.Operator.Addition,
3326                                  (Expression) $1, (Expression) $3, lexer.Location);
3327           }       
3328         ;
3329
3330 relational_expression
3331         : additive_expression
3332         | relational_expression OP_LT additive_expression
3333           {
3334                 $$ = new Binary (Binary.Operator.LessThan,
3335                                  (Expression) $1, (Expression) $3, lexer.Location);
3336           }
3337         | relational_expression OP_GT additive_expression
3338           {
3339                 $$ = new Binary (Binary.Operator.GreaterThan,
3340                                  (Expression) $1, (Expression) $3, lexer.Location);
3341           }
3342         | relational_expression OP_LE additive_expression
3343           {
3344                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
3345                                  (Expression) $1, (Expression) $3, lexer.Location);
3346           }
3347         | relational_expression OP_GE additive_expression
3348           {
3349                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
3350                                  (Expression) $1, (Expression) $3, lexer.Location);
3351           }
3352         | relational_expression IS unary_expression
3353           {
3354                 $$ = new Binary (Binary.Operator.Equality,
3355                         (Expression) $1, (Expression) $3, lexer.Location);
3356           }
3357         | relational_expression AS type_name
3358           {
3359                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
3360           }
3361         ;
3362
3363 equality_expression
3364         : relational_expression
3365         | equality_expression ASSIGN relational_expression
3366           {
3367                 $$ = new Binary (Binary.Operator.Equality,
3368                                  (Expression) $1, (Expression) $3, lexer.Location);
3369           }
3370         | equality_expression OP_NE relational_expression
3371           {
3372                 $$ = new Binary (Binary.Operator.Inequality, 
3373                                  (Expression) $1, (Expression) $3, lexer.Location);
3374           }       
3375         ;
3376
3377 and_expression
3378         : equality_expression
3379         | and_expression AND equality_expression
3380           {
3381                 $$ = new Binary (Binary.Operator.BitwiseAnd,
3382                                  (Expression) $1, (Expression) $3, lexer.Location);
3383           }
3384         ;
3385
3386 exclusive_or_expression
3387         : and_expression
3388         | exclusive_or_expression OP_XOR and_expression
3389           {
3390                 $$ = new Binary (Binary.Operator.ExclusiveOr,
3391                                  (Expression) $1, (Expression) $3, lexer.Location);
3392           }
3393         ;
3394
3395 conditional_and_expression
3396         : exclusive_or_expression
3397         | conditional_and_expression AND exclusive_or_expression
3398           {
3399                 $$ = new Binary (Binary.Operator.LogicalAnd,
3400                                  (Expression) $1, (Expression) $3, lexer.Location);
3401           }
3402         | conditional_and_expression ANDALSO exclusive_or_expression
3403           {     // FIXME: this is likely to be broken
3404                 $$ = new Binary (Binary.Operator.LogicalAnd,
3405                                  (Expression) $1, (Expression) $3, lexer.Location);
3406           }
3407         ;
3408
3409 conditional_or_expression
3410         : conditional_and_expression
3411         | conditional_or_expression OR conditional_and_expression
3412           {
3413                 $$ = new Binary (Binary.Operator.LogicalOr,
3414                                  (Expression) $1, (Expression) $3, lexer.Location);
3415           }
3416         | conditional_or_expression ORELSE conditional_and_expression
3417           {     // FIXME: this is likely to be broken
3418                 $$ = new Binary (Binary.Operator.LogicalOr,
3419                                  (Expression) $1, (Expression) $3, lexer.Location);
3420           }
3421         ;
3422
3423 conditional_expression
3424         : conditional_or_expression
3425         ;
3426
3427 assignment_expression
3428         : prefixed_unary_expression ASSIGN expression
3429           { 
3430                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3431           }
3432         | prefixed_unary_expression OP_MULT_ASSIGN expression
3433           {
3434                 Location l = lexer.Location;
3435
3436                 $$ = new CompoundAssign (
3437                         Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
3438           }
3439         | prefixed_unary_expression OP_DIV_ASSIGN expression
3440           {
3441                 Location l = lexer.Location;
3442
3443                 $$ = new CompoundAssign (
3444                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3445           }
3446         | prefixed_unary_expression OP_IDIV_ASSIGN expression
3447           {
3448                 Location l = lexer.Location;
3449
3450                 $$ = new CompoundAssign (
3451                         Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3452           }       
3453         | prefixed_unary_expression OP_ADD_ASSIGN expression
3454           {
3455                 Location l = lexer.Location;
3456
3457                 $$ = new CompoundAssign (
3458                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3459           }
3460         | prefixed_unary_expression OP_SUB_ASSIGN expression
3461           {
3462                 Location l = lexer.Location;
3463
3464                 $$ = new CompoundAssign (
3465                         Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
3466           }
3467         | prefixed_unary_expression OP_CONCAT_ASSIGN expression
3468           {
3469                 Location l = lexer.Location;
3470
3471                 $$ = new CompoundAssign (
3472                         Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3473           }               
3474         ;
3475
3476 constant_expression
3477         : expression
3478         ;
3479
3480 boolean_expression
3481         : expression
3482         ;
3483
3484 type
3485         : type_name {   /* class_type */
3486                 /*
3487                    This does interfaces, delegates, struct_types, class_types,
3488                    parent classes, and more! 4.2
3489                  */
3490                 $$ = DecomposeQI ((string) $1, lexer.Location); 
3491           }
3492         | builtin_types 
3493         /*| array_type 
3494          | pointer_type */
3495         ;
3496
3497 type_list
3498         : type
3499           {
3500                 ArrayList types = new ArrayList ();
3501
3502                 types.Add ($1);
3503                 $$ = types;
3504           }
3505         | type_list COMMA type
3506           {
3507                 ArrayList types = (ArrayList) $1;
3508
3509                 types.Add ($3);
3510                 $$ = types;
3511           }
3512         ;
3513
3514 type_name
3515         : namespace_or_type_name
3516         ;
3517         
3518 namespace_or_type_name
3519         : qualified_identifier
3520         ;
3521
3522 array_type
3523         : type bracketed_rank_specifiers
3524           {
3525                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3526           }
3527         ;
3528         
3529 bracketed_rank_specifiers
3530         : bracketed_rank_specifier bracketed_opt_rank_specifier
3531           {
3532                   $$ = (string) $2 + (string) $1;
3533           }
3534         ;
3535
3536 bracketed_rank_specifier
3537         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
3538           {
3539                 $$ = "[" + (string) $2 + "]";
3540           }
3541         ;
3542
3543 bracketed_opt_rank_specifier
3544         : /* empty */
3545           {
3546                   $$ = "";
3547           }
3548         | bracketed_rank_specifiers
3549           {
3550                 $$ = $1;
3551           }
3552         ;               
3553
3554 /* Built-in / Integral types */
3555 builtin_types
3556         : OBJECT        { $$ = TypeManager.system_object_expr; }
3557         | STRING        { $$ = TypeManager.system_string_expr; }
3558         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
3559         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
3560         | SINGLE        { $$ = TypeManager.system_single_expr; }
3561         | DOUBLE        { $$ = TypeManager.system_double_expr; }
3562         | integral_type
3563         ;
3564
3565 integral_type
3566         : 
3567         | BYTE          { $$ = TypeManager.system_byte_expr; }
3568         | SHORT         { $$ = TypeManager.system_int16_expr; }
3569         | LONG          { $$ = TypeManager.system_int64_expr; }
3570         | INTEGER       { $$ = TypeManager.system_int32_expr; }
3571         | CHAR          { $$ = TypeManager.system_char_expr; }
3572 /*
3573         | SBYTE         { $$ = TypeManager.system_sbyte_expr; }
3574         | UINT          { $$ = TypeManager.system_uint32_expr; }
3575         | ULONG         { $$ = TypeManager.system_uint64_expr; }
3576         | USHORT        { $$ = TypeManager.system_uint16_expr; }
3577         | CHAR          { $$ = TypeManager.system_char_expr; }
3578         | VOID          { $$ = TypeManager.system_void_expr; }
3579 */
3580         ;
3581
3582 interface_type
3583         : type_name
3584         ;
3585         
3586 end_of_stmt
3587         : EOL
3588         | COLON
3589         ;       
3590 %%
3591
3592
3593 Tokenizer lexer;
3594
3595 public Tokenizer Lexer {
3596         get {
3597                 return lexer;
3598         }
3599 }                  
3600
3601 public static Expression DecomposeQI (string name, Location loc)
3602 {
3603         Expression o;
3604
3605         if (name.IndexOf ('.') == -1){
3606                 return new SimpleName (name, loc);
3607         } else {
3608                 int pos = name.LastIndexOf (".");
3609                 string left = name.Substring (0, pos);
3610                 string right = name.Substring (pos + 1);
3611
3612                 o = DecomposeQI (left, loc);
3613
3614                 return new MemberAccess (o, right, loc);
3615         }
3616 }
3617
3618 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3619 {
3620         Block implicit_block;
3621         ArrayList inits = null;
3622
3623         //
3624         // We use the `Used' property to check whether statements
3625         // have been added to the current block.  If so, we need
3626         // to create another block to contain the new declaration
3627         // otherwise, as an optimization, we use the same block to
3628         // add the declaration.
3629         //
3630         // FIXME: A further optimization is to check if the statements
3631         // that were added were added as part of the initialization
3632         // below.  In which case, no other statements have been executed
3633         // and we might be able to reduce the number of blocks for
3634         // situations like this:
3635         //
3636         // int j = 1;  int k = j + 1;
3637         //
3638         
3639         VariableDeclaration.FixupTypes (variable_declarators);
3640         
3641         if (current_block.Used) {
3642                 implicit_block = new Block (current_block, true, loc, Location.Null);
3643                 implicit_block.AddChildVariableNames (current_block);
3644         } else
3645                 implicit_block = current_block;
3646
3647         foreach (VariableDeclaration decl in variable_declarators){
3648                 Expression type = decl.type;
3649                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3650                         if (decl.expression_or_array_initializer != null){
3651                                 if (inits == null)
3652                                         inits = new ArrayList ();
3653                                 inits.Add (decl);
3654                         }
3655                 }
3656         }
3657
3658         if (inits == null)
3659                 return implicit_block;
3660
3661         foreach (VariableDeclaration decl in inits){
3662                 Assign assign;
3663                 Expression expr;
3664                 Expression type = decl.type;
3665                 
3666                 if ((decl.expression_or_array_initializer is Expression) || 
3667                     (decl.expression_or_array_initializer is New)) {
3668                         expr = (Expression) decl.expression_or_array_initializer;
3669                 } else {
3670                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3671                         
3672                         expr = new ArrayCreation (type, "", init, decl.Location);
3673                 }
3674
3675                 LocalVariableReference var;
3676                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3677
3678                 assign = new Assign (var, expr, decl.Location);
3679
3680                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3681         }
3682         
3683         return implicit_block;
3684 }
3685
3686
3687 Block declare_local_constant (Expression type, VariableDeclaration decl)
3688 {
3689         Block implicit_block;
3690
3691         if (current_block.Used)
3692                 implicit_block = new Block (current_block, true);
3693         else
3694                 implicit_block = current_block;
3695
3696         if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3697                                           current_local_parameters, decl.Location))){
3698         }
3699         
3700         return implicit_block;
3701 }
3702
3703 // <summary>
3704 //   A class used to pass around variable declarations and constants
3705 // </summary>
3706 public class VariableDeclaration {
3707         public string identifier;
3708         public object expression_or_array_initializer;
3709         public Location Location;
3710         public Attributes OptAttributes;
3711         public Expression type;
3712         public ArrayList dims;
3713                 
3714         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
3715         {
3716                 this.identifier = id;
3717                 this.expression_or_array_initializer = eoai;
3718                 this.Location = l;
3719                 this.OptAttributes = opt_attrs;
3720                 this.type = t;
3721                 this.dims = null;
3722         }       
3723
3724         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3725         {
3726         }
3727         
3728         public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
3729         {
3730         }       
3731         
3732         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
3733                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
3734         {
3735         }       
3736         
3737         public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
3738         {       
3739                 // FIXME : This is broken: only the first rank is parsed
3740                 return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
3741         }
3742         
3743         public static void FixupTypes (ArrayList vars)
3744         {
3745                 int varcount =  vars.Count;
3746                 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
3747                         
3748                 if (last_var.type == null)
3749                         last_var.type = TypeManager.system_object_expr;
3750                         
3751                 Expression cur_type = last_var.type;
3752                 int n = varcount - 1;
3753                 
3754                 while (n >= 0) {
3755                         VariableDeclaration var = (VariableDeclaration) vars[n--];
3756                         if (var.type == null)
3757                                 var.type = cur_type;
3758                         else
3759                                 cur_type = var.type;
3760                 }
3761         }
3762         
3763         public static bool IndexesSpecified (Parser t)
3764         {
3765                 bool res = false;
3766                 ArrayList ranks = t.current_rank_specifiers;
3767                 
3768                 if (ranks != null) {
3769                         foreach (ArrayList IndexList in ranks) {
3770                                 foreach (Expression e in IndexList)
3771                                         if (!(e is EmptyExpression)) {
3772                                                 res = true;
3773                                                 break;
3774                                         }
3775                         }       
3776                 }
3777                 return (res);
3778         }
3779         
3780         public static string StripDims (string varname, ref string d)
3781         {
3782                 string res = varname;
3783                 string dres = "";
3784                 
3785                 if (varname.IndexOf("[") >= 0) {
3786                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3787                         res = varname.Substring(0, varname.IndexOf("["));
3788                 }
3789                 d = dres;
3790                 return (res);
3791         }       
3792         
3793         public static string StripDims (string varname)
3794         {
3795                 string dres = "";
3796                 
3797                 return (StripDims(varname, ref dres));
3798         }       
3799         
3800         public static string StripIndexesFromDims (string dims)
3801         {
3802                 StringBuilder sb = new StringBuilder();
3803                 //  
3804                 foreach (char c in dims) 
3805                         if (c == ',' || c == ']' || c == '[')
3806                                 sb.Append (c);
3807                                 
3808                 return sb.ToString();                           
3809         }
3810         
3811         public static string BuildRank (ArrayList rank)
3812         {
3813                 string res = "";
3814
3815                 res += "[";
3816                 for (int x = 0; x < (rank.Count -1 ); x++)
3817                         res += ",";
3818                         
3819                 res += "]";
3820                 return res;
3821         }
3822                 
3823         public static string BuildRanks (Parser t)
3824         {
3825                 string res = "";
3826
3827                 foreach (ArrayList rank in t.current_rank_specifiers)
3828                         res += BuildRank (rank);
3829
3830                 return res;
3831         }       
3832         
3833         public static bool HasExplicitIndexes (ArrayList a)
3834         {
3835                 bool res = false;
3836                 
3837                 if (a != null) {
3838                         foreach (Expression e in a) 
3839                                 if (!(e is EmptyExpression)) {
3840                                         res = true;
3841                                         break;
3842                                 }
3843                 }                       
3844                 return res;                     
3845         }
3846         
3847         public static ArrayList ParseIndexList (Parser t)
3848         {
3849                 ArrayList res = new ArrayList();
3850                 //string d = dims.Substring (1, dims.Length -2);
3851                 //Array a = d.Split (',');
3852                 
3853                 return t.current_rank_specifiers;
3854                 /*
3855                 if (a.GetLength(0) > 32) {
3856                         Report.Error (999, "Arrays cannot have more than 32 dimensions");
3857                 }
3858                 
3859                 foreach (string s in a) 
3860                         if (s != "")
3861                                 res.Add (new IntLiteral ((Int32) Convert.ToInt32(s) + 1));
3862                         else
3863                                 res.Add (new IntLiteral ((Int32) 0));
3864                 
3865                 return (res);*/
3866         }               
3867         
3868         public static bool IsArrayDecl (Parser t)
3869         {
3870                 // return (varname.IndexOf("[") >= 0);
3871                 return (t.current_rank_specifiers != null);
3872         }                       
3873         
3874         public static void FixupArrayTypes (ArrayList vars)
3875         {
3876                 int varcount =  vars.Count;
3877                 string dims;
3878                 
3879                 foreach (VariableDeclaration var in vars) {
3880                         if (var.identifier.EndsWith(",")) {
3881                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
3882                                                                 var.identifier.LastIndexOf(",")) + "]";
3883                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
3884                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
3885                         }
3886                 }
3887         }                               
3888 }
3889
3890 public Property BuildSimpleProperty (Expression p_type, string name, 
3891                                         Field p_fld, int mod_flags,
3892                                         Attributes attrs, Location loc) 
3893 {
3894         Property p;
3895         Block get_block, set_block;
3896         Accessor acc_set, acc_get;
3897         StatementExpression a_set;
3898         Statement a_get;
3899         Parameter [] args;
3900         
3901         // Build SET Block
3902         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
3903         args  = new Parameter [1];
3904         args [0] = implicit_value_parameter;
3905                 
3906         Parameters set_params = new Parameters (args, null, loc);
3907         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
3908                             (Expression) new SimpleName("value", loc), loc), loc);
3909                             
3910         set_block = new Block (current_block, set_params, loc, Location.Null);
3911         set_block.AddStatement ((Statement) a_set);                                         
3912         acc_set = new Accessor (set_block, attrs);
3913         
3914         // Build GET Block
3915         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
3916         get_block = new Block (current_block, null, loc, Location.Null);
3917         get_block.AddStatement ((Statement) a_get);                                         
3918         acc_get = new Accessor (get_block, attrs);
3919                 
3920         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
3921         
3922         return (p);
3923 }
3924                 
3925 void start_block () 
3926 {
3927         current_block = new Block (current_block, current_local_parameters,
3928                            lexer.Location, Location.Null);
3929
3930
3931 Block end_block ()
3932
3933         Block res;
3934         
3935         while (current_block.Implicit)
3936                 current_block = current_block.Parent;
3937
3938         res = current_block;
3939
3940         current_block.SetEndLocation (lexer.Location);
3941         current_block = current_block.Parent;
3942         
3943         return (res);
3944 }
3945
3946 private void AddHandler (Expression evt_definition, string handler_name)
3947 {
3948         AddHandler (current_block, evt_definition, handler_name);
3949 }
3950
3951 void CheckAttributeTarget (string a)
3952 {
3953         switch (a) {
3954
3955         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3956                 return;
3957                 
3958         default :
3959                 Location l = lexer.Location;
3960                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3961                 break;
3962         }
3963 }
3964
3965 private void AddHandler (Block b, Expression evt_id, string handler_name)
3966 {
3967         Location loc = lexer.Location;
3968         string evt_target = evt_id.ToString();
3969         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
3970         Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
3971         b.AddStatement (s);
3972 }
3973
3974 private void RaiseEvent (string evt_name, ArrayList args)
3975 {
3976         Location loc = lexer.Location;
3977         
3978         Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
3979         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); 
3980         current_block.AddStatement (s); 
3981 }
3982
3983 // FIXME: THIS DOES NOT WORK!!!
3984 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
3985 {
3986         Location loc = lexer.Location;
3987         ArrayList neh_args = new ArrayList();
3988         neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
3989         
3990         ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
3991         
3992         CompoundAssign ca = new CompoundAssign (
3993                         Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
3994                         
3995         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
3996         b.AddStatement (s);     
3997 }
3998
3999 // <summary>
4000 //  This method is used to get at the complete string representation of
4001 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
4002 //  This is necessary because local_variable_type admits primary_expression
4003 //  as the type of the variable. So we do some extra checking
4004 // </summary>
4005 string GetQualifiedIdentifier (Expression expr)
4006 {
4007         if (expr is SimpleName)
4008                 return ((SimpleName)expr).Name;
4009         else if (expr is MemberAccess)
4010                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4011         else 
4012                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4013         
4014 }
4015
4016 private void RemoveHandler (Expression evt_definition, string handler_name)
4017 {
4018         RemoveHandler (current_block, evt_definition, handler_name);
4019 }
4020
4021 private ConstructorInitializer FixConstructorInitializer (ref ArrayList s)
4022 {
4023         ConstructorInitializer ci = null;
4024         
4025         if (s.Count > 0) {
4026                 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4027                         Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4028                         
4029                         if (i.expr is BaseAccess) {
4030                                 BaseAccess ba = (BaseAccess) i.expr;
4031                                 if (ba.member == "New" || ba.member == ".ctor") {
4032                                         ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4033                                         s.Remove(0);
4034                                 }
4035                         }
4036                         if (i.expr.ToString() == "Mono.CSharp.This..ctor") {
4037                                 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location); 
4038                                 s.Remove(0);
4039                         }
4040                 }
4041         }
4042         return ci;
4043 }
4044
4045 void Error_ExpectingTypeName (Location l, Expression expr)
4046 {
4047         if (expr is Invocation){
4048                 Report.Error (1002, l, "; expected");
4049         } else {
4050                 Report.Error (-1, l, "Invalid Type definition");
4051         }
4052 }
4053
4054 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4055         return true;
4056 }
4057
4058 private void ReportError9998()
4059 {
4060         Report.Error (9998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4061 }
4062
4063 public override int parse ()
4064 {
4065         current_namespace = new Namespace (null, RootContext.RootNamespace);
4066         current_container = RootContext.Tree.Types;
4067         current_container.Namespace = current_namespace;
4068         oob_stack = new Stack ();
4069         switch_stack = new Stack ();
4070         expr_stack = new Stack ();      
4071         tmp_blocks = new Stack(); 
4072         statement_stack = new Stack();  
4073         
4074         UseExtendedSyntax = name.EndsWith(".mbs");
4075         OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4076         OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4077         OptionCompareBinary = InitialOptionCompareBinary;
4078
4079         lexer = new Tokenizer (input, name, defines);
4080         StringBuilder value = new StringBuilder ();
4081         //yacc_verbose_flag=true;
4082         try 
4083         {
4084                 if (yacc_verbose_flag)
4085                         yyparse (lexer, new yydebug.yyDebugSimple ());
4086                 else
4087                         yyparse (lexer);
4088         } 
4089         catch (Exception e)
4090         {
4091                 Console.WriteLine (lexer.location + "  : Parsing error in " + lexer.ref_name);
4092                 Report.Error (9999, lexer.Location, "\n");
4093                 //Console.WriteLine (e);
4094         }
4095         
4096         return Report.Errors;
4097 }
4098
4099 /* end end end */
4100 }