2003-03-17 Joel Basson <jstrike@mweb.co.za>
[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         ;
842
843 module_declaration
844         : MODULE identifier EOL
845           { 
846                 Module new_module;
847                 string name;
848                 name = MakeName((string) $2);
849                 new_module = new Module(current_container, 
850                                                                 name, 
851                                                                 current_modifiers, // already checks then
852                                                                 (Attributes) current_attributes,
853                                                                 lexer.Location);
854                 current_container = new_module;
855                 current_container.Namespace = current_namespace;
856                 RootContext.Tree.RecordDecl(name, new_module);
857           }
858           opt_class_member_declarations
859           END MODULE EOL
860           {
861                 Module new_module = (Module)current_container;
862
863                 current_container = current_container.Parent;
864                 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
865
866                 $$ = new_module;
867           }
868         ;
869
870 opt_module_member_declarations
871         : /* empty */
872         | module_member_declarations
873         ;
874
875 module_member_declarations
876         : module_member_declaration
877         | module_member_declarations module_member_declaration
878         ;
879
880 module_member_declaration
881         :  opt_attributes
882            opt_modifiers
883            { 
884                 current_attributes = (Attributes) $1;
885                 current_modifiers = (int) $2 | (int)Modifiers.STATIC; // FIXME: for type_declaration it can result in trouble
886            }
887            module_member_declarator
888            {
889                 $$ = $3;
890            }
891         ;
892
893 module_member_declarator
894         :  static_constructor_declaration
895         |  method_declaration
896            { 
897                 Method method = (Method) $1;
898                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
899            }    
900         |  field_declaration
901         |  withevents_declaration       /* This is a field but must be treated specially, see below */
902         |  constant_declaration
903         |  property_declaration                 
904         |  event_declaration    
905         |  type_declaration                     
906         ;
907         
908 constant_declaration // TODO: implement truly the logic
909         : CONST identifier ASSIGN constant_expression
910         | CONST identifier AS qualified_identifier ASSIGN constant_expression
911         ;
912            
913 opt_class_member_declarations
914         : /* empty */
915         | class_member_declarations
916         ;
917
918 class_member_declarations
919         : class_member_declaration
920         | class_member_declarations class_member_declaration
921         ;
922
923 class_member_declaration
924         :  opt_attributes
925            opt_modifiers
926            { 
927                 current_attributes = (Attributes) $1;
928                 current_modifiers = (int) $2; 
929            }
930            class_member_declarator
931            {
932                 $$ = $3;
933            }
934         ;
935
936 class_member_declarator
937         :  constructor_declaration
938         |  method_declaration
939            { 
940                 Method method = (Method) $1;
941                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
942            }    
943         |  field_declaration
944         |  constant_declaration
945         |  property_declaration                 
946         |  event_declaration    
947         |  withevents_declaration       /* This is a field but must be treated specially, see below */
948         |  type_declaration                     
949         ;
950         
951         
952 method_declaration
953         : sub_declaration
954         | func_declaration 
955         ;
956         
957 sub_declaration
958         : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
959           { 
960                 
961                 current_local_parameters = (Parameters) $4;
962                 start_block(); 
963
964                 /* This is WEIRD: declaring a method (sub) in a module as static will
965                    trigger a syntax error, but the same methods MUST be static in order
966                    to be properly called
967                 */
968                 if (current_container is Module) {
969                         if (current_modifiers == Modifiers.STATIC) {
970                                 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
971                         }
972                         else
973                         {
974                                 current_modifiers = Modifiers.STATIC;
975                         }
976                 }
977                 
978                 // Structure members are Public by default                      
979                 if ((current_container is Struct) && (current_modifiers == 0))
980                         current_modifiers = Modifiers.PUBLIC;                   
981           }
982           opt_statement_list 
983           END SUB EOL
984           {
985                 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
986                                             (Parameters) current_local_parameters, null, (Expression) $7, 
987                                             lexer.Location);
988         
989                 method.Block = (Block) end_block();
990                 $$ = method;
991
992                 if ($6 != null) { /* we have an event handler to take care of */
993                         // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
994                         string evt_def = ((MemberAccess)$6).ToString();
995                         int pos = evt_def.LastIndexOf (".");
996                         string evt_target = ((string) $2).Substring (0, pos);
997
998                         foreach (Property p in current_container.Properties) {
999                                 if (p.Name == evt_target) {
1000                                         // FIXME: See below 
1001                                         // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
1002                                         AddHandler (p.Set.Block, (Expression)$6, (string) $2);
1003                                         break;
1004                                 }
1005                         }                               
1006                 }       
1007           }       
1008         ;
1009         
1010 func_declaration
1011         : FUNCTION identifier 
1012           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type opt_implement_clause EOL
1013           { 
1014                 
1015                 current_local_parameters = (Parameters) $4;
1016                 start_block(); 
1017         
1018                 /* This is WEIRD: declaring a method (sub) in a module as static will
1019                    trigger a syntax error, but the same methods MUST be static in order
1020                    to be properly called
1021                 */
1022                 if (current_container is Module) {
1023                         if (current_modifiers == Modifiers.STATIC) {
1024                                 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1025                         }
1026                         else
1027                         {
1028                                 current_modifiers = Modifiers.STATIC;
1029                         }                       
1030                 }
1031                 
1032                 // Structure members are Public by default                      
1033                 if ((current_container is Struct) && (current_modifiers == 0))
1034                         current_modifiers = Modifiers.PUBLIC;                           
1035                 // Add local var declaration
1036                 // for return value
1037                 ArrayList retval = new ArrayList ();
1038                 retval.Add (new VariableDeclaration ((string) $2, (Expression) $7, lexer.Location));
1039                 declare_local_variables ((Expression) $7, retval, lexer.Location);
1040           }       
1041           opt_statement_list
1042           END FUNCTION EOL
1043           {
1044                 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
1045                                             (Parameters) current_local_parameters, null, 
1046                                             (Expression) $7, lexer.Location);
1047         
1048                 method.Block = end_block();
1049                 $$ = method;
1050
1051           }       
1052         ;               
1053
1054 struct_declaration
1055         : STRUCTURE identifier EOL
1056           opt_implement_clause
1057           {
1058                 Struct new_struct;
1059                 string full_struct_name = MakeName ((string) $2);
1060
1061                 new_struct = new Struct (current_container, full_struct_name, 
1062                                          (int) current_modifiers,
1063                                          (Attributes) current_attributes, lexer.Location);
1064                 current_container = new_struct;
1065                 current_container.Namespace = current_namespace;
1066                 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1067           }
1068           opt_struct_member_declarations
1069           {
1070                 Struct new_struct = (Struct) current_container;
1071
1072                 if ($4 != null)
1073                         new_struct.Bases = (ArrayList) $4;
1074
1075                 current_container = current_container.Parent;
1076                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1077                 $$ = new_struct;
1078           }
1079           END STRUCTURE EOL
1080         ;
1081         
1082 opt_struct_member_declarations
1083         : /* empty */
1084         | struct_member_declarations
1085         ;
1086
1087 struct_member_declarations
1088         : struct_member_declaration
1089         | struct_member_declarations struct_member_declaration
1090         ;
1091
1092 struct_member_declaration
1093         : opt_modifiers
1094           struct_member_declarator
1095         ;
1096 struct_member_declarator        
1097         : field_declaration
1098         //| constant_declaration
1099         | method_declaration
1100         | property_declaration
1101         | event_declaration
1102         | constructor_declaration
1103         | type_declaration
1104
1105         /*
1106          * This is only included so we can flag error 575:
1107          * destructors only allowed on class types
1108          */
1109         //| destructor_declaration
1110         ;
1111         
1112 event_declaration
1113         : EVENT identifier AS type EOL
1114           {
1115                 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1116
1117                 Event e = new Event ((Expression) $4, var.identifier, 
1118                                      null, current_modifiers, null, null, 
1119                                      current_attributes, lexer.Location);
1120
1121                 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1122
1123           }
1124 //      | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1125 //        {
1126 //              throw new NotSupportedException();
1127 //        }
1128         ;       
1129
1130 enum_declaration
1131         : ENUM identifier opt_type_spec EOL
1132           opt_enum_member_declarations
1133           { 
1134                 Location enum_location = lexer.Location;
1135
1136                 string full_name = MakeName ((string) $2);
1137                 Mono.CSharp.Enum e = new Mono.CSharp.Enum (current_container, (Expression) $3, (int) current_modifiers, full_name, 
1138                                    (Attributes) current_attributes, enum_location);
1139                 
1140                 foreach (VariableDeclaration ev in (ArrayList) $5) {
1141                         Location loc = (Location) ev.Location;
1142
1143                         CheckDef (e.AddEnumMember (ev.identifier, 
1144                                                    (Expression) ev.expression_or_array_initializer,
1145                                                    loc, ev.OptAttributes), ev.identifier, loc);
1146                 }
1147
1148                 e.Namespace = current_namespace;
1149
1150                 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1151                 RootContext.Tree.RecordDecl (full_name, e);
1152
1153           }
1154           END ENUM EOL
1155         ;
1156
1157 opt_enum_member_declarations
1158         : /* empty */                   { $$ = new ArrayList (); }
1159         | enum_member_declarations      { $$ = $1; }
1160         ;
1161
1162 enum_member_declarations
1163         : enum_member_declaration 
1164           {
1165                 ArrayList l = new ArrayList ();
1166
1167                 l.Add ($1);
1168                 $$ = l;
1169           }
1170         | enum_member_declarations  enum_member_declaration
1171           {
1172                 ArrayList l = (ArrayList) $1;
1173
1174                 l.Add ($2);
1175
1176                 $$ = l;
1177           }
1178         ;
1179
1180 enum_member_declaration
1181         : opt_attributes identifier EOL
1182           {
1183                 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1184           }
1185         | opt_attributes identifier
1186           {
1187                   $$ = lexer.Location;
1188           }
1189           ASSIGN expression EOL
1190           { 
1191                 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1192           }
1193         ;
1194                 
1195 interface_declaration
1196         : INTERFACE identifier EOL
1197           {
1198                 Interface new_interface;
1199                 string full_interface_name = MakeName ((string) $2);
1200
1201                 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1202                                                (Attributes) current_attributes, lexer.Location);
1203                 if (current_interface != null) {
1204                         Location l = lexer.Location;
1205                         Report.Error (-2, l, "Internal compiler error: interface inside interface");
1206                 }
1207                 current_interface = new_interface;
1208                 new_interface.Namespace = current_namespace;
1209                 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1210           }
1211           opt_interface_base
1212           interface_body
1213           { 
1214                 Interface new_interface = (Interface) current_interface;
1215
1216                 if ($5 != null)
1217                         new_interface.Bases = (ArrayList) $5;
1218
1219                 current_interface = null;
1220                 CheckDef (current_container.AddInterface (new_interface),
1221                           new_interface.Name, new_interface.Location);
1222
1223           }
1224           END INTERFACE EOL
1225         ;
1226
1227 opt_interface_base
1228         : /* empty */                     { $$ = null; }
1229         | interface_base
1230         ;
1231
1232 interface_base
1233         : INHERITS interface_type_list    { $$ = $2; }
1234         ;
1235
1236 interface_type_list
1237         : interface_type
1238           {
1239                 ArrayList interfaces = new ArrayList ();
1240
1241                 interfaces.Add ($1);
1242                 $$ = interfaces;
1243           }
1244         | interface_type_list COMMA interface_type
1245           {
1246                 ArrayList interfaces = (ArrayList) $1;
1247                 interfaces.Add ($3);
1248                 $$ = interfaces;
1249           }
1250         ;
1251
1252 interface_body
1253         : opt_interface_member_declarations
1254         ;
1255
1256 opt_interface_member_declarations
1257         : /* empty */
1258         | interface_member_declarations
1259         ;
1260
1261 interface_member_declarations
1262         : interface_member_declaration
1263         | interface_member_declarations interface_member_declaration
1264         ;
1265
1266 interface_member_declaration
1267         : interface_method_declaration          
1268           { 
1269                 InterfaceMethod m = (InterfaceMethod) $1;
1270
1271                 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1272           }
1273         | interface_property_declaration        
1274           { 
1275                 InterfaceProperty p = (InterfaceProperty) $1;
1276                 
1277                 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1278           }
1279         | interface_event_declaration 
1280           { 
1281                 InterfaceEvent e = (InterfaceEvent) $1;
1282
1283                 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1284           }
1285         ;
1286
1287 opt_new
1288         : /* empty */   { $$ = false; }
1289         | NEW           { $$ = true; }
1290         ;
1291         
1292 interface_method_declaration
1293         : SUB identifier
1294           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1295           {
1296                 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1297                                           (Parameters) $4, current_attributes, lexer.Location);
1298           }
1299         | FUNCTION identifier
1300           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1301           {
1302                 $$ = new InterfaceMethod (
1303                                           (Expression) $7, (string) $2, false, (Parameters) $4,
1304                                           current_attributes, lexer.Location);
1305           }
1306         ;
1307
1308 interface_property_declaration
1309         : PROPERTY identifier
1310           OPEN_PARENS
1311           opt_formal_parameter_list
1312           CLOSE_PARENS opt_type_spec EOL
1313           {
1314                 // FIXME we MUST pass property parameters
1315                 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1316                                             true, true, current_attributes,
1317                                             lexer.Location);
1318           }
1319         ;
1320
1321 interface_event_declaration
1322         : opt_attributes opt_new EVENT type identifier EOL
1323           {
1324                 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1325                                          lexer.Location);
1326           }
1327         ;
1328
1329 property_declaration
1330           : PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
1331           {
1332                 get_implicit_value_parameter_type = (Expression) $5;
1333                 get_implicit_value_parameter_name = (string) $2;
1334                 
1335                 current_local_parameters = (Parameters) $3;
1336                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
1337                         get_parameters = current_local_parameters.Copy (lexer.Location);
1338                         set_parameters = current_local_parameters.Copy (lexer.Location);
1339                 }
1340                 else
1341                 {
1342                         get_parameters = Parameters.EmptyReadOnlyParameters;
1343                         set_parameters = new Parameters (null, null ,lexer.Location);           
1344                 }
1345                 lexer.PropertyParsing = true;
1346
1347                 $$ = lexer.Location;
1348           }
1349           accessor_declarations 
1350           END PROPERTY EOL
1351           {
1352                 lexer.PropertyParsing = false;
1353
1354                 Property prop;
1355                 Pair pair = (Pair) $9;
1356                 Accessor get_block = (Accessor) pair.First;
1357                 Accessor set_block = (Accessor) pair.Second;
1358
1359                 Location loc = lexer.Location;
1360                 
1361                 // Structure members are Public by default                      
1362                 if ((current_container is Struct) && (current_modifiers == 0))
1363                         current_modifiers = Modifiers.PUBLIC;                           
1364                         
1365                 prop = new Property ((Expression) $5, (string) $2, current_modifiers, get_block, set_block,
1366                                      current_attributes, loc, set_implicit_value_parameter_name, 
1367                                      get_parameters, set_parameters, (Expression) $6);
1368                 
1369                 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1370                 get_implicit_value_parameter_type = null;
1371                 set_implicit_value_parameter_type = null;
1372                 get_parameters = null;
1373                 set_parameters = null;
1374                 current_local_parameters = null;
1375           }
1376         ;
1377
1378 opt_property_parameters
1379         : /* empty */
1380           {
1381                 $$ = Parameters.EmptyReadOnlyParameters;
1382           }
1383         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1384           {
1385                 $$ = $2;
1386           }
1387         ;
1388         
1389 opt_implement_clause
1390         : /* empty */
1391           {
1392                 $$ = null;
1393           }
1394         | IMPLEMENTS qualified_identifier
1395           {
1396                 $$ = DecomposeQI ((string)$2, lexer.Location);
1397           }     
1398         ;
1399         
1400 accessor_declarations
1401         : get_accessor_declaration opt_set_accessor_declaration
1402           { 
1403                 $$ = new Pair ($1, $2);
1404           }
1405         | set_accessor_declaration opt_get_accessor_declaration
1406           {
1407                 $$ = new Pair ($2, $1);
1408           }
1409         ;
1410
1411 opt_get_accessor_declaration
1412         : /* empty */                   { $$ = null; }
1413         | get_accessor_declaration
1414         ;
1415
1416 opt_set_accessor_declaration
1417         : /* empty */                   { $$ = null; }
1418         | set_accessor_declaration
1419         ;
1420
1421 get_accessor_declaration
1422         : opt_attributes GET EOL
1423           {
1424                 current_local_parameters = get_parameters;
1425                 
1426                 lexer.PropertyParsing = false;
1427                 
1428                 start_block();  
1429                 // Add local var declaration
1430                 // for return value
1431                 ArrayList retval = new ArrayList ();
1432                 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1433                 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);    
1434                 
1435           }
1436           opt_statement_list
1437           END GET EOL
1438           {
1439                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1440                 current_local_parameters = null;
1441                 lexer.PropertyParsing = true;
1442           }
1443         ;
1444
1445 set_accessor_declaration
1446         : opt_attributes SET opt_set_parameter EOL
1447           {
1448                 Parameter implicit_value_parameter = new Parameter (
1449                         set_implicit_value_parameter_type, 
1450                         set_implicit_value_parameter_name, 
1451                         Parameter.Modifier.NONE, null);
1452
1453                 current_local_parameters = set_parameters;
1454                 current_local_parameters.AppendParameter (implicit_value_parameter);
1455                 
1456                 start_block();
1457                 lexer.PropertyParsing = false;
1458           }
1459           opt_statement_list
1460           END SET EOL
1461           {
1462                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1463                 current_local_parameters = null;
1464                 lexer.PropertyParsing = true;
1465           }
1466         ;
1467                 
1468 opt_set_parameter
1469         : /* empty */
1470         {
1471                 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
1472                 set_implicit_value_parameter_name = "Value";
1473         }       
1474         | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
1475         {
1476                 /* FIXME: possible syntax error which must be caught
1477                    Set ( As <type>) is currently (and wrongly so) legal
1478                 */
1479                 set_implicit_value_parameter_type = (Expression) $3;
1480                 if ($2 != null)
1481                         set_implicit_value_parameter_name = (string) $2;
1482                 else
1483                         set_implicit_value_parameter_name = "Value";
1484         }
1485         ;
1486                         
1487 field_declaration
1488         : opt_dim_stmt 
1489           variable_declarators EOL
1490           {               
1491                 int mod = (int) current_modifiers;
1492                 
1493
1494                 VariableDeclaration.FixupTypes ((ArrayList) $2);
1495                 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1496                 
1497                 if (current_container is Module)
1498                         mod = mod | Modifiers.STATIC;
1499                         
1500                 // Structure members are Public by default                      
1501                 if ((current_container is Struct) && (mod == 0))
1502                         mod = Modifiers.PUBLIC;                 
1503                                         
1504                 foreach (VariableDeclaration var in (ArrayList) $2){
1505                         Location l = var.Location;
1506
1507                         Field field = new Field (var.type, mod, var.identifier, 
1508                                                  var.expression_or_array_initializer, 
1509                                                  (Attributes) null, l);
1510
1511                         CheckDef (current_container.AddField (field), field.Name, l);
1512                 }
1513           }
1514         ;
1515         
1516 withevents_declaration
1517         : WITHEVENTS variable_declarators EOL
1518           {
1519                 /* WithEvents Fields must be resolved into properties
1520                    with a bit of magic behind the scenes */
1521                   
1522                 VariableDeclaration.FixupTypes ((ArrayList) $2);
1523                 
1524                 foreach (VariableDeclaration var in (ArrayList) $2) {
1525                         // 1 - We create a private field
1526                         Location l = var.Location;
1527                         Property prop;
1528                         if ((current_modifiers & Modifiers.STATIC) > 0) 
1529                                 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1530                         
1531                         Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, 
1532                                                  var.expression_or_array_initializer, 
1533                                                  (Attributes) null, l);
1534
1535                         CheckDef (current_container.AddField (field), field.Name, l);   
1536                         
1537                         // 2 - Public property
1538                                 
1539                         prop = BuildSimpleProperty (var.type, (string) var.identifier, 
1540                                                 field, (int) current_modifiers, 
1541                                                 (Attributes) current_attributes, l);
1542                         
1543                         CheckDef (current_container.AddProperty (prop), prop.Name, l);
1544                 }               
1545           }
1546         ;
1547         
1548 opt_dim_stmt 
1549         : /* empty */
1550         | DIM
1551         ; 
1552                 
1553 delegate_declaration
1554         : DELEGATE SUB  
1555           identifier OPEN_PARENS 
1556           opt_formal_parameter_list
1557           CLOSE_PARENS 
1558           EOL
1559           {
1560                 Location l = lexer.Location;
1561                 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr, 
1562                                              (int) current_modifiers, 
1563                                              MakeName ((string) $3), (Parameters) $5, 
1564                                              (Attributes) current_attributes, l);
1565                                                   
1566                 del.Namespace = current_namespace;
1567                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1568           }     
1569         | DELEGATE FUNCTION       
1570           identifier OPEN_PARENS 
1571           opt_formal_parameter_list
1572           CLOSE_PARENS AS type
1573           {
1574                 Location l = lexer.Location;
1575                 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
1576                         current_container,
1577                         (Expression) $8, (int) current_modifiers, MakeName ((string) $3), 
1578                         (Parameters) $5, (Attributes) current_attributes, l);
1579
1580                 del.Namespace = current_namespace;
1581                 CheckDef (current_container.AddDelegate (del), del.Name, l);
1582           }
1583         ;
1584         
1585 opt_evt_handler
1586         : /* empty */
1587         {       $$ = null; }
1588         | HANDLES qualified_identifier
1589         {
1590                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
1591         }
1592         ;       
1593
1594 opt_empty_parens
1595         : /* empty */
1596         | OPEN_PARENS CLOSE_PARENS
1597         ;       
1598         
1599 static_constructor_declaration
1600         : SHARED SUB NEW opt_empty_parens EOL
1601           {
1602                 current_local_parameters = Parameters.EmptyReadOnlyParameters;
1603                 start_block();
1604                 oob_stack.Push (lexer.Location);
1605
1606                 Location l = (Location) oob_stack.Pop ();
1607                 $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
1608           }
1609           opt_statement_list
1610           { 
1611                 Constructor c = (Constructor) $1;
1612                 c.Block = (Block) end_block();
1613                 c.ModFlags = (int) current_modifiers;
1614                 c.OptAttributes = current_attributes;
1615                 
1616                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1617                 current_local_parameters = null;
1618           }
1619           END SUB EOL
1620         
1621 constructor_declaration
1622         : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1623           {
1624                 current_local_parameters = (Parameters) $4;
1625                 start_block();
1626                 oob_stack.Push (lexer.Location);
1627
1628                 Location l = (Location) oob_stack.Pop ();
1629                 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1630           }
1631           opt_statement_list
1632           { 
1633                 Constructor c = (Constructor) $1;
1634                 c.Block = (Block) end_block();
1635                 c.ModFlags = (int) current_modifiers;
1636                 c.OptAttributes = current_attributes;
1637                 
1638                 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1639                 current_local_parameters = null;
1640           }
1641           END SUB EOL
1642         ;
1643         
1644 opt_formal_parameter_list
1645         : /* empty */                   
1646           { 
1647                 $$ = Parameters.EmptyReadOnlyParameters; 
1648           }
1649         | formal_parameter_list 
1650           { 
1651                 $$ = $1;        
1652                 //Parameter p = ((Parameters) $1).FixedParameters[0];
1653           }
1654         ;
1655         
1656 formal_parameter_list
1657         : fixed_parameters              
1658           { 
1659                 ArrayList pars_list = (ArrayList) $1;
1660
1661                 Parameter [] pars = new Parameter [pars_list.Count];
1662                 pars_list.CopyTo (pars);
1663                 $$ = new Parameters (pars, null, lexer.Location); 
1664           } 
1665         | fixed_parameters COMMA parameter_array
1666           {
1667                 ArrayList pars_list = (ArrayList) $1;
1668
1669                 Parameter [] pars = new Parameter [pars_list.Count];
1670                 pars_list.CopyTo (pars);
1671
1672                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1673           }
1674         | parameter_array 
1675           {
1676                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1677           }
1678         ;
1679
1680 fixed_parameters
1681         : fixed_parameter       
1682           {
1683                 ArrayList pars = new ArrayList ();
1684
1685                 pars.Add ($1);
1686                 $$ = pars;
1687           }
1688         | fixed_parameters COMMA fixed_parameter
1689           {
1690                 ArrayList pars = (ArrayList) $1;
1691
1692                 pars.Add ($3);
1693                 $$ = $1;
1694           }
1695         ;
1696
1697 fixed_parameter
1698         : opt_attributes
1699           opt_parameter_modifier
1700           identifier opt_type_spec opt_variable_initializer
1701           {
1702                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1703                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1704                 
1705                 if (opt_parm && ($5 == null))
1706                         Report.Error (999, "Optional parameters must have a default value");
1707                 
1708                 if (opt_parm) {
1709                         if ((pm & Parameter.Modifier.REF) !=0)
1710                                 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1711                         else
1712                                 pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
1713                 }                       
1714                 $$ = new Parameter ((Expression) $4, (string) $3, 
1715                                         pm, (Attributes) $1, (Expression) $5, opt_parm);
1716           }
1717         ;
1718         
1719 parameter_array
1720         : PARAM_ARRAY identifier opt_parens AS type 
1721           { 
1722                 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1723                 // note  ("type must be a single-dimension array type"); 
1724           }
1725         ;
1726                 
1727 opt_parens
1728         : /* empty */
1729         | OPEN_PARENS CLOSE_PARENS
1730         ;
1731         
1732 opt_parameter_modifier
1733         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
1734         | parameter_modifiers   { $$ = $1;                      }
1735         ;
1736
1737 parameter_modifiers
1738         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1739         | parameter_modifier                            { $$ = $1;      }
1740         ;
1741         
1742 parameter_modifier
1743         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1744         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
1745         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
1746         ;       
1747
1748 opt_statement_list
1749         : /* empty */
1750         | statement_list EOL
1751         ;
1752
1753 statement_list
1754         : statement 
1755         | statement_list EOL statement
1756         ;
1757         
1758 statement : 
1759             declaration_statement
1760             {
1761                 if ($1 != null && (Block) $1 != current_block){
1762                         current_block.AddStatement ((Statement) $1);
1763                         current_block = (Block) $1;
1764                 }
1765             }
1766           | embedded_statement 
1767             {
1768                 Statement s = (Statement) $1;
1769
1770                 current_block.AddStatement ((Statement) $1);
1771             } 
1772           | labeled_statement 
1773           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1774            {
1775                 AddHandler ((Expression) $2, (string) $5);
1776            }
1777           | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1778             {
1779                 RaiseEvent ((string) $2, (ArrayList) $4);
1780             }
1781           ;     
1782
1783 labeled_statement
1784         : identifier COLON 
1785           {
1786                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1787
1788                 if (!current_block.AddLabel ((string) $1, labeled)){
1789                         Location l = lexer.Location;
1790                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1791                 }       
1792                 current_block.AddStatement (labeled);
1793           }
1794           statement
1795         ;
1796
1797 embedded_statement
1798         : expression_statement
1799         | selection_statement
1800         | iteration_statement
1801         | try_statement
1802         | jump_statement 
1803         ;
1804         
1805 jump_statement
1806         : /*break_statement
1807         | continue_statement
1808         | goto_statement
1809         | throw_statement
1810         | */return_statement
1811         | exit_statement
1812         ;
1813                 
1814 exit_statement
1815         : EXIT exit_type
1816           {
1817                 $$ = new Exit ((ExitType)$2, lexer.Location);           
1818           }
1819         ;
1820         
1821 exit_type
1822         : DO            { $$ = ExitType.DO;             }
1823         | FOR           { $$ = ExitType.FOR;            }
1824         | WHILE         { $$ = ExitType.WHILE;          }
1825         | SELECT        { $$ = ExitType.SELECT;         }
1826         | SUB           { $$ = ExitType.SUB;            }
1827         | FUNCTION      { $$ = ExitType.FUNCTION;       }
1828         | PROPERTY      { $$ = ExitType.PROPERTY;       }
1829         | TRY           { $$ = ExitType.TRY;            }
1830         ;
1831 return_statement
1832         : RETURN opt_expression 
1833           {       
1834                 $$ = new Return ((Expression) $2, lexer.Location);
1835           }
1836         ;
1837                 
1838 iteration_statement
1839         : while_statement
1840         | do_statement
1841         | for_statement
1842         /*| foreach_statement*/
1843         ;
1844
1845 try_statement
1846         : try_catch
1847         | try_catch_finally
1848         ;
1849                                 
1850 try_catch
1851         : try_header 
1852           END TRY
1853           { 
1854                 Catch g = null;
1855                 ArrayList s = new ArrayList ();
1856
1857                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
1858                         if (cc.IsGeneral)
1859                                 g = cc;
1860                         else
1861                                 s.Add (cc);
1862                 }
1863
1864                 // Now s contains the list of specific catch clauses
1865                 // and g contains the general one.
1866                 Block b = end_block();
1867
1868                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
1869           }       
1870         ;       
1871           
1872 try_catch_finally
1873         : try_header 
1874           { 
1875                 tmp_block = end_block(); 
1876           }     
1877           FINALLY EOL
1878           { 
1879                 start_block(); 
1880           }       
1881           opt_statement_list 
1882           END TRY
1883           {
1884                 Catch g = null;
1885                 ArrayList s = new ArrayList ();
1886                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
1887
1888                 if (catch_list != null){
1889                         foreach (Catch cc in catch_list) {
1890                                 if (cc.IsGeneral)
1891                                         g = cc;
1892                                 else
1893                                         s.Add (cc);
1894                         }
1895                 }
1896
1897                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
1898         
1899           }     
1900           ;       
1901         
1902 try_header
1903         : TRY EOL
1904           {   
1905                 start_block();  
1906           }
1907           opt_statement_list 
1908           opt_catch_clauses
1909           {
1910                 tmp_catch_clauses = (ArrayList) $5;
1911           }
1912         ;       
1913
1914 opt_catch_clauses
1915         : /* empty */  {  $$ = null;  }
1916         | catch_clauses
1917         ;
1918
1919 catch_clauses
1920         : catch_clause 
1921           {
1922                 ArrayList l = new ArrayList ();
1923
1924                 l.Add ($1);
1925                 $$ = l;
1926           }
1927         | catch_clauses catch_clause
1928           {
1929                 ArrayList l = (ArrayList) $1;
1930
1931                 l.Add ($2);
1932                 $$ = l;
1933           }
1934         ;
1935
1936 opt_identifier
1937         : /* empty */   {  $$ = null;  }
1938         | identifier
1939         ;
1940
1941 catch_clause 
1942         : CATCH opt_catch_args EOL
1943         {
1944                 Expression type = null;
1945                 string id = null;
1946                 
1947                 if ($2 != null) {
1948                         DictionaryEntry cc = (DictionaryEntry) $2;
1949                         type = (Expression) cc.Key;
1950                         id   = (string) cc.Value;
1951                         
1952                         if (id != null){
1953                                 ArrayList one = new ArrayList ();
1954                                 Location loc = lexer.Location;
1955
1956                                 one.Add (new VariableDeclaration (id, null, loc));
1957
1958
1959                                 $1 = current_block;
1960                                 current_block = new Block (current_block);
1961                                 Block b = declare_local_variables (type, one, loc);
1962                                 current_block = b;
1963                         }
1964                 }
1965         
1966         } 
1967         opt_statement_list {
1968                 Expression type = null;
1969                 string id = null;
1970                 Block b_catch = current_block;
1971                 
1972                 if ($2 != null){
1973                         DictionaryEntry cc = (DictionaryEntry) $2;
1974                         type = (Expression) cc.Key;
1975                         id   = (string) cc.Value;
1976                         
1977                         if ($1 != null) {
1978                                 //
1979                                 // FIXME: I can change this for an assignment.
1980                                 //
1981                                 while (current_block != (Block) $1)
1982                                         current_block = current_block.Parent;
1983                         }
1984                 }
1985
1986                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
1987         }
1988         ;
1989
1990 opt_catch_args
1991         : /* empty */ {  $$ = null; }
1992         | catch_args
1993         ;         
1994
1995 catch_args 
1996         : identifier AS type
1997         {
1998                  $$ = new DictionaryEntry ($3, $1); 
1999         }
2000         ;
2001         
2002         
2003 do_statement
2004         : DO opt_do_construct EOL
2005           {
2006                 start_block();
2007                 oob_stack.Push (lexer.Location);
2008           }     
2009           opt_statement_list
2010           LOOP opt_do_construct
2011           {
2012                 Expression t_before = (Expression) $2;
2013                 Expression t_after = (Expression) $7;
2014                 Expression t;
2015
2016                 if  ((t_before != null) && (t_after != null))
2017                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2018
2019                 if ((t_before == null) && (t_after == null))
2020                         t = new BoolLiteral (true);
2021                 else
2022                         t = (t_before != null) ? t_before : t_after;
2023                         
2024                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2025                 
2026                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2027                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2028                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2029                          
2030                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2031           }
2032           ;
2033
2034 opt_do_construct
2035         : /* empty */ { $$ = null; }
2036         | while_or_until boolean_expression
2037           {
2038                 do_type = (DoOptions)$1;
2039                 $$ = (Expression) $2;
2040           }
2041         ;
2042
2043 while_or_until
2044         : WHILE { $$ = DoOptions.WHILE; }
2045         | UNTIL { $$ = DoOptions.UNTIL; }
2046         ;
2047
2048 while_statement
2049         : WHILE
2050         {
2051                 start_block();
2052                 oob_stack.Push (lexer.Location);
2053         }
2054         boolean_expression EOL
2055         opt_statement_list
2056         END WHILE
2057         {
2058                 Location l = (Location) oob_stack.Pop ();
2059                 Block b = end_block();
2060                 Expression e = (Expression) $3;
2061                 $$ = new While ((Expression) e, (Statement) b, l);
2062         }
2063         ;
2064         
2065                 
2066 for_statement
2067         : FOR qualified_identifier ASSIGN expression TO expression opt_step EOL
2068           {
2069                 start_block();
2070           }
2071           opt_statement_list
2072           NEXT opt_next_identifier 
2073           {
2074                 Block statement = end_block();
2075                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2076                 
2077                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2078                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
2079                                                 for_var, (Expression) $6, lexer.Location);
2080                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2081                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
2082                                  
2083                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
2084                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2085                 
2086                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
2087           }       
2088         ;
2089
2090 opt_step
2091         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
2092         | STEP expression       { $$ = $2; }
2093         ;
2094
2095 opt_next_identifier
2096         : /* empty */
2097         | qualified_identifier
2098         ;
2099
2100 selection_statement
2101         : if_statement
2102         | select_statement
2103         ;
2104
2105 if_statement
2106         : if_statement_open if_statement_rest
2107           {
2108                 $$ = $2;
2109           }
2110         ;
2111         
2112 if_statement_open
2113         : IF boolean_expression THEN EOL 
2114           {
2115                 oob_stack.Push (lexer.Location);
2116                 start_block();
2117                 tmp_expr = (Expression) $2;
2118           }
2119          ;
2120
2121 if_statement_rest
2122         :         
2123           opt_statement_list
2124           END IF
2125           { 
2126                 Location l = (Location) oob_stack.Pop ();
2127
2128                 $$ = new If ((Expression) tmp_expr, (Statement) end_block(), l);
2129
2130           }       
2131         |
2132           opt_statement_list
2133           ELSE EOL 
2134           { 
2135                 tmp_block = end_block();
2136                 start_block();
2137           }
2138           opt_statement_list
2139           END IF        
2140           {
2141                 Location l = (Location) oob_stack.Pop ();
2142
2143                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2144           }        
2145         ;
2146         
2147 select_statement
2148         : SELECT opt_case expression EOL
2149           { 
2150                 oob_stack.Push (lexer.Location);
2151                 switch_stack.Push (current_block);
2152           }     
2153           opt_case_sections
2154           END SELECT 
2155           {
2156                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2157                 current_block = (Block) switch_stack.Pop ();
2158           }       
2159         ;
2160
2161 opt_case_sections
2162         : /* empty */   { $$ = null; }
2163         | case_sections { $$ = $1; }
2164         ;
2165         
2166 case_sections
2167         : case_sections case_section
2168           {
2169                 ArrayList sections = (ArrayList) $1;
2170
2171                 sections.Add ($2);
2172                 $$ = sections;
2173           }
2174         | case_section
2175           {
2176                 ArrayList sections = new ArrayList ();
2177
2178                 sections.Add ($1);
2179                 $$ = sections;
2180           }
2181         ;
2182
2183 case_section
2184         : CASE case_clauses EOL
2185           { 
2186                 start_block();
2187           }
2188           opt_statement_list
2189           {
2190                 Block topmost = current_block;
2191
2192                 while (topmost.Implicit)
2193                         topmost = topmost.Parent;
2194                         
2195                 // FIXME: This is a horrible hack which MUST go                 
2196                 topmost.statements.Add (new Break (lexer.Location));
2197                 $$ = new SwitchSection ((ArrayList) $2, topmost);
2198           }
2199           | CASE ELSE EOL
2200             /* FIXME: we should somehow flag an error 
2201                (BC30321 'Case' cannot follow a 'Case Else' 
2202                in the same 'Select' statement.) 
2203                if Case Else is not the last of the Case clauses
2204             */
2205           { 
2206                 start_block();
2207           }     
2208           opt_statement_list
2209           { 
2210                 Block topmost = current_block;
2211
2212                 while (topmost.Implicit)
2213                         topmost = topmost.Parent;
2214                         
2215                 // FIXME: This is a horrible hack which MUST go                 
2216                 topmost.statements.Add (new Break (lexer.Location));
2217                 
2218                 ArrayList a = new ArrayList();
2219                 a.Add (new SwitchLabel (null, lexer.Location));                 
2220                 $$ = new SwitchSection ((ArrayList) a, topmost);                
2221           }
2222         ;         
2223         
2224 case_clauses
2225         : case_clause
2226           {
2227                 ArrayList labels = new ArrayList ();
2228
2229                 labels.Add ($1);
2230                 $$ = labels;
2231           }     
2232         | case_clauses COMMA case_clause
2233           {
2234                 ArrayList labels = (ArrayList) ($1);
2235                 labels.Add ($2);
2236
2237                 $$ = labels;
2238           }     
2239         ;
2240         
2241 case_clause
2242         : opt_is comparison_operator expression
2243         | expression
2244           {
2245                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2246           }
2247         ;
2248         
2249 opt_is 
2250         : /* empty */
2251         | IS
2252         ;
2253
2254 comparison_operator
2255         : OP_LT
2256         | OP_GT
2257         | OP_LE
2258         | OP_NE
2259         /*| OP_EQ */
2260         ;
2261
2262 opt_case
2263         : /* empty */
2264         | CASE
2265         ;
2266
2267 expression_statement
2268         : statement_expression 
2269           {
2270                  $$ = $1; 
2271           }
2272         ;
2273
2274 statement_expression
2275         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2276         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2277         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
2278         ;
2279
2280 object_creation_expression
2281         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2282           {
2283                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2284           }
2285         ;
2286
2287 new_expression
2288         : object_creation_expression
2289         /* | array_creation_expression */
2290         ;
2291
2292 declaration_statement
2293         : local_variable_declaration 
2294           {
2295                 if ($1 != null){
2296                         DictionaryEntry de = (DictionaryEntry) $1;
2297
2298                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2299                 }
2300           }
2301
2302         | local_constant_declaration 
2303           {
2304                 if ($1 != null){
2305                         DictionaryEntry de = (DictionaryEntry) $1;
2306
2307                         $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
2308                 }
2309           }
2310         ;        
2311         
2312 local_variable_declaration
2313         : DIM variable_declarators
2314           {
2315                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
2316           }
2317         /*| DIM variable_declarators 
2318           {
2319                 $$ = new DictionaryEntry (TypeManager.system_object_expr, $2);
2320           }
2321         | DIM variable_declarators AS object_creation_expression
2322           {
2323                 if ($4 != null)
2324                         $$ = new DictionaryEntry ($4, $2);
2325                 else
2326                         $$ = null;
2327                                                 
2328           } */
2329         ;
2330
2331         
2332 local_constant_declaration
2333         : CONST constant_declarator
2334           {
2335                 if ($2 != null)
2336                         $$ = new DictionaryEntry ($1, $2);
2337                 else
2338                         $$ = null;
2339           }
2340         ;        
2341         
2342 constant_declarator
2343         : identifier ASSIGN constant_expression
2344           {
2345                 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
2346           }
2347         ;               
2348
2349 variable_declarators
2350         : variable_declarator 
2351           {
2352                 ArrayList decl = new ArrayList ();
2353                 decl.Add ($1);
2354                 $$ = decl;
2355           }
2356         | variable_declarators COMMA variable_declarator
2357           {
2358                 ArrayList decls = (ArrayList) $1;
2359                 decls.Add ($3);
2360                 $$ = $1;
2361           }
2362         ;
2363
2364 variable_declarator
2365         : variable_identifier opt_type_decl opt_variable_initializer
2366           {
2367                 string varname = (string)$1;
2368                 string dims = "";
2369                 object varinit = $3;
2370                 Expression vartype = (Expression) $2;
2371                 
2372                 /*
2373                    Check for a declaration like Dim a(2) or Dim a(2,3)
2374                    If this is the case, we must generate an ArrayCreationExpression
2375                    and, in case, add the initializer after the array has been created.
2376                 */
2377                 if (VariableDeclaration.IsArrayDecl (varname)) {
2378                         if (VariableDeclaration.DimsSpecified(varname)) { 
2379                                 varname = VariableDeclaration.StripDims (varname, ref dims);
2380                                 ArrayList a_dims = VariableDeclaration.ParseDimList(dims);
2381                                 varinit = new ArrayCreation (vartype, a_dims,"", (ArrayList) varinit, lexer.Location);
2382                         }
2383                         vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.GetRank (dims), lexer.Location);
2384                 }
2385
2386                 if (vartype is New) {
2387                         if (varinit != null) {
2388                                 Report.Error (30205, lexer.Location, "End of statement expected");
2389                                 $$ = null;
2390                         }
2391                         else
2392                         {
2393                                 varinit = vartype;
2394                                 vartype = ((New)vartype).RequestedType;
2395                         }
2396                 }
2397                 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
2398           }
2399         ;
2400
2401 variable_identifier
2402         : identifier opt_array_name_modifier 
2403           {
2404                 $$ = $1; 
2405                 if ($2 != null)
2406                         $$ = (string)$$ + (string)$2;
2407           }
2408         ;               
2409                 
2410 opt_type_spec
2411         : /* empty */   { $$ = null;            }
2412         | AS type       { $$ = (Expression) $2; };
2413         ;
2414                         
2415 opt_type_decl
2416         : opt_type_spec
2417           {
2418                 $$ = $1;
2419           }
2420         | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS 
2421           {
2422                 Report.Error (30638, "Array bounds cannot appear in type specifiers");
2423                 $$ = null;
2424           }
2425         | AS NEW type
2426           {
2427                 New n = new New ((Expression)$3, null, lexer.Location);
2428                 $$ = (Expression) n;
2429           }
2430         | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS 
2431           {
2432                 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
2433                 $$ = (Expression) n;
2434           }
2435         ;
2436                 
2437 opt_array_name_modifier
2438         : /* empty */                           { $$ = null; }
2439         | array_type_modifier                   { $$ = $1;   } 
2440         ;
2441         
2442 array_type_modifier
2443         : rank_specifiers  { $$ = $1; }
2444         ;
2445         
2446 opt_variable_initializer
2447         : /* empty */                   { $$ = null; }
2448         | ASSIGN variable_initializer   { $$ = $2; }
2449         ;
2450                 
2451 variable_initializer
2452         : expression
2453           {
2454                 $$ = $1;
2455           }
2456         | array_initializer
2457           {
2458                 $$ = $1;
2459           }
2460         
2461         ;       
2462         
2463 array_initializer
2464         : OPEN_BRACE CLOSE_BRACE
2465           {
2466                 ArrayList list = new ArrayList ();
2467                 $$ = list;
2468           }
2469         | OPEN_BRACE variable_initializer_list CLOSE_BRACE
2470           {
2471                 $$ = (ArrayList) $2;
2472           }
2473         ;
2474
2475 variable_initializer_list
2476         : variable_initializer
2477           {
2478                 ArrayList list = new ArrayList ();
2479                 list.Add ($1);
2480                 $$ = list;
2481           }
2482         | variable_initializer_list COMMA variable_initializer
2483           {
2484                 ArrayList list = (ArrayList) $1;
2485                 list.Add ($3);
2486                 $$ = list;
2487           }
2488         ;       
2489                 
2490 /* 
2491  * The following is from Rhys' grammar:
2492  * > Types in local variable declarations must be recognized as 
2493  * > expressions to prevent reduce/reduce errors in the grammar.
2494  * > The expressions are converted into types during semantic analysis.
2495  */
2496 local_variable_type
2497         : primary_expression opt_rank_specifier
2498           { 
2499                 // FIXME: Do something smart here regarding the composition of the type.
2500
2501                 // Ok, the above "primary_expression" is there to get rid of
2502                 // both reduce/reduce and shift/reduces in the grammar, it should
2503                 // really just be "type_name".  If you use type_name, a reduce/reduce
2504                 // creeps up.  If you use qualified_identifier (which is all we need
2505                 // really) two shift/reduces appear.
2506                 // 
2507
2508                 // So the super-trick is that primary_expression
2509                 // can only be either a SimpleName or a MemberAccess. 
2510                 // The MemberAccess case arises when you have a fully qualified type-name like :
2511                 // Foo.Bar.Blah i;
2512                 // SimpleName is when you have
2513                 // Blah i;
2514                   
2515                 Expression expr = (Expression) $1;  
2516                 if (!(expr is SimpleName || expr is MemberAccess)) {
2517                         Error_ExpectingTypeName (lexer.Location, expr);
2518                         $$ = null;
2519                 } else {
2520                         //
2521                         // So we extract the string corresponding to the SimpleName
2522                         // or MemberAccess
2523                         // 
2524                         if ((string) $2 == "")
2525                                 $$ = $1;
2526                         else
2527                                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2528                 }
2529           }
2530         | builtin_types opt_rank_specifier
2531           {
2532                 if ((string) $2 == "")
2533                         $$ = $1;
2534                 else
2535                         $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2536           }
2537         ;
2538                 
2539 rank_specifiers
2540         : rank_specifier
2541           {
2542                   $$ = $1;
2543           }
2544         | rank_specifiers rank_specifier
2545           {
2546                   $$ = (string) $2 + (string) $1;
2547           }             
2548         ;
2549
2550 rank_specifier
2551         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
2552           {
2553                 $$ = "[" + (string) $2 + "]";
2554           }
2555         ;
2556                         
2557 opt_rank_specifier
2558         : /* empty */
2559           {
2560                   $$ = "";
2561           }
2562         | rank_specifiers
2563           {
2564                         $$ = $1;
2565           }
2566         ;               
2567         
2568 opt_dim_separators
2569         : /* empty */
2570           {
2571                 $$ = "";
2572           }
2573         | dim_separators
2574           {
2575                 $$ = $1;
2576           }     
2577         | dim_specifiers
2578           {
2579                 $$ = $1;
2580           }       
2581         ;
2582
2583 dim_separators
2584         : COMMA
2585           {
2586                 $$ = ",";
2587           }
2588         | dim_separators COMMA
2589           {
2590                 $$ = (string) $1 + ",";
2591           }
2592         ;
2593         
2594 dim_specifiers
2595         : integer_literal                       { $$ = ((IntLiteral)$1).AsString(); }
2596         | dim_specifiers COMMA integer_literal  { $$ = $1 + "," + ((IntLiteral)$3).AsString(); }
2597         ;
2598                 
2599 /* Expressions */
2600 primary_expression
2601         : literal
2602           {
2603                 // 7.5.1: Literals
2604           }
2605
2606         | qualified_identifier
2607           {
2608                 string name = (string) $1;
2609
2610                 $$ = DecomposeQI (name, lexer.Location);
2611           }
2612         | parenthesized_expression
2613         | member_access
2614         | invocation_expression
2615         | element_access
2616         | this_access
2617         //| base_access
2618         | new_expression
2619         ;
2620
2621 literal
2622         : boolean_literal
2623         | integer_literal
2624         | real_literal
2625         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
2626         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
2627         | NOTHING                       { $$ = NullLiteral.Null; }
2628         ;
2629
2630 real_literal
2631         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
2632         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
2633         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
2634         ;
2635
2636 integer_literal
2637         : LITERAL_INTEGER       {
2638                 object v = lexer.Value;
2639
2640                 if (v is int)
2641                         $$ = new IntLiteral ((Int32) v); 
2642                 else if (v is uint)
2643                         $$ = new UIntLiteral ((UInt32) v);
2644                 else if (v is long)
2645                         $$ = new LongLiteral ((Int64) v);
2646                 else if (v is ulong)
2647                         $$ = new ULongLiteral ((UInt64) v);
2648                 else
2649                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
2650                         
2651           }
2652         ;
2653
2654 boolean_literal
2655         : TRUE                  { $$ = new BoolLiteral (true); }
2656         | FALSE                 { $$ = new BoolLiteral (false); }
2657         ;
2658
2659 parenthesized_expression
2660         : OPEN_PARENS expression CLOSE_PARENS
2661           { $$ = $2; }
2662         ;
2663
2664 member_access
2665         : primary_expression DOT identifier
2666           {
2667                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2668           }
2669         | predefined_type DOT identifier
2670           {
2671                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2672           }
2673         ;
2674
2675 predefined_type
2676         : builtin_types
2677         ;
2678
2679 invocation_expression
2680         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2681           {
2682                 if ($1 == null) {
2683                         Location l = lexer.Location;
2684                         Report.Error (1, l, "THIS IS CRAZY");
2685                 }
2686                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2687           }
2688         | MYBASE DOT identifier OPEN_PARENS opt_expression_list CLOSE_PARENS
2689           {
2690                 BaseAccess ba = new BaseAccess ((string) $3, lexer.Location);
2691                 $$ = new Invocation ((Expression) ba, (ArrayList) $5, lexer.Location);
2692           }  
2693         | MYBASE DOT NEW OPEN_PARENS opt_expression_list CLOSE_PARENS
2694           {
2695                 BaseAccess ba = new BaseAccess ("New", lexer.Location);
2696                 $$ = new Invocation ((Expression) ba, (ArrayList) $5, lexer.Location);
2697           }       
2698         ;
2699
2700 opt_argument_list
2701         : argument_list
2702           { 
2703                 /*
2704                    The 'argument' rule returns an 'empty' argument
2705                    of type NoArg (used for default arguments in invocations)
2706                    if no arguments are actually passed.
2707
2708                    If there is only one argument and it is o type NoArg,
2709                    we return a null (empty) list
2710                 */
2711                 ArrayList args = (ArrayList) $1;
2712                 if (args.Count == 1 &&
2713                     ((Argument)args[0]).ArgType == Argument.AType.NoArg)
2714                         $$ = null;
2715                 else
2716                         $$ = $1;
2717           }
2718         ;
2719
2720 argument_list
2721         : argument
2722           {
2723                 ArrayList list = new ArrayList ();
2724                 list.Add ($1);
2725                 $$ = list;
2726           }
2727         | argument_list COMMA argument
2728           {
2729                 ArrayList list = (ArrayList) $1;
2730                 list.Add ($3);
2731                 $$ = list;
2732           }
2733         ;
2734
2735 argument
2736         : expression
2737           {
2738                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2739           }
2740         | BYREF variable_reference
2741           {
2742                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2743           }
2744         | /* empty */
2745           {
2746                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
2747           }
2748         ;
2749
2750 variable_reference
2751         : expression {/* note ("section 5.4"); */  $$ = $1;  }
2752         ;
2753
2754 element_access
2755         : primary_expression OPEN_PARENS expression_list CLOSE_PARENS
2756           {
2757           
2758                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2759           }
2760 /*      | primary_expression rank_specifiers
2761           {
2762                 // So the super-trick is that primary_expression
2763                 // can only be either a SimpleName or a MemberAccess.
2764                 // The MemberAccess case arises when you have a fully qualified type-name like :
2765                 // Foo.Bar.Blah i;
2766                 // SimpleName is when you have
2767                 // Blah i;
2768                 Expression expr = (Expression) $1;
2769                 
2770                 if (!(expr is SimpleName || expr is MemberAccess)) {
2771                         Error_ExpectingTypeName (lexer.Location, expr);
2772                         $$ = TypeManager.system_object_expr;
2773                 } else {
2774                         //
2775                         // So we extract the string corresponding to the SimpleName
2776                         // or MemberAccess
2777                         //
2778                         $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2779                 }
2780           }*/
2781         ;
2782
2783 expression
2784         : conditional_expression { $$ = $1; }
2785         /*| assignment_expression*/
2786         ;
2787
2788 opt_expression
2789         : /* empty */
2790         | expression
2791         ;
2792         
2793 expression_list
2794         : expression
2795           {
2796                 ArrayList list = new ArrayList ();
2797                 list.Add ($1);
2798                 $$ = list;
2799           }
2800         | expression_list COMMA expression
2801           {
2802                 ArrayList list = (ArrayList) $1;
2803                 list.Add ($3);
2804                 $$ = list;
2805           }
2806         ;
2807
2808 opt_expression_list
2809         : /*empty */ { $$ = null; }
2810         | expression_list
2811         ;
2812         
2813 this_access
2814         : ME
2815           {
2816                 $$ = new This (current_block, lexer.Location);
2817           }
2818         ;
2819
2820 unary_expression
2821         : primary_expression
2822         | NOT prefixed_unary_expression
2823           {
2824                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2825           }
2826         | cast_expression
2827         ;
2828
2829 cast_expression
2830         : cast_operator OPEN_PARENS expression CLOSE_PARENS
2831           {
2832                   $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2833           }     
2834         | CTYPE OPEN_PARENS expression COMMA expression CLOSE_PARENS
2835           {
2836                   $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
2837           }                       
2838         ;
2839         
2840 cast_operator
2841         : CBOOL         { $$ = TypeManager.system_boolean_expr;         }
2842         | CBYTE         { $$ = TypeManager.system_byte_expr;            }
2843         | CCHAR         { $$ = TypeManager.system_char_expr;            }
2844         | CDATE         { $$ = TypeManager.system_decimal_expr;         } //FIXME
2845         | CDBL          { $$ = TypeManager.system_double_expr;          }
2846         | CDEC          { $$ = TypeManager.system_decimal_expr;         }
2847         | CINT          { $$ = TypeManager.system_int32_expr;           }
2848         | CLNG          { $$ = TypeManager.system_int64_expr;           }
2849         | COBJ          { $$ = TypeManager.system_object_expr;          }
2850         | CSHORT        { $$ = TypeManager.system_int16_expr;           }
2851         | CSNG          { $$ = TypeManager.system_single_expr;          }
2852         | CSTR          { $$ = TypeManager.system_string_expr;  }
2853         ;
2854         
2855         //
2856         // The idea to split this out is from Rhys' grammar
2857         // to solve the problem with casts.
2858         //
2859 prefixed_unary_expression
2860         : unary_expression
2861         | PLUS prefixed_unary_expression
2862           {
2863                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2864           }
2865         | MINUS prefixed_unary_expression
2866           {
2867                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2868           }
2869         | ADDRESSOF prefixed_unary_expression
2870           {
2871                 // FIXME: We should generate an error if AddressOf is NOT used
2872                 // during delegate creation
2873                 $$ = $2;
2874           }       
2875         ;
2876
2877 multiplicative_expression
2878         : prefixed_unary_expression
2879         | multiplicative_expression STAR prefixed_unary_expression
2880           {
2881                 $$ = new Binary (Binary.Operator.Multiply,
2882                                  (Expression) $1, (Expression) $3, lexer.Location);
2883           }
2884         | multiplicative_expression DIV prefixed_unary_expression
2885           {
2886                 $$ = new Binary (Binary.Operator.Division,
2887                                  (Expression) $1, (Expression) $3, lexer.Location);
2888           }
2889         | multiplicative_expression OP_MODULUS prefixed_unary_expression
2890           {
2891                 $$ = new Binary (Binary.Operator.Modulus,
2892                                  (Expression) $1, (Expression) $3, lexer.Location);
2893           }
2894         ;
2895
2896 additive_expression
2897         : multiplicative_expression
2898         | additive_expression PLUS multiplicative_expression
2899           {
2900                 $$ = new Binary (Binary.Operator.Addition,
2901                                  (Expression) $1, (Expression) $3, lexer.Location);
2902           }
2903         | additive_expression MINUS multiplicative_expression
2904           {
2905                 $$ = new Binary (Binary.Operator.Subtraction,
2906                                  (Expression) $1, (Expression) $3, lexer.Location);
2907           }
2908         | additive_expression OP_CONCAT multiplicative_expression
2909           {
2910                 // FIXME: This should only work for String expressions
2911                 // We probably need to use something from the runtime
2912                 $$ = new Binary (Binary.Operator.Addition,
2913                                  (Expression) $1, (Expression) $3, lexer.Location);
2914           }       
2915         ;
2916
2917 relational_expression
2918         : additive_expression
2919         | relational_expression OP_LT additive_expression
2920           {
2921                 $$ = new Binary (Binary.Operator.LessThan,
2922                                  (Expression) $1, (Expression) $3, lexer.Location);
2923           }
2924         | relational_expression OP_GT additive_expression
2925           {
2926                 $$ = new Binary (Binary.Operator.GreaterThan,
2927                                  (Expression) $1, (Expression) $3, lexer.Location);
2928           }
2929         | relational_expression OP_LE additive_expression
2930           {
2931                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2932                                  (Expression) $1, (Expression) $3, lexer.Location);
2933           }
2934         | relational_expression OP_GE additive_expression
2935           {
2936                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2937                                  (Expression) $1, (Expression) $3, lexer.Location);
2938           }
2939         | relational_expression IS type_name
2940           {
2941                 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2942           }
2943         | relational_expression AS type_name
2944           {
2945                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2946           }
2947         ;
2948
2949 equality_expression
2950         : relational_expression
2951         | equality_expression ASSIGN relational_expression
2952           {
2953                 $$ = new Binary (Binary.Operator.Equality,
2954                                  (Expression) $1, (Expression) $3, lexer.Location);
2955           }
2956         ;
2957
2958 and_expression
2959         : equality_expression
2960         | and_expression OP_AND equality_expression
2961           {
2962                 $$ = new Binary (Binary.Operator.BitwiseAnd,
2963                                  (Expression) $1, (Expression) $3, lexer.Location);
2964           }
2965         ;
2966
2967 exclusive_or_expression
2968         : and_expression
2969         | exclusive_or_expression OP_XOR and_expression
2970           {
2971                 $$ = new Binary (Binary.Operator.ExclusiveOr,
2972                                  (Expression) $1, (Expression) $3, lexer.Location);
2973           }
2974         ;
2975
2976 conditional_and_expression
2977         : exclusive_or_expression
2978         | conditional_and_expression OP_AND exclusive_or_expression
2979           {
2980                 $$ = new Binary (Binary.Operator.LogicalAnd,
2981                                  (Expression) $1, (Expression) $3, lexer.Location);
2982           }
2983         ;
2984
2985 conditional_or_expression
2986         : conditional_and_expression
2987         | conditional_or_expression OP_OR conditional_and_expression
2988           {
2989                 $$ = new Binary (Binary.Operator.LogicalOr,
2990                                  (Expression) $1, (Expression) $3, lexer.Location);
2991           }
2992         ;
2993
2994 conditional_expression
2995         : conditional_or_expression
2996         ;
2997
2998 assignment_expression
2999         : prefixed_unary_expression ASSIGN expression
3000           { 
3001                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3002           }
3003         ;
3004
3005 constant_expression
3006         : expression
3007         ;
3008
3009 boolean_expression
3010         : expression
3011         ;
3012
3013 type
3014         : type_name {   /* class_type */
3015                 /*
3016                    This does interfaces, delegates, struct_types, class_types,
3017                    parent classes, and more! 4.2
3018                  */
3019                 $$ = DecomposeQI ((string) $1, lexer.Location); 
3020           }
3021         | builtin_types 
3022         /*| array_type 
3023          | pointer_type */
3024         ;
3025
3026 type_list
3027         : type
3028           {
3029                 ArrayList types = new ArrayList ();
3030
3031                 types.Add ($1);
3032                 $$ = types;
3033           }
3034         | type_list COMMA type
3035           {
3036                 ArrayList types = (ArrayList) $1;
3037
3038                 types.Add ($3);
3039                 $$ = types;
3040           }
3041         ;
3042
3043 type_name
3044         : namespace_or_type_name
3045         ;
3046         
3047 namespace_or_type_name
3048         : qualified_identifier
3049         ;
3050
3051 array_type
3052         : type bracketed_rank_specifiers
3053           {
3054                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3055           }
3056         ;
3057         
3058 bracketed_rank_specifiers
3059         : bracketed_rank_specifier bracketed_opt_rank_specifier
3060           {
3061                   $$ = (string) $2 + (string) $1;
3062           }
3063         ;
3064
3065 bracketed_rank_specifier
3066         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
3067           {
3068                 $$ = "[" + (string) $2 + "]";
3069           }
3070         ;
3071
3072 bracketed_opt_rank_specifier
3073         : /* empty */
3074           {
3075                   $$ = "";
3076           }
3077         | bracketed_rank_specifiers
3078           {
3079                 $$ = $1;
3080           }
3081         ;               
3082
3083 /* Built-in / Integral types */
3084 builtin_types
3085         : OBJECT        { $$ = TypeManager.system_object_expr; }
3086         | STRING        { $$ = TypeManager.system_string_expr; }
3087         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
3088         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
3089         | SINGLE        { $$ = TypeManager.system_single_expr; }
3090         | DOUBLE        { $$ = TypeManager.system_double_expr; }
3091         | integral_type
3092         ;
3093
3094 integral_type
3095         : /*SBYTE               { $$ = TypeManager.system_sbyte_expr; }
3096         | BYTE          { $$ = TypeManager.system_byte_expr; }
3097         | SHORT         { $$ = TypeManager.system_int16_expr; }
3098         | USHORT        { $$ = TypeManager.system_uint16_expr; }
3099         | */ INTEGER    { $$ = TypeManager.system_int32_expr; }/*
3100         | UINT          { $$ = TypeManager.system_uint32_expr; }
3101         | LONG          { $$ = TypeManager.system_int64_expr; }
3102         | ULONG         { $$ = TypeManager.system_uint64_expr; }
3103         | CHAR          { $$ = TypeManager.system_char_expr; }
3104         | VOID          { $$ = TypeManager.system_void_expr; }*/
3105         ;
3106
3107 interface_type
3108         : type_name
3109         ;
3110 %%
3111
3112
3113 Tokenizer lexer;
3114
3115 public Tokenizer Lexer {
3116         get {
3117                 return lexer;
3118         }
3119 }                  
3120
3121 public static Expression DecomposeQI (string name, Location loc)
3122 {
3123         Expression o;
3124
3125         if (name.IndexOf ('.') == -1){
3126                 return new SimpleName (name, loc);
3127         } else {
3128                 int pos = name.LastIndexOf (".");
3129                 string left = name.Substring (0, pos);
3130                 string right = name.Substring (pos + 1);
3131
3132                 o = DecomposeQI (left, loc);
3133
3134                 return new MemberAccess (o, right, loc);
3135         }
3136 }
3137
3138 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3139 {
3140         Block implicit_block;
3141         ArrayList inits = null;
3142
3143         //
3144         // We use the `Used' property to check whether statements
3145         // have been added to the current block.  If so, we need
3146         // to create another block to contain the new declaration
3147         // otherwise, as an optimization, we use the same block to
3148         // add the declaration.
3149         //
3150         // FIXME: A further optimization is to check if the statements
3151         // that were added were added as part of the initialization
3152         // below.  In which case, no other statements have been executed
3153         // and we might be able to reduce the number of blocks for
3154         // situations like this:
3155         //
3156         // int j = 1;  int k = j + 1;
3157         //
3158         
3159         VariableDeclaration.FixupTypes (variable_declarators);
3160         
3161         if (current_block.Used) {
3162                 implicit_block = new Block (current_block, true, loc, Location.Null);
3163                 implicit_block.AddChildVariableNames (current_block);
3164         } else
3165                 implicit_block = current_block;
3166
3167         foreach (VariableDeclaration decl in variable_declarators){
3168                 Expression type = decl.type;
3169                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3170                         if (decl.expression_or_array_initializer != null){
3171                                 if (inits == null)
3172                                         inits = new ArrayList ();
3173                                 inits.Add (decl);
3174                         }
3175                 }
3176         }
3177
3178         if (inits == null)
3179                 return implicit_block;
3180
3181         foreach (VariableDeclaration decl in inits){
3182                 Assign assign;
3183                 Expression expr;
3184                 Expression type = decl.type;
3185                 
3186                 if ((decl.expression_or_array_initializer is Expression) || 
3187                     (decl.expression_or_array_initializer is New)) {
3188                         expr = (Expression) decl.expression_or_array_initializer;
3189                 } else {
3190                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3191                         
3192                         expr = new ArrayCreation (type, "", init, decl.Location);
3193                 }
3194
3195                 LocalVariableReference var;
3196                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3197
3198                 assign = new Assign (var, expr, decl.Location);
3199
3200                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3201         }
3202         
3203         return implicit_block;
3204 }
3205
3206
3207 Block declare_local_constant (Expression type, VariableDeclaration decl)
3208 {
3209         Block implicit_block;
3210
3211         if (current_block.Used)
3212                 implicit_block = new Block (current_block, true);
3213         else
3214                 implicit_block = current_block;
3215
3216         if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3217                                           current_local_parameters, decl.Location))){
3218         }
3219         
3220         return implicit_block;
3221 }
3222
3223 // <summary>
3224 //   A class used to pass around variable declarations and constants
3225 // </summary>
3226 public class VariableDeclaration {
3227         public string identifier;
3228         public object expression_or_array_initializer;
3229         public Location Location;
3230         public Attributes OptAttributes;
3231         public Expression type;
3232         public ArrayList dims;
3233                 
3234         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
3235         {
3236                 this.identifier = id;
3237                 this.expression_or_array_initializer = eoai;
3238                 this.Location = l;
3239                 this.OptAttributes = opt_attrs;
3240                 this.type = t;
3241                 this.dims = null;
3242         }       
3243
3244         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3245         {
3246         }
3247         
3248         public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
3249         {
3250         }       
3251         
3252         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
3253                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
3254         {
3255         }       
3256         
3257         public static void FixupTypes (ArrayList vars)
3258         {
3259                 int varcount =  vars.Count;
3260                 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
3261                         
3262                 if (last_var.type == null)
3263                         last_var.type = TypeManager.system_object_expr;
3264                         
3265                 Expression cur_type = last_var.type;
3266                 int n = varcount - 1;
3267                 
3268                 while (n >= 0) {
3269                         VariableDeclaration var = (VariableDeclaration) vars[n--];
3270                         if (var.type == null)
3271                                 var.type = cur_type;
3272                         else
3273                                 cur_type = var.type;
3274                 }
3275         }
3276         
3277         public static bool DimsSpecified (string varname)
3278         {
3279                 bool res = false;
3280                 
3281                 if (varname.IndexOf("[") >= 0) {
3282                         char[] ds = {'1','2','3','4','5','6','7','8','9'};
3283                         
3284                         string dimpart = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3285                         if (dimpart.IndexOfAny (ds) >= 0) 
3286                                 res = true;
3287                 }
3288                 return (res);
3289         }
3290         
3291         public static string StripDims (string varname, ref string d)
3292         {
3293                 string res = varname;
3294                 string dres = "";
3295                 
3296                 if (varname.IndexOf("[") >= 0) {
3297                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3298                         res = varname.Substring(0, varname.IndexOf("["));
3299                 }
3300                 d = dres;
3301                 return (res);
3302         }       
3303         
3304         public static string StripDims (string varname)
3305         {
3306                 string dres = "";
3307                 
3308                 return (StripDims(varname, ref dres));
3309         }       
3310         
3311         public static string GetRank (string dims)
3312         {
3313                 string res = "";
3314                 int x;
3315                 
3316                 for (x = 0; x < dims.Length; x++) {
3317                         if (dims[x] == '[' || dims[x] == ']' || dims[x] == ',')
3318                                 res = res + dims[x];
3319                 }                               
3320                 return (res);
3321         }               
3322         
3323         public static ArrayList ParseDimList (string dims)
3324         {
3325                 ArrayList res = new ArrayList();
3326                 string d = dims.Substring (1, dims.Length -2);
3327                 Array a = d.Split (',');
3328                 
3329                 if (a.GetLength(0) > 32) {
3330                         Report.Error (999, "Arrays cannot have more than 32 dimensions");
3331                 }
3332                 
3333                 foreach (string s in a) 
3334                         if (s != "")
3335                                 res.Add (new IntLiteral ((Int32) Convert.ToInt32(s)));
3336                         else
3337                                 res.Add (new IntLiteral ((Int32) 0));
3338                 
3339                 return (res);
3340         }               
3341         
3342         public static bool IsArrayDecl (string varname)
3343         {
3344                 return (varname.IndexOf("[") >= 0);
3345         }                       
3346         
3347         public static void FixupArrayTypes (ArrayList vars)
3348         {
3349                 int varcount =  vars.Count;
3350                 string dims;
3351                 
3352                 foreach (VariableDeclaration var in vars) {
3353                         if (var.identifier.EndsWith(",")) {
3354                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
3355                                                                 var.identifier.LastIndexOf(",")) + "]";
3356                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
3357                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
3358                         }
3359                 }
3360         }                               
3361 }
3362
3363 public Property BuildSimpleProperty (Expression p_type, string name, 
3364                                         Field p_fld, int mod_flags,
3365                                         Attributes attrs, Location loc) 
3366 {
3367         Property p;
3368         Block get_block, set_block;
3369         Accessor acc_set, acc_get;
3370         StatementExpression a_set;
3371         Statement a_get;
3372         Parameter [] args;
3373         
3374         // Build SET Block
3375         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
3376         args  = new Parameter [1];
3377         args [0] = implicit_value_parameter;
3378                 
3379         Parameters set_params = new Parameters (args, null, loc);
3380         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
3381                             (Expression) new SimpleName("value", loc), loc), loc);
3382                             
3383         set_block = new Block (current_block, set_params, loc, Location.Null);
3384         set_block.AddStatement ((Statement) a_set);                                         
3385         acc_set = new Accessor (set_block, attrs);
3386         
3387         // Build GET Block
3388         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
3389         get_block = new Block (current_block, null, loc, Location.Null);
3390         get_block.AddStatement ((Statement) a_get);                                         
3391         acc_get = new Accessor (get_block, attrs);
3392                 
3393         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
3394         
3395         return (p);
3396 }
3397                 
3398 void start_block () 
3399 {
3400         current_block = new Block (current_block, current_local_parameters,
3401                            lexer.Location, Location.Null);
3402
3403
3404 Block end_block ()
3405
3406         Block res;
3407         
3408         while (current_block.Implicit)
3409                 current_block = current_block.Parent;
3410
3411         res = current_block;
3412
3413         current_block.SetEndLocation (lexer.Location);
3414         current_block = current_block.Parent;
3415         
3416         return (res);
3417 }
3418
3419 private void AddHandler (Expression evt_definition, string handler_name)
3420 {
3421         AddHandler (current_block, evt_definition, handler_name);
3422 }
3423
3424 void CheckAttributeTarget (string a)
3425 {
3426         switch (a) {
3427
3428         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3429                 return;
3430                 
3431         default :
3432                 Location l = lexer.Location;
3433                 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3434                 break;
3435         }
3436 }
3437
3438 private void AddHandler (Block b, Expression evt_id, string handler_name)
3439 {
3440         Location loc = lexer.Location;
3441         string evt_target = evt_id.ToString();
3442         evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
3443         Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
3444         b.AddStatement (s);
3445 }
3446
3447 private void RaiseEvent (string evt_name, ArrayList args)
3448 {
3449         Location loc = lexer.Location;
3450         
3451         Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
3452         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); 
3453         current_block.AddStatement (s); 
3454 }
3455
3456 // FIXME: THIS DOES NOT WORK!!!
3457 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
3458 {
3459         Location loc = lexer.Location;
3460         ArrayList neh_args = new ArrayList();
3461         neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
3462         
3463         ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
3464         
3465         CompoundAssign ca = new CompoundAssign (
3466                         Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
3467                         
3468         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
3469         b.AddStatement (s);     
3470 }
3471
3472 // <summary>
3473 //  This method is used to get at the complete string representation of
3474 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
3475 //  This is necessary because local_variable_type admits primary_expression
3476 //  as the type of the variable. So we do some extra checking
3477 // </summary>
3478 string GetQualifiedIdentifier (Expression expr)
3479 {
3480         if (expr is SimpleName)
3481                 return ((SimpleName)expr).Name;
3482         else if (expr is MemberAccess)
3483                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3484         else 
3485                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3486         
3487 }
3488
3489 private void RemoveHandler (Expression evt_definition, string handler_name)
3490 {
3491         RemoveHandler (current_block, evt_definition, handler_name);
3492 }
3493
3494
3495
3496 void Error_ExpectingTypeName (Location l, Expression expr)
3497 {
3498         if (expr is Invocation){
3499                 Report.Error (1002, l, "; expected");
3500         } else {
3501                 Report.Error (-1, l, "Invalid Type definition");
3502         }
3503 }
3504
3505 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
3506         return true;
3507 }
3508
3509 public override int parse ()
3510 {
3511         current_namespace = new Namespace (null, RootContext.RootNamespace);
3512         current_container = RootContext.Tree.Types;
3513         current_container.Namespace = current_namespace;
3514         oob_stack = new Stack ();
3515         switch_stack = new Stack ();
3516         
3517         UseExtendedSyntax = name.EndsWith(".mbs");
3518         OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
3519         OptionStrict = InitialOptionStrict || UseExtendedSyntax;
3520         OptionCompareBinary = InitialOptionCompareBinary;
3521
3522         lexer = new Tokenizer (input, name, defines);
3523         StringBuilder value = new StringBuilder ();
3524         //yacc_verbose_flag=true;
3525         try 
3526         {
3527                 if (yacc_verbose_flag)
3528                         yyparse (lexer, new yydebug.yyDebugSimple ());
3529                 else
3530                         yyparse (lexer);
3531         } 
3532         catch (Exception e)
3533         {
3534                 Console.WriteLine (lexer.location + "  : Parsing error in " + lexer.ref_name);
3535                 Report.Error (9999, lexer.Location, "");
3536                 Console.WriteLine (e);
3537         }
3538         
3539         return Report.Errors;
3540 }
3541
3542 /* end end end */
3543 }
3544