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