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