Optional parameters support
[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                 bool UseExtendedSyntax; // for ".mbs" files
123
124                 public override string[] extensions()
125                 {
126                         string [] list = { ".vb", ".mbs" };
127                         return list;
128                 }
129
130 %}
131
132 %token EOF
133 %token NONE   /* This token is never returned by our lexer */
134 %token ERROR  // This is used not by the parser, but by the tokenizer.
135               // do not remove.
136
137 /*
138  *These are the MonoBASIC keywords
139  */
140 %token ADDHANDLER
141 %token ADDRESSOF
142 %token ALIAS
143 %token AND
144 %token ANDALSO
145 %token ANSI
146 %token AS
147 %token ASSEMBLY
148 %token AUTO
149 %token BOOLEAN  
150 %token BYREF
151 %token BYTE
152 %token BYVAL    
153 %token CALL
154 %token CASE     
155 %token CATCH    
156 %token CBOOL
157 %token CBYTE
158 %token CCHAR    
159 %token CDATE
160 %token CDEC
161 %token CDBL
162 %token CHAR     
163 %token CINT
164 %token CLASS
165 %token CLNG
166 %token COBJ
167 //%token COMPARE        
168 %token CONST    
169 %token CSHORT   
170 %token CSNG
171 %token CSTR
172 %token CTYPE
173 %token DATE
174 %token DECIMAL  
175 %token DECLARE
176 %token DEFAULT  
177 %token DELEGATE 
178 %token DESCRIPTION // MonoBASIC extension
179 %token DIM
180 %token DO       
181 %token DOUBLE   
182 %token EACH     
183 %token ELSE
184 %token ELSEIF
185 %token END      
186 %token ENUM     
187 %token EOL
188 %token ERASE
189 %token ERROR
190 %token EVENT
191 %token EXIT     
192 //%token EXPLICIT       
193 %token FALSE    
194 %token FINALLY  
195 %token FOR      
196 %token FRIEND
197 %token FUNCTION
198 %token GET
199 %token GETTYPE
200 %token GOTO     
201 %token HANDLES
202 %token IF       
203 %token IMPLEMENTS
204 %token IMPORTS  
205 %token IN       
206 %token INHERITS
207 %token INTEGER  
208 %token INTERFACE
209 %token IS
210 %token LET
211 %token LIB      
212 %token LIKE     
213 %token LONG     
214 %token LOOP
215 %token ME
216 %token MOD
217 %token MODULE
218 %token MUSTINHERIT      
219 %token MUSTOVERRIDE
220 %token MYBASE
221 %token MYCLASS
222 %token NAMESPACE
223 %token NEW
224 %token NEXT     
225 %token NOT
226 %token NOTHING
227 %token NOTINHERITABLE
228 %token NOTOVERRIDABLE
229 %token OBJECT   
230 %token ON
231 %token OPTION   
232 %token OPTIONAL 
233 %token OR
234 %token ORELSE
235 %token OVERLOADS
236 %token OVERRIDABLE      
237 %token OVERRIDES        
238 %token PARAMETER // MonoBASIC extension
239 %token PARAM_ARRAY
240 %token PRESERVE
241 %token PRIVATE  
242 %token PROPERTY
243 %token PROTECTED
244 %token PUBLIC
245 %token RAISEEVENT
246 %token READONLY 
247 %token REDIM
248 %token REM
249 %token REMOVEHANDLER
250 %token RESUME   
251 %token RETURN
252 %token SELECT
253 %token SET
254 %token SHADOWS
255 %token SHARED
256 %token SHORT    
257 %token SINGLE
258 %token SIZEOF   
259 %token STATIC   
260 %token STEP
261 %token STOP
262 %token STRING   
263 %token STRUCTURE        
264 %token SUB
265 %token SUMMARY // MonoBASIC extension
266 %token SYNCLOCK
267 %token THEN
268 %token THROW
269 %token TO
270 %token TRUE     
271 %token TRY      
272 %token TYPEOF   
273 %token UNICODE
274 %token UNTIL
275 %token VARIANT  
276 %token WHEN     
277 %token WHILE    
278 %token WITH
279 %token WITHEVENTS
280 %token WRITEONLY
281 %token XOR
282
283 /* MonoBASIC single character operators/punctuation. */
284 %token OPEN_BRACKET  "["
285 %token CLOSE_BRACKET "]"
286 %token OPEN_PARENS   "("
287 %token CLOSE_PARENS  ")"
288 %token DOT           "."
289 %token COMMA         ","
290 %token COLON         ":"
291
292 %token PLUS           "+"
293 %token MINUS          "-"
294 %token ASSIGN         "="
295 %token OP_LT          "<"
296 %token OP_GT          ">"
297 %token STAR           "*"
298 %token PERCENT        "%"
299 %token DIV            "/"
300 %token OP_EXP         "^"
301 %token INTERR         "?"
302 %token OP_IDIV        "\\"
303 %token OP_CONCAT      "&"
304
305 /* MonoBASIC multi-character operators. */
306 %token OP_LE                  "<="
307 %token OP_GE                  ">="
308 %token OP_EQ                  "=="
309 %token OP_NE                  "<>"
310 %token OP_AND                 //"and"
311 %token OP_OR                  //"or"
312 %token OP_XOR                 //"xor"
313 %token OP_MODULUS             //"mod"
314 %token OP_MULT_ASSIGN         "*="
315 %token OP_DIV_ASSIGN          "/="
316 %token OP_IDIV_ASSIGN         "\\="
317 %token OP_ADD_ASSIGN          "+="
318 %token OP_SUB_ASSIGN          "-="
319 %token OP_CONCAT_ASSIGN       "&="
320 %token OP_EXP_ASSIGN          "^="
321
322 /* Numbers */
323 %token LITERAL_INTEGER           "int literal"
324 %token LITERAL_SINGLE            "float literal"
325 %token LITERAL_DOUBLE            "double literal"
326 %token LITERAL_DECIMAL           "decimal literal"
327 %token LITERAL_CHARACTER         "character literal"
328 %token LITERAL_STRING            "string literal"
329
330 %token IDENTIFIER
331
332 /* Add precedence rules to solve dangling else s/r conflict */
333 %nonassoc LOWPREC
334 %nonassoc IF
335 %nonassoc ELSE
336 %right ASSIGN
337 %left OP_OR
338 %left OP_AND
339 %left BITWISE_OR
340 %left BITWISE_AND
341 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
342 %left PLUS MINUS
343 %left STAR DIV PERCENT
344 %right BITWISE_NOT CARRET UMINUS
345 %nonassoc OP_INC OP_DEC
346 %left OPEN_PARENS
347 %left OPEN_BRACKET OPEN_BRACE
348 %left DOT
349 %nonassoc HIGHPREC
350
351 %start compilation_unit
352 %%
353
354 compilation_unit
355         : opt_imports_directives 
356           opt_attributes
357           opt_declarations 
358           EOF
359           {
360                 $$ = $3;
361           }
362         ;
363         
364 opt_declarations
365         : /* empty */
366         | declarations
367         ;
368
369 declarations
370         : declaration
371         | declarations declaration
372         ;
373         
374 declaration
375         : namespace_declaration
376         | type_declaration
377           {
378                 string name = "";
379                 int mod_flags;
380
381                 if ($1 is Class){
382                         Class c = (Class) $1;
383                         mod_flags = c.ModFlags;
384                         name = c.Name;
385                 } else if ($1 is Struct){
386                         Struct s = (Struct) $1;
387                         mod_flags = s.ModFlags;
388                         name = s.Name;
389                 } else if ($1 is Module){
390                         Module m = (Module) $1;
391                         mod_flags = m.ModFlags;
392                         name = m.Name;                  
393                 } else
394                         break;
395
396                 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
397                         Report.Error (
398                                 1527, lexer.Location, 
399                                 "Namespace elements cannot be explicitly " +
400                                 "declared private or protected in '" + name + "'");
401                 }
402           }
403         ;
404
405 qualified_identifier
406         : IDENTIFIER
407         | qualified_identifier DOT IDENTIFIER 
408           { 
409             $$ = (($1).ToString ()) + "." + ($3.ToString ()); 
410           }
411         ;
412 opt_imports_directives
413         : /* empty */
414         | imports_directives
415         ;
416
417 imports_directives
418         : imports_directive 
419         | imports_directives imports_directive 
420         ;
421
422 imports_directive
423         : /* imports_alias_directive
424         | */ imports_namespace_directive
425         ;
426
427 imports_namespace_directive
428         : IMPORTS qualified_identifier EOL 
429           {
430                 current_namespace.Using ((string) $2, lexer.Location);
431           }
432         ;
433
434 opt_attributes
435         : /* empty */
436         | OP_LT attribute_list OP_GT
437         ; 
438
439 attribute_list
440         : attribute 
441         | attribute_list COMMA attribute
442         ;
443         
444 attribute 
445         : IDENTIFIER
446         ;
447                 
448 namespace_declaration
449         : NAMESPACE qualified_identifier EOL
450           {
451                 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$2);
452           } 
453           opt_imports_directives
454           opt_declarations
455           END NAMESPACE EOL
456           { 
457                 current_namespace = current_namespace.Parent;
458           }
459         ;
460
461 type_declaration
462         : opt_attributes
463           opt_modifiers
464            { 
465                 current_attributes = (Attributes) $1;
466                 current_modifiers = (int) $2; 
467            }      
468           type_spec_declaration
469         ;
470
471 type_spec_declaration
472         : class_declaration
473         | module_declaration
474 //      | struct_declaration            
475 //      | interface_declaration         
476 //      | enum_declaration              
477         | delegate_declaration
478         ;
479         
480 class_declaration
481         : CLASS IDENTIFIER EOL opt_class_base 
482           {
483                 Class new_class;
484                 string name;
485                 
486                 name = MakeName ((string) $2);
487
488                 new_class = new Class (current_container, name, current_modifiers, 
489                                        (Attributes) current_attributes, lexer.Location);
490
491                 current_container = new_class;
492                 current_container.Namespace = current_namespace;
493                 RootContext.Tree.RecordDecl (name, new_class);
494           }
495           opt_class_member_declarations
496           END CLASS EOL
497           {
498                 Class new_class = (Class) current_container;
499                 new_class.Bases = (ArrayList) $4;       
500         
501                 current_container = current_container.Parent;
502                 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
503
504                 $$ = new_class;
505           }
506         ;
507
508 opt_class_base
509         : /* empty */           { $$ = null; }
510         | class_base            { $$ = $1; }
511         ;
512
513 class_base
514         : INHERITS type_list EOL { $$ = $2; }
515         ;
516         
517 opt_modifiers
518         : /* empty */           { $$ = (int) 0; current_modifiers = 0; }
519         | modifiers             { $$ = $1; current_modifiers = (int) $1; }
520         ;
521
522 modifiers
523         : modifier
524         | modifiers modifier
525           { 
526                 int m1 = (int) $1;
527                 int m2 = (int) $2;
528
529                 if ((m1 & m2) != 0) {
530                         Location l = lexer.Location;
531                         Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
532                 }
533                 $$ = (int) (m1 | m2);
534           }
535         ;
536
537 modifier
538         : PUBLIC                { $$ = Modifiers.PUBLIC; }
539         | PROTECTED             { $$ = Modifiers.PROTECTED; }
540         | PRIVATE               { $$ = Modifiers.PRIVATE; }
541         | STATIC                { $$ = Modifiers.STATIC; }
542         /* FIXME: FRIEND and PROTECTED FRIEND are missing */
543         ;
544
545 module_declaration
546         : MODULE IDENTIFIER EOL
547           { 
548                 Module new_module;
549                 string name;
550                 // FIXME : Check for valid module modifiers
551                 name = MakeName((string) $2);
552                 new_module = new Module(current_container, 
553                                                                 name, 
554                                                                 current_modifiers, 
555                                                                 (Attributes) current_attributes,
556                                                                 lexer.Location);
557                 current_container = new_module;
558                 current_container.Namespace = current_namespace;
559                 RootContext.Tree.RecordDecl(name, new_module);
560           }
561           opt_class_member_declarations
562           END MODULE EOL
563           {
564                 Module new_module = (Module)current_container;
565
566                 current_container = current_container.Parent;
567                 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
568
569                 $$ = new_module;
570           }
571         ;
572
573 opt_class_member_declarations
574         : /* empty */
575         | class_member_declarations
576         ;
577
578 class_member_declarations
579         : class_member_declaration
580         | class_member_declarations class_member_declaration
581         ;
582
583 class_member_declaration
584         :  
585            opt_attributes
586            opt_modifiers
587            { 
588                 current_attributes = (Attributes) $1;
589                 current_modifiers = (int) $2; 
590            }
591            class_member_declarator
592            {
593                 $$ = $3;
594            }
595         ;
596
597 class_member_declarator
598         :       
599            constructor_declaration
600         |  method_declaration
601            { 
602                 Method method = (Method) $1;
603                 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
604            }    
605         |  field_declaration
606         |  property_declaration                 
607 //      |  event_declaration    
608         |  withevents_declaration       /* This is a field but must be treated specially, see below */
609         |  type_declaration                     
610         ;
611         
612         
613 method_declaration
614         : sub_declaration
615         | func_declaration 
616         ;
617         
618 sub_declaration
619         : SUB IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler EOL
620           { 
621                 
622                 current_local_parameters = (Parameters) $4;
623                 start_block(); 
624           } 
625           opt_local_declarations 
626           {     
627                 /* This is WEIRD: declaring a method (sub) in a module as static will
628                    trigger a syntax error, but the same methods MUST be static in order
629                    to be properly called
630                 */
631                 if (current_container is Module) {
632                         if (current_modifiers == Modifiers.STATIC) {
633                                 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
634                         }
635                         else
636                         {
637                                 current_modifiers = Modifiers.STATIC;
638                         }
639                 }
640           }
641           opt_statement_list 
642           END SUB EOL
643           {
644                 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
645                                             (Parameters) current_local_parameters, null, lexer.Location);
646         
647                 method.Block = (Block) end_block();
648                 $$ = method;
649
650                 if ($6 != null) { /* we have an event handler to take care of */
651                         // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
652                         string evt_def = ((MemberAccess)$6).ToString();
653                         int pos = evt_def.LastIndexOf (".");
654                         string evt_target = ((string) $2).Substring (0, pos);
655
656                         foreach (Property p in current_container.Properties) {
657                                 if (p.Name == evt_target) {
658                                         // FIXME: See below 
659                                         // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
660                                         AddHandler (p.Set.Block, (Expression)$6, (string) $2);
661                                         break;
662                                 }
663                         }
664                                                         
665                                                         
666                 }       
667           }       
668         ;
669         
670 func_declaration
671         : FUNCTION IDENTIFIER 
672           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type EOL
673           { 
674                 
675                 current_local_parameters = (Parameters) $4;
676                 start_block(); 
677           } 
678           opt_local_declarations 
679           {     
680                 /* This is WEIRD: declaring a method (sub) in a module as static will
681                    trigger a syntax error, but the same methods MUST be static in order
682                    to be properly called
683                 */
684                 if (current_container is Module) {
685                         if (current_modifiers == Modifiers.STATIC) {
686                                 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
687                         }
688                         else
689                         {
690                                 current_modifiers = Modifiers.STATIC;
691                         }
692                 }
693                 // Add local var declaration
694                 // for return value
695                 ArrayList retval = new ArrayList ();
696                 retval.Add (new VariableDeclaration ((string) $2, null, lexer.Location));
697                 declare_local_variables ((Expression) $7, retval, lexer.Location);
698           }       
699           opt_statement_list
700           END FUNCTION EOL
701           {
702                 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
703                                             (Parameters) current_local_parameters, null, lexer.Location);
704         
705                 method.Block = end_block();
706                 $$ = method;
707
708           }       
709         ;               
710         
711 property_declaration
712           : PROPERTY IDENTIFIER opt_property_parameters AS type EOL
713           {
714                 get_implicit_value_parameter_type = (Expression) $5;
715                 get_implicit_value_parameter_name = (string) $2;
716                 
717                 current_local_parameters = (Parameters) $3;
718                 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
719                         get_parameters = current_local_parameters.Copy (lexer.Location);
720                         set_parameters = current_local_parameters.Copy (lexer.Location);
721                 }
722                 else
723                 {
724                         get_parameters = Parameters.EmptyReadOnlyParameters;
725                         set_parameters = new Parameters (null, null ,lexer.Location);           
726                 }
727                 lexer.PropertyParsing = true;
728
729                 $$ = lexer.Location;
730           }
731           accessor_declarations 
732           END PROPERTY EOL
733           {
734                 lexer.PropertyParsing = false;
735
736                 Property prop;
737                 Pair pair = (Pair) $8;
738                 Accessor get_block = (Accessor) pair.First;
739                 Accessor set_block = (Accessor) pair.Second;
740                 Location loc = lexer.Location;
741                 
742                 prop = new Property ((Expression) $5, (string) $2, current_modifiers, get_block, set_block,
743                                      current_attributes, loc, set_implicit_value_parameter_name, 
744                                      get_parameters, set_parameters);
745                 
746                 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
747                 get_implicit_value_parameter_type = null;
748                 set_implicit_value_parameter_type = null;
749                 get_parameters = null;
750                 set_parameters = null;
751                 current_local_parameters = null;
752           }
753         ;
754
755 opt_property_parameters
756         : /* empty */
757           {
758                 $$ = Parameters.EmptyReadOnlyParameters; ;
759           }
760         | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
761           {
762                 $$ = $2;
763           }
764         ;
765         
766 accessor_declarations
767         : get_accessor_declaration opt_set_accessor_declaration
768           { 
769                 $$ = new Pair ($1, $2);
770           }
771         | set_accessor_declaration opt_get_accessor_declaration
772           {
773                 $$ = new Pair ($2, $1);
774           }
775         ;
776
777 opt_get_accessor_declaration
778         : /* empty */                   { $$ = null; }
779         | get_accessor_declaration
780         ;
781
782 opt_set_accessor_declaration
783         : /* empty */                   { $$ = null; }
784         | set_accessor_declaration
785         ;
786
787 get_accessor_declaration
788         : opt_attributes GET EOL
789           {
790                 current_local_parameters = get_parameters;
791                 
792                 lexer.PropertyParsing = false;
793                 
794                 start_block();  
795                 // Add local var declaration
796                 // for return value
797                 ArrayList retval = new ArrayList ();
798                 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, null, lexer.Location));
799                 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);    
800                 
801           }
802           opt_statement_list
803           END GET EOL
804           {
805                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
806                 current_local_parameters = null;
807                 lexer.PropertyParsing = true;
808           }
809         ;
810
811 set_accessor_declaration
812         : opt_attributes SET opt_set_parameter EOL
813           {
814                 
815                 Parameter implicit_value_parameter = new Parameter (
816                         set_implicit_value_parameter_type, 
817                         set_implicit_value_parameter_name, 
818                         Parameter.Modifier.NONE, null);
819
820                 current_local_parameters = set_parameters;
821                 current_local_parameters.AppendParameter (implicit_value_parameter);
822                 
823                 start_block();
824                 lexer.PropertyParsing = false;
825           }
826           opt_statement_list
827           END SET EOL
828           {
829                 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
830                 current_local_parameters = null;
831                 lexer.PropertyParsing = true;
832           }
833         ;
834                 
835 opt_set_parameter
836         : /* empty */
837         {
838                 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
839                 set_implicit_value_parameter_name = "Value";
840         }       
841         | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
842         {
843                 /* FIXME: possible syntax error which must be caught
844                    Set ( As <type>) is currently (and wrongly so) legal
845                 */
846                 set_implicit_value_parameter_type = (Expression) $3;
847                 if ($2 != null)
848                         set_implicit_value_parameter_name = (string) $2;
849                 else
850                         set_implicit_value_parameter_name = "Value";
851         }
852         ;
853                         
854 field_declaration
855         : opt_dim_stmt 
856           variable_declarators EOL
857           {               
858                 int mod = (int) current_modifiers;
859                 
860
861                 VariableDeclaration.FixupTypes ((ArrayList) $2);
862                 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
863                 
864                 if (current_container is Module)
865                         mod = mod | Modifiers.STATIC;
866                                         
867                 foreach (VariableDeclaration var in (ArrayList) $2){
868                         Location l = var.Location;
869
870                         Field field = new Field (var.type, mod, var.identifier, 
871                                                  var.expression_or_array_initializer, 
872                                                  (Attributes) null, l);
873
874                         CheckDef (current_container.AddField (field), field.Name, l);
875                 }
876           }
877         ;
878         
879 withevents_declaration
880         : WITHEVENTS variable_declarators EOL
881           {
882                 /* WithEvents Fields must be resolved into properties
883                    with a bit of magic behind the scenes */
884                   
885                 VariableDeclaration.FixupTypes ((ArrayList) $2);
886                 
887                 foreach (VariableDeclaration var in (ArrayList) $2) {
888                         // 1 - We create a private field
889                         Location l = var.Location;
890                         Property prop;
891                         if ((current_modifiers & Modifiers.STATIC) > 0) 
892                                 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
893                         
894                         Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, 
895                                                  var.expression_or_array_initializer, 
896                                                  (Attributes) null, l);
897
898                         CheckDef (current_container.AddField (field), field.Name, l);   
899                         
900                         // 2 - Public property
901                                 
902                         prop = BuildSimpleProperty (var.type, (string) var.identifier, 
903                                                 field, (int) current_modifiers, 
904                                                 (Attributes) current_attributes, l);
905                         
906                         CheckDef (current_container.AddProperty (prop), prop.Name, l);
907                 }               
908           }
909         ;
910         
911 opt_dim_stmt 
912         : /* empty */
913         | DIM
914         ; 
915                 
916 delegate_declaration
917         : DELEGATE SUB  
918           IDENTIFIER OPEN_PARENS 
919           opt_formal_parameter_list
920           CLOSE_PARENS 
921           EOL
922           {
923                 Location l = lexer.Location;
924                 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr, 
925                                              (int) current_modifiers, 
926                                              MakeName ((string) $3), (Parameters) $5, 
927                                              (Attributes) current_attributes, l);
928                                                   
929                 del.Namespace = current_namespace;
930                 CheckDef (current_container.AddDelegate (del), del.Name, l);
931           }     
932         | DELEGATE FUNCTION       
933           IDENTIFIER OPEN_PARENS 
934           opt_formal_parameter_list
935           CLOSE_PARENS AS type
936           {
937                 Location l = lexer.Location;
938                 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
939                         current_container,
940                         (Expression) $8, (int) current_modifiers, MakeName ((string) $3), 
941                         (Parameters) $5, (Attributes) current_attributes, l);
942
943                 del.Namespace = current_namespace;
944                 CheckDef (current_container.AddDelegate (del), del.Name, l);
945           }
946         ;
947         
948 opt_evt_handler
949         : /* empty */
950         {       $$ = null; }
951         | HANDLES qualified_identifier
952         {
953                 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);     
954         }
955         ;       
956         
957 constructor_declaration
958         : constructor_declarator
959           opt_local_declarations
960           opt_statement_list
961           { 
962                 Constructor c = (Constructor) $1;
963                 c.Block = (Block) end_block();
964                 c.ModFlags = (int) current_modifiers;
965                 c.OptAttributes = (Attributes) null;
966                 
967                 CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
968                 current_local_parameters = null;
969           }
970           END SUB EOL
971         ;
972
973 constructor_declarator
974         : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
975           {
976                 current_local_parameters = (Parameters) $4;
977                 start_block();
978                 oob_stack.Push (lexer.Location);
979
980                 Location l = (Location) oob_stack.Pop ();
981                 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
982           }
983         ;
984         
985         
986 opt_formal_parameter_list
987         : /* empty */                   
988           { 
989                 $$ = Parameters.EmptyReadOnlyParameters; 
990           }
991         | formal_parameter_list 
992           { 
993                 $$ = $1;        
994                 //Parameter p = ((Parameters) $1).FixedParameters[0];
995           }
996         ;
997         
998 formal_parameter_list
999         : fixed_parameters              
1000           { 
1001                 ArrayList pars_list = (ArrayList) $1;
1002
1003                 Parameter [] pars = new Parameter [pars_list.Count];
1004                 pars_list.CopyTo (pars);
1005                 $$ = new Parameters (pars, null, lexer.Location); 
1006           } 
1007         | fixed_parameters COMMA parameter_array
1008           {
1009                 ArrayList pars_list = (ArrayList) $1;
1010
1011                 Parameter [] pars = new Parameter [pars_list.Count];
1012                 pars_list.CopyTo (pars);
1013
1014                 $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
1015           }
1016         | parameter_array 
1017           {
1018                 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1019           }
1020         ;
1021
1022 fixed_parameters
1023         : fixed_parameter       
1024           {
1025                 ArrayList pars = new ArrayList ();
1026
1027                 pars.Add ($1);
1028                 $$ = pars;
1029           }
1030         | fixed_parameters COMMA fixed_parameter
1031           {
1032                 ArrayList pars = (ArrayList) $1;
1033
1034                 pars.Add ($3);
1035                 $$ = $1;
1036           }
1037         ;
1038
1039 fixed_parameter
1040         : opt_attributes
1041           opt_parameter_modifier
1042           IDENTIFIER opt_type_spec opt_variable_initializer
1043           {
1044                 Parameter.Modifier pm = (Parameter.Modifier)$2;
1045                 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1046                 
1047                 if (opt_parm && ($5 == null))
1048                         Report.Error (999, "Optional parameters must have a default value");
1049                 
1050                 if (opt_parm)
1051                         pm = Parameter.Modifier.NONE;   //FIXME: should take into account BYREF
1052                         
1053                 $$ = new Parameter ((Expression) $4, (string) $3, 
1054                                         pm, (Attributes) $1, (Expression) $5, opt_parm);
1055           }
1056         ;
1057         
1058 parameter_array
1059         : PARAM_ARRAY IDENTIFIER opt_parens AS type 
1060           { 
1061                 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1062                 // note  ("type must be a single-dimension array type"); 
1063           }
1064         ;
1065                 
1066 opt_parens
1067         : /* empty */
1068         | OPEN_PARENS CLOSE_PARENS
1069         ;
1070                         
1071 opt_type_spec
1072         : /* empty */   { $$ = (Expression) TypeManager.system_object_expr; }
1073         | AS type       { $$ = (Expression) $2; };
1074         ;
1075         
1076 opt_parameter_modifier
1077         : /* empty */           { $$ = Parameter.Modifier.VAL;  }
1078         | parameter_modifiers   { $$ = $1;                      }
1079         ;
1080
1081 parameter_modifiers
1082         : parameter_modifiers parameter_modifier        { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1083         | parameter_modifier                            { $$ = $1;      }
1084         ;
1085         
1086 parameter_modifier
1087         : BYREF                 { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1088         | BYVAL                 { $$ = Parameter.Modifier.VAL; }
1089         | OPTIONAL              { $$ = Parameter.Modifier.OPTIONAL; } 
1090         ;       
1091
1092 opt_actual_parameters 
1093         : /* empty */
1094         | qualified_identifier
1095         | LITERAL_STRING
1096         ;
1097
1098 opt_statement_list
1099         : /* empty */
1100         | statement_list EOL
1101         ;
1102
1103 statement_list
1104         : statement 
1105         | statement_list EOL statement
1106         ;
1107         
1108 statement : embedded_statement 
1109           {
1110                 Statement s = (Statement) $1;
1111
1112                 current_block.AddStatement ((Statement) $1);
1113           } 
1114           | labeled_statement EOL
1115           | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1116            {
1117                 AddHandler ((Expression) $2, (string) $5);
1118            }
1119           ;     
1120           
1121
1122 labeled_statement
1123         : IDENTIFIER COLON 
1124           {
1125                 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1126
1127                 if (!current_block.AddLabel ((string) $1, labeled)){
1128                         Location l = lexer.Location;
1129                         Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1130                 }       
1131                 current_block.AddStatement (labeled);
1132           }
1133           statement
1134         ;
1135
1136 embedded_statement
1137         : expression_statement
1138         | selection_statement
1139         | iteration_statement
1140         | try_statement
1141         | jump_statement 
1142         ;
1143         
1144 jump_statement
1145         : /*break_statement
1146         | continue_statement
1147         | goto_statement
1148         | throw_statement
1149         | */return_statement
1150         | exit_statement
1151         ;
1152                 
1153 exit_statement
1154         : EXIT exit_type
1155           {
1156                 $$ = new Exit ((ExitType)$2, lexer.Location);           
1157           }
1158         ;
1159         
1160 exit_type
1161         : DO            { $$ = ExitType.DO;             }
1162         | FOR           { $$ = ExitType.FOR;            }
1163         | WHILE         { $$ = ExitType.WHILE;          }
1164         | SELECT        { $$ = ExitType.SELECT;         }
1165         | SUB           { $$ = ExitType.SUB;            }
1166         | FUNCTION      { $$ = ExitType.FUNCTION;       }
1167         | PROPERTY      { $$ = ExitType.PROPERTY;       }
1168         | TRY           { $$ = ExitType.TRY;            }
1169         ;
1170 return_statement
1171         : RETURN opt_expression 
1172           {       
1173                 $$ = new Return ((Expression) $2, lexer.Location);
1174           }
1175         ;
1176                 
1177 iteration_statement
1178         : while_statement
1179         | do_statement
1180         | for_statement
1181         /*| foreach_statement*/
1182         ;
1183
1184 try_statement
1185         : try_catch
1186         | try_catch_finally
1187         ;
1188                                 
1189 try_catch
1190         : try_header 
1191           END TRY
1192           { 
1193                 Catch g = null;
1194                 ArrayList s = new ArrayList ();
1195
1196                 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
1197                         if (cc.IsGeneral)
1198                                 g = cc;
1199                         else
1200                                 s.Add (cc);
1201                 }
1202
1203                 // Now s contains the list of specific catch clauses
1204                 // and g contains the general one.
1205                 Block b = end_block();
1206
1207                 $$ = new Try ((Block) b, s, g, null, lexer.Location);
1208           }       
1209         ;       
1210           
1211 try_catch_finally
1212         : try_header 
1213           { 
1214                 tmp_block = end_block(); 
1215           }     
1216           FINALLY EOL
1217           { 
1218                 start_block(); 
1219           }       
1220           opt_statement_list 
1221           END TRY
1222           {
1223                 Catch g = null;
1224                 ArrayList s = new ArrayList ();
1225                 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
1226
1227                 if (catch_list != null){
1228                         foreach (Catch cc in catch_list) {
1229                                 if (cc.IsGeneral)
1230                                         g = cc;
1231                                 else
1232                                         s.Add (cc);
1233                         }
1234                 }
1235
1236                 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
1237         
1238           }     
1239           ;       
1240         
1241 try_header
1242         : TRY EOL
1243           {   Console.WriteLine ("try_header");
1244                 start_block();  
1245           }
1246           opt_statement_list 
1247           opt_catch_clauses
1248           {
1249                 tmp_catch_clauses = (ArrayList) $5;
1250           }
1251         ;       
1252
1253 opt_catch_clauses
1254         : /* empty */  {  $$ = null;  }
1255         | catch_clauses
1256         ;
1257
1258 catch_clauses
1259         : catch_clause 
1260           {
1261                 ArrayList l = new ArrayList ();
1262
1263                 l.Add ($1);
1264                 $$ = l;
1265           }
1266         | catch_clauses catch_clause
1267           {
1268                 ArrayList l = (ArrayList) $1;
1269
1270                 l.Add ($2);
1271                 $$ = l;
1272           }
1273         ;
1274
1275 opt_identifier
1276         : /* empty */   {  $$ = null;  }
1277         | IDENTIFIER
1278         ;
1279
1280 catch_clause 
1281         : CATCH opt_catch_args EOL
1282         {
1283                 Expression type = null;
1284                 string id = null;
1285                 
1286                 if ($2 != null) {
1287                         DictionaryEntry cc = (DictionaryEntry) $2;
1288                         type = (Expression) cc.Key;
1289                         id   = (string) cc.Value;
1290                         
1291                         if (id != null){
1292                                 ArrayList one = new ArrayList ();
1293                                 Location loc = lexer.Location;
1294
1295                                 one.Add (new VariableDeclaration (id, null, loc));
1296
1297
1298                                 $1 = current_block;
1299                                 current_block = new Block (current_block);
1300                                 Block b = declare_local_variables (type, one, loc);
1301                                 current_block = b;
1302                         }
1303                 }
1304         
1305         } 
1306         opt_statement_list {
1307                 Expression type = null;
1308                 string id = null;
1309                 Block b_catch = current_block;
1310                 
1311                 if ($2 != null){
1312                         DictionaryEntry cc = (DictionaryEntry) $2;
1313                         type = (Expression) cc.Key;
1314                         id   = (string) cc.Value;
1315                         
1316                         if ($1 != null) {
1317                                 //
1318                                 // FIXME: I can change this for an assignment.
1319                                 //
1320                                 while (current_block != (Block) $1)
1321                                         current_block = current_block.Parent;
1322                         }
1323                 }
1324
1325                 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
1326         }
1327         ;
1328
1329 opt_catch_args
1330         : /* empty */ {  $$ = null; }
1331         | catch_args
1332         ;         
1333
1334 catch_args 
1335         : IDENTIFIER AS type
1336         {
1337                  $$ = new DictionaryEntry ($3, $1); 
1338         }
1339         ;
1340         
1341         
1342 do_statement
1343         : DO opt_do_construct EOL
1344           {
1345                 start_block();
1346                 oob_stack.Push (lexer.Location);
1347           }     
1348           opt_statement_list
1349           LOOP opt_do_construct
1350           {
1351                 Expression t_before = (Expression) $2;
1352                 Expression t_after = (Expression) $7;
1353                 Expression t;
1354
1355                 if  ((t_before != null) && (t_after != null))
1356                         Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
1357
1358                 if ((t_before == null) && (t_after == null))
1359                         t = new BoolLiteral (true);
1360                 else
1361                         t = (t_before != null) ? t_before : t_after;
1362                         
1363                 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
1364                 
1365                 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
1366                     ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
1367                          t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
1368                          
1369                 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
1370           }
1371           ;
1372
1373 opt_do_construct
1374         : /* empty */ { $$ = null; }
1375         | while_or_until boolean_expression
1376           {
1377                 do_type = (DoOptions)$1;
1378                 $$ = (Expression) $2;
1379           }
1380         ;
1381
1382 while_or_until
1383         : WHILE { $$ = DoOptions.WHILE; }
1384         | UNTIL { $$ = DoOptions.UNTIL; }
1385         ;
1386
1387 while_statement
1388         : WHILE
1389         {
1390                 start_block();
1391                 oob_stack.Push (lexer.Location);
1392         }
1393         boolean_expression EOL
1394         opt_statement_list
1395         END WHILE
1396         {
1397                 Location l = (Location) oob_stack.Pop ();
1398                 Block b = end_block();
1399                 Expression e = (Expression) $3;
1400                 $$ = new While ((Expression) e, (Statement) b, l);
1401         }
1402         ;
1403         
1404                 
1405 for_statement
1406         : FOR qualified_identifier ASSIGN expression TO expression opt_step EOL
1407           {
1408                 start_block();
1409           }
1410           opt_statement_list
1411           NEXT opt_next_identifier 
1412           {
1413                 Block statement = end_block();
1414                 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
1415                 
1416                 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
1417                 Expression test_expr =  new Binary (Binary.Operator.LessThanOrEqual,
1418                                                 for_var, (Expression) $6, lexer.Location);
1419                 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
1420                                  for_var, (Expression) $7, lexer.Location), lexer.Location);
1421                                  
1422                 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);                     
1423                 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
1424                 
1425                 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);            
1426           }       
1427         ;
1428
1429 opt_step
1430         : /* empty */           { $$ = new IntLiteral ((Int32) 1); }
1431         | STEP expression       { $$ = $2; }
1432         ;
1433
1434 opt_next_identifier
1435         : /* empty */
1436         | qualified_identifier
1437         ;
1438
1439 selection_statement
1440         : if_statement
1441         | select_statement
1442         ;
1443
1444 if_statement
1445         : if_statement_open if_statement_rest
1446           {
1447                 $$ = $2;
1448           }
1449         ;
1450         
1451 if_statement_open
1452         : IF boolean_expression THEN EOL 
1453           {
1454                 oob_stack.Push (lexer.Location);
1455                 start_block();
1456                 tmp_expr = (Expression) $2;
1457           }
1458          ;
1459
1460 if_statement_rest
1461         :         
1462           opt_statement_list
1463           END IF
1464           { 
1465                 Location l = (Location) oob_stack.Pop ();
1466
1467                 $$ = new If ((Expression) tmp_expr, (Statement) end_block(), l);
1468
1469           }       
1470         |
1471           opt_statement_list
1472           ELSE EOL 
1473           { 
1474                 tmp_block = end_block();
1475                 start_block();
1476           }
1477           opt_statement_list
1478           END IF        
1479           {
1480                 Location l = (Location) oob_stack.Pop ();
1481
1482                 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
1483           }        
1484         ;
1485         
1486 select_statement
1487         : SELECT opt_case expression EOL
1488           { 
1489                 oob_stack.Push (lexer.Location);
1490                 switch_stack.Push (current_block);
1491           }     
1492           opt_case_sections
1493           END SELECT 
1494           {
1495                 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
1496                 current_block = (Block) switch_stack.Pop ();
1497           }       
1498         ;
1499
1500 opt_case_sections
1501         : /* empty */   { $$ = null; }
1502         | case_sections { $$ = $1; }
1503         ;
1504         
1505 case_sections
1506         : case_sections case_section
1507           {
1508                 ArrayList sections = (ArrayList) $1;
1509
1510                 sections.Add ($2);
1511                 $$ = sections;
1512           }
1513         | case_section
1514           {
1515                 ArrayList sections = new ArrayList ();
1516
1517                 sections.Add ($1);
1518                 $$ = sections;
1519           }
1520         ;
1521
1522 case_section
1523         : CASE case_clauses EOL
1524           { 
1525                 start_block();
1526           }
1527           opt_statement_list
1528           {
1529                 Block topmost = current_block;
1530
1531                 while (topmost.Implicit)
1532                         topmost = topmost.Parent;
1533                         
1534                 // FIXME: This is a horrible hack which MUST go                 
1535                 topmost.statements.Add (new Break (lexer.Location));
1536                 $$ = new SwitchSection ((ArrayList) $2, topmost);
1537           }
1538           | CASE ELSE EOL
1539             /* FIXME: we should somehow flag an error 
1540                (BC30321 'Case' cannot follow a 'Case Else' 
1541                in the same 'Select' statement.) 
1542                if Case Else is not the last of the Case clauses
1543             */
1544           { 
1545                 start_block();
1546           }     
1547           opt_statement_list
1548           { 
1549                 Block topmost = current_block;
1550
1551                 while (topmost.Implicit)
1552                         topmost = topmost.Parent;
1553                         
1554                 // FIXME: This is a horrible hack which MUST go                 
1555                 topmost.statements.Add (new Break (lexer.Location));
1556                 
1557                 ArrayList a = new ArrayList();
1558                 a.Add (new SwitchLabel (null, lexer.Location));                 
1559                 $$ = new SwitchSection ((ArrayList) a, topmost);                
1560           }
1561         ;         
1562         
1563 case_clauses
1564         : case_clause
1565           {
1566                 ArrayList labels = new ArrayList ();
1567
1568                 labels.Add ($1);
1569                 $$ = labels;
1570           }     
1571         | case_clauses COMMA case_clause
1572           {
1573                 ArrayList labels = (ArrayList) ($1);
1574                 labels.Add ($2);
1575
1576                 $$ = labels;
1577           }     
1578         ;
1579         
1580 case_clause
1581         : opt_is comparison_operator expression
1582         | expression
1583           {
1584                 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
1585           }
1586         ;
1587         
1588 opt_is 
1589         : /* empty */
1590         | IS
1591         ;
1592
1593 comparison_operator
1594         : OP_LT
1595         | OP_GT
1596         | OP_LT
1597         | OP_LE
1598         | OP_NE
1599         | OP_EQ
1600         ;
1601
1602 opt_case
1603         : /* empty */
1604         | CASE
1605         ;
1606
1607 expression_statement
1608         : statement_expression 
1609           {
1610                  $$ = $1; 
1611           }
1612         ;
1613
1614 statement_expression
1615         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
1616         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
1617         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location);  }
1618         ;
1619
1620 object_creation_expression
1621         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
1622           {
1623                 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);  
1624           }
1625         ;
1626
1627 new_expression
1628         : object_creation_expression
1629         /* | array_creation_expression */
1630         ;
1631
1632 assignment_expression
1633         : prefixed_unary_expression ASSIGN expression
1634           {
1635                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location); 
1636           }
1637         ;
1638
1639 opt_local_declarations
1640         : /* empty */
1641         | local_declarations
1642         {       if ($1 != null && (Block) $1 != current_block){
1643                         current_block.AddStatement ((Statement) $1);
1644                         current_block = (Block) $1;
1645                 }
1646         }
1647         ;
1648         
1649 local_declarations
1650         : local_declaration EOL
1651         | local_declaration EOL local_declarations
1652         ;
1653         
1654 local_declaration
1655         : local_variable_declaration 
1656           {
1657                 if ($1 != null){
1658                         DictionaryEntry de = (DictionaryEntry) $1;
1659
1660                         $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
1661                 }
1662           }
1663
1664         | local_constant_declaration 
1665           {
1666                 if ($1 != null){
1667                         DictionaryEntry de = (DictionaryEntry) $1;
1668
1669                         $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
1670                 }
1671           }
1672         ;        
1673         
1674 local_variable_declaration
1675         : DIM variable_declarators
1676           {
1677                 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);             
1678           }
1679         | DIM variable_declarators 
1680           {
1681                 $$ = new DictionaryEntry (TypeManager.system_object_expr, $2);
1682           }
1683         /*| DIM variable_declarators AS object_creation_expression
1684           {
1685                 if ($4 != null)
1686                         $$ = new DictionaryEntry ($4, $2);
1687                 else
1688                         $$ = null;
1689                                                 
1690           } */
1691         ;
1692
1693         
1694 local_constant_declaration
1695         : CONST constant_declarator
1696           {
1697                 if ($2 != null)
1698                         $$ = new DictionaryEntry ($1, $2);
1699                 else
1700                         $$ = null;
1701           }
1702         ;        
1703         
1704 constant_declarator
1705         : IDENTIFIER ASSIGN constant_expression
1706           {
1707                 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
1708           }
1709         ;               
1710
1711 variable_declarators
1712         : variable_declarator 
1713           {
1714                 ArrayList decl = new ArrayList ();
1715                 decl.Add ($1);
1716                 $$ = decl;
1717           }
1718         | variable_declarators COMMA variable_declarator
1719           {
1720                 ArrayList decls = (ArrayList) $1;
1721                 decls.Add ($3);
1722                 $$ = $1;
1723           }
1724         ;
1725
1726 variable_declarator
1727         : variable_identifier opt_type_decl opt_variable_initializer
1728           {
1729                 string varname = (string)$1;
1730                 string dims = "";
1731                 Expression vartype = (Expression) $2;
1732                 Expression varinit = (Expression) $3;
1733                 /*
1734                    Check for a declaration like Dim a(2) or Dim a(2,3)
1735                    If this is the case, we must generate an ArrayCreationExpression
1736                    and, in case, add the initializer after the array has been created.
1737                 */
1738                 if (VariableDeclaration.IsArrayDecl (varname)) {
1739                         if (VariableDeclaration.HasDimBounds(varname)) { 
1740                                 varname = VariableDeclaration.StripDims (varname, ref dims);
1741                                 ArrayList a_dims = VariableDeclaration.ParseDims(dims);
1742                                 varinit = new ArrayCreation (vartype, a_dims,"", null, lexer.Location);
1743                         }
1744                         vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.GetRank (dims), lexer.Location);
1745                 }
1746                 
1747                 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
1748           }
1749         ;
1750
1751 variable_identifier
1752         : IDENTIFIER opt_array_name_modifier 
1753           {
1754                 $$ = $1; 
1755                 if ($2 != null)
1756                         $$ = (string)$$ + (string)$2;
1757           }
1758         ;               
1759         
1760 opt_type_decl
1761         : /* empty */   
1762           {
1763                 $$ =  null;
1764           }
1765         | AS type opt_argument_list /* FIXME must handle argument list*/
1766           {
1767                 $$ = $2;
1768           }
1769         | AS NEW type opt_argument_list /* FIXME must handle NEW clause + argument list */
1770           {
1771                 $$ = $3;
1772           }
1773         ;
1774                 
1775 opt_array_name_modifier
1776         : /* empty */                           { $$ = null; }
1777         | array_type_modifier                   { $$ = $1;   } 
1778         | array_initialization_modifier 
1779         ;
1780         
1781 array_type_modifier
1782         : rank_specifiers  { $$ = $1; }
1783         ;
1784         
1785 opt_dim_separators
1786         : /* empty */
1787           {
1788                 $$ = "";
1789           }
1790         | dim_separators
1791           {
1792                   $$ = $1;
1793           }               
1794         ;
1795         
1796 dim_separators
1797         : COMMA
1798           {
1799                 $$ = ",";
1800           }
1801         | dim_separators COMMA
1802           {
1803                 $$ = (string) $1 + ",";
1804           }
1805         ;       
1806                 
1807 opt_variable_initializer
1808         : /* empty */                   { $$ = null; }
1809         | ASSIGN variable_initializer   { $$ = $2; }
1810         ;
1811         
1812 array_initialization_modifier
1813         : /* empty */ { $$ = null; }
1814         ;       
1815                 
1816 variable_initializer
1817         : expression
1818           {
1819                 $$ = $1;
1820           }
1821         /*| array_initializer
1822           {
1823                 $$ = $1;
1824           }
1825         */
1826         ;       
1827                 
1828 /* 
1829  * The following is from Rhys' grammar:
1830  * > Types in local variable declarations must be recognized as 
1831  * > expressions to prevent reduce/reduce errors in the grammar.
1832  * > The expressions are converted into types during semantic analysis.
1833  */
1834 local_variable_type
1835         : primary_expression opt_rank_specifier
1836           { 
1837                 // FIXME: Do something smart here regarding the composition of the type.
1838
1839                 // Ok, the above "primary_expression" is there to get rid of
1840                 // both reduce/reduce and shift/reduces in the grammar, it should
1841                 // really just be "type_name".  If you use type_name, a reduce/reduce
1842                 // creeps up.  If you use qualified_identifier (which is all we need
1843                 // really) two shift/reduces appear.
1844                 // 
1845
1846                 // So the super-trick is that primary_expression
1847                 // can only be either a SimpleName or a MemberAccess. 
1848                 // The MemberAccess case arises when you have a fully qualified type-name like :
1849                 // Foo.Bar.Blah i;
1850                 // SimpleName is when you have
1851                 // Blah i;
1852                   
1853                 Expression expr = (Expression) $1;  
1854                 if (!(expr is SimpleName || expr is MemberAccess)) {
1855                         Error_ExpectingTypeName (lexer.Location, expr);
1856                         $$ = null;
1857                 } else {
1858                         //
1859                         // So we extract the string corresponding to the SimpleName
1860                         // or MemberAccess
1861                         // 
1862                         if ((string) $2 == "")
1863                                 $$ = $1;
1864                         else
1865                                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1866                 }
1867           }
1868         | builtin_types opt_rank_specifier
1869           {
1870                 if ((string) $2 == "")
1871                         $$ = $1;
1872                 else
1873                         $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1874           }
1875         ;
1876                 
1877 rank_specifiers
1878         : rank_specifier
1879           {
1880                   $$ = $1;
1881           }
1882         | rank_specifiers rank_specifier
1883           {
1884                   $$ = (string) $2 + (string) $1;
1885           }             
1886         ;
1887
1888 rank_specifier
1889         : OPEN_PARENS opt_dim_separators CLOSE_PARENS
1890           {
1891                 $$ = "[" + (string) $2 + "]";
1892           }
1893         ;
1894                         
1895 opt_rank_specifier
1896         : /* empty */
1897           {
1898                   $$ = "";
1899           }
1900         | rank_specifiers
1901           {
1902                         $$ = $1;
1903           }
1904         ;               
1905         
1906 opt_dim_separators
1907         : /* empty */
1908           {
1909                 $$ = "";
1910           }
1911         | dim_separators
1912           {
1913                 $$ = $1;
1914           }     
1915         | dim_specifiers
1916           {
1917                 $$ = $1;
1918           }       
1919         ;
1920
1921 dim_separators
1922         : COMMA
1923           {
1924                 $$ = ",";
1925           }
1926         | dim_separators COMMA
1927           {
1928                 $$ = (string) $1 + ",";
1929           }
1930         ;
1931         
1932 dim_specifiers
1933         : integer_literal                       { $$ = ((IntLiteral)$1).AsString(); }
1934         | dim_specifiers COMMA integer_literal  { $$ = $1 + "," + ((IntLiteral)$3).AsString(); }
1935         ;
1936                 
1937 /* Expressions */
1938 primary_expression
1939         : literal
1940           {
1941                 // 7.5.1: Literals
1942           }
1943
1944         | qualified_identifier
1945           {
1946                 string name = (string) $1;
1947
1948                 $$ = null;
1949                 $$ = DecomposeQI (name, lexer.Location);
1950           }
1951         | parenthesized_expression
1952         | member_access
1953         | invocation_expression
1954         | element_access
1955         | this_access
1956         | base_access
1957         | new_expression
1958         ;
1959
1960 literal
1961         : boolean_literal
1962         | integer_literal
1963         | real_literal
1964         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
1965         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
1966         | NOTHING                       { $$ = NullLiteral.Null; }
1967         ;
1968
1969 real_literal
1970         : LITERAL_SINGLE        { $$ = new FloatLiteral ((float) lexer.Value); }
1971         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
1972         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1973         ;
1974
1975 integer_literal
1976         : LITERAL_INTEGER       {
1977                 object v = lexer.Value;
1978
1979                 if (v is int)
1980                         $$ = new IntLiteral ((Int32) v); 
1981                 else if (v is uint)
1982                         $$ = new UIntLiteral ((UInt32) v);
1983                 else if (v is long)
1984                         $$ = new LongLiteral ((Int64) v);
1985                 else if (v is ulong)
1986                         $$ = new ULongLiteral ((UInt64) v);
1987                 else
1988                         Console.WriteLine ("OOPS.  Unexpected result from scanner");
1989                         
1990           }
1991         ;
1992
1993 boolean_literal
1994         : TRUE                  { $$ = new BoolLiteral (true); }
1995         | FALSE                 { $$ = new BoolLiteral (false); }
1996         ;
1997
1998 parenthesized_expression
1999         : OPEN_PARENS expression CLOSE_PARENS
2000           { $$ = $2; }
2001         ;
2002
2003 member_access
2004         : primary_expression DOT IDENTIFIER
2005           {
2006                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2007           }
2008         | predefined_type DOT IDENTIFIER
2009           {
2010                 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2011           }
2012         ;
2013
2014 predefined_type
2015         : builtin_types
2016         ;
2017
2018 invocation_expression
2019         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2020           {
2021                 if ($1 == null) {
2022                         Location l = lexer.Location;
2023                         Report.Error (1, l, "THIS IS CRAZY");
2024                 }
2025                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2026           }
2027         ;
2028
2029 opt_argument_list
2030         : /* empty */           { $$ = null; }
2031         | argument_list
2032         ;
2033
2034 argument_list
2035         : argument
2036           {
2037                 ArrayList list = new ArrayList ();
2038                 list.Add ($1);
2039                 $$ = list;
2040           }
2041         | argument_list COMMA argument
2042           {
2043                 ArrayList list = (ArrayList) $1;
2044                 list.Add ($3);
2045                 $$ = list;
2046           }
2047         ;
2048
2049 argument
2050         : expression
2051           {
2052                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2053           }
2054         | BYREF variable_reference
2055           {
2056                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2057           }
2058         | /* empty */
2059           {
2060                 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
2061           }
2062         ;
2063
2064 variable_reference
2065         : expression {/* note ("section 5.4"); */  $$ = $1;  }
2066         ;
2067
2068 element_access
2069         : primary_expression OPEN_PARENS expression_list CLOSE_PARENS
2070           {
2071                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2072           }
2073         /*| primary_expression rank_specifiers
2074           {
2075                 // So the super-trick is that primary_expression
2076                 // can only be either a SimpleName or a MemberAccess.
2077                 // The MemberAccess case arises when you have a fully qualified type-name like :
2078                 // Foo.Bar.Blah i;
2079                 // SimpleName is when you have
2080                 // Blah i;
2081                 Expression expr = (Expression) $1;
2082                 
2083                 if (!(expr is SimpleName || expr is MemberAccess)) {
2084                         Error_ExpectingTypeName (lexer.Location, expr);
2085                         $$ = TypeManager.system_object_expr;
2086                 } else {
2087                         //
2088                         // So we extract the string corresponding to the SimpleName
2089                         // or MemberAccess
2090                         //
2091                         $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2092                 }
2093           }*/
2094         ;
2095
2096 opt_expression
2097         : /* empty */
2098         | expression
2099         ;
2100         
2101 expression_list
2102         : expression
2103           {
2104                 ArrayList list = new ArrayList ();
2105                 list.Add ($1);
2106                 $$ = list;
2107           }
2108         | expression_list COMMA expression
2109           {
2110                 ArrayList list = (ArrayList) $1;
2111                 list.Add ($3);
2112                 $$ = list;
2113           }
2114         ;
2115
2116 this_access
2117         : ME
2118           {
2119                 $$ = new This (current_block, lexer.Location);
2120           }
2121         ;
2122
2123 base_access
2124         : MYBASE DOT IDENTIFIER
2125           {
2126                 $$ = new BaseAccess ((string) $3, lexer.Location);
2127           }
2128         | MYBASE OPEN_BRACKET expression_list CLOSE_BRACKET
2129           {
2130                 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
2131           }
2132         ;
2133
2134 post_increment_expression
2135         : primary_expression OP_INC
2136           {
2137                 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2138                                        (Expression) $1, lexer.Location);
2139           }
2140         ;
2141
2142 unary_expression
2143         : primary_expression
2144         | NOT prefixed_unary_expression
2145           {
2146                 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2147           }
2148         ;
2149
2150         //
2151         // The idea to split this out is from Rhys' grammar
2152         // to solve the problem with casts.
2153         //
2154 prefixed_unary_expression
2155         : unary_expression
2156         | PLUS prefixed_unary_expression
2157           {
2158                 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2159           }
2160         | MINUS prefixed_unary_expression
2161           {
2162                 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2163           }
2164         | ADDRESSOF prefixed_unary_expression
2165           {
2166                 // FIXME: We should generate an error if AddressOf is NOT used
2167                 // during delegate creation
2168                 $$ = $2;
2169           }       
2170         ;
2171
2172 multiplicative_expression
2173         : prefixed_unary_expression
2174         | multiplicative_expression STAR prefixed_unary_expression
2175           {
2176                 $$ = new Binary (Binary.Operator.Multiply,
2177                                  (Expression) $1, (Expression) $3, lexer.Location);
2178           }
2179         | multiplicative_expression DIV prefixed_unary_expression
2180           {
2181                 $$ = new Binary (Binary.Operator.Division,
2182                                  (Expression) $1, (Expression) $3, lexer.Location);
2183           }
2184         | multiplicative_expression OP_MODULUS prefixed_unary_expression
2185           {
2186                 $$ = new Binary (Binary.Operator.Modulus,
2187                                  (Expression) $1, (Expression) $3, lexer.Location);
2188           }
2189         ;
2190
2191 additive_expression
2192         : multiplicative_expression
2193         | additive_expression PLUS multiplicative_expression
2194           {
2195                 $$ = new Binary (Binary.Operator.Addition,
2196                                  (Expression) $1, (Expression) $3, lexer.Location);
2197           }
2198         | additive_expression MINUS multiplicative_expression
2199           {
2200                 $$ = new Binary (Binary.Operator.Subtraction,
2201                                  (Expression) $1, (Expression) $3, lexer.Location);
2202           }
2203         ;
2204
2205 relational_expression
2206         : additive_expression
2207         | relational_expression OP_LT additive_expression
2208           {
2209                 $$ = new Binary (Binary.Operator.LessThan,
2210                                  (Expression) $1, (Expression) $3, lexer.Location);
2211           }
2212         | relational_expression OP_GT additive_expression
2213           {
2214                 $$ = new Binary (Binary.Operator.GreaterThan,
2215                                  (Expression) $1, (Expression) $3, lexer.Location);
2216           }
2217         | relational_expression OP_LE additive_expression
2218           {
2219                 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2220                                  (Expression) $1, (Expression) $3, lexer.Location);
2221           }
2222         | relational_expression OP_GE additive_expression
2223           {
2224                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2225                                  (Expression) $1, (Expression) $3, lexer.Location);
2226           }
2227         | relational_expression IS type
2228           {
2229                 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2230           }
2231         | relational_expression AS type
2232           {
2233                 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2234           }
2235         ;
2236
2237 equality_expression
2238         : relational_expression
2239         | equality_expression OP_EQ relational_expression
2240           {
2241                 $$ = new Binary (Binary.Operator.Equality,
2242                                  (Expression) $1, (Expression) $3, lexer.Location);
2243           }
2244         | equality_expression OP_NE relational_expression
2245           {
2246                 $$ = new Binary (Binary.Operator.Inequality,
2247                                  (Expression) $1, (Expression) $3, lexer.Location);
2248           }
2249         ;
2250
2251 and_expression
2252         : equality_expression
2253         | and_expression OP_AND equality_expression
2254           {
2255                 $$ = new Binary (Binary.Operator.BitwiseAnd,
2256                                  (Expression) $1, (Expression) $3, lexer.Location);
2257           }
2258         ;
2259
2260 exclusive_or_expression
2261         : and_expression
2262         | exclusive_or_expression OP_XOR and_expression
2263           {
2264                 $$ = new Binary (Binary.Operator.ExclusiveOr,
2265                                  (Expression) $1, (Expression) $3, lexer.Location);
2266           }
2267         ;
2268
2269 conditional_and_expression
2270         : exclusive_or_expression
2271         | conditional_and_expression OP_AND exclusive_or_expression
2272           {
2273                 $$ = new Binary (Binary.Operator.LogicalAnd,
2274                                  (Expression) $1, (Expression) $3, lexer.Location);
2275           }
2276         ;
2277
2278 conditional_or_expression
2279         : conditional_and_expression
2280         | conditional_or_expression OP_OR conditional_and_expression
2281           {
2282                 $$ = new Binary (Binary.Operator.LogicalOr,
2283                                  (Expression) $1, (Expression) $3, lexer.Location);
2284           }
2285         ;
2286
2287 conditional_expression
2288         : conditional_or_expression
2289         ;
2290
2291 assignment_expression
2292         : prefixed_unary_expression ASSIGN expression
2293           {
2294                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2295           }
2296         ;
2297
2298 expression
2299         : conditional_expression
2300         | assignment_expression
2301         ;
2302
2303 constant_expression
2304         : expression
2305         ;
2306
2307 boolean_expression
2308         : expression
2309         ;
2310
2311 type
2312         : type_name {   /* class_type */
2313                 /*
2314                    This does interfaces, delegates, struct_types, class_types,
2315                    parent classes, and more! 4.2
2316                  */
2317                 $$ = DecomposeQI ((string) $1, lexer.Location); 
2318           }
2319         | builtin_types 
2320         /*| array_type 
2321          | pointer_type */
2322         ;
2323
2324 type_list
2325         : type
2326           {
2327                 ArrayList types = new ArrayList ();
2328
2329                 types.Add ($1);
2330                 $$ = types;
2331           }
2332         | type_list COMMA type
2333           {
2334                 ArrayList types = (ArrayList) $1;
2335
2336                 types.Add ($3);
2337                 $$ = types;
2338           }
2339         ;
2340
2341 type_name
2342         : namespace_or_type_name
2343         ;
2344         
2345 namespace_or_type_name
2346         : qualified_identifier
2347         ;
2348
2349 array_type
2350         : type rank_specifiers
2351           {
2352                 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2353           }
2354         ;
2355         
2356 rank_specifiers
2357         : rank_specifier opt_rank_specifier
2358           {
2359                   $$ = (string) $2 + (string) $1;
2360           }
2361         ;
2362
2363 rank_specifier
2364         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2365           {
2366                 $$ = "[" + (string) $2 + "]";
2367           }
2368         ;
2369
2370 opt_dim_separators
2371         : /* empty */
2372           {
2373                 $$ = "";
2374           }
2375         | dim_separators
2376           {
2377                   $$ = $1;
2378           }               
2379         ;
2380
2381 dim_separators
2382         : COMMA
2383           {
2384                 $$ = ",";
2385           }
2386         | dim_separators COMMA
2387           {
2388                 $$ = (string) $1 + ",";
2389           }
2390         ;       
2391 /* Built-in / Integral types */
2392 builtin_types
2393         : OBJECT        { $$ = TypeManager.system_object_expr; }
2394         | STRING        { $$ = TypeManager.system_string_expr; }
2395         | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
2396         | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
2397         | SINGLE        { $$ = TypeManager.system_single_expr; }
2398         | DOUBLE        { $$ = TypeManager.system_double_expr; }
2399         | integral_type
2400         ;
2401
2402 integral_type
2403         : /*SBYTE               { $$ = TypeManager.system_sbyte_expr; }
2404         | BYTE          { $$ = TypeManager.system_byte_expr; }
2405         | SHORT         { $$ = TypeManager.system_int16_expr; }
2406         | USHORT        { $$ = TypeManager.system_uint16_expr; }
2407         | */ INTEGER    { $$ = TypeManager.system_int32_expr; }/*
2408         | UINT          { $$ = TypeManager.system_uint32_expr; }
2409         | LONG          { $$ = TypeManager.system_int64_expr; }
2410         | ULONG         { $$ = TypeManager.system_uint64_expr; }
2411         | CHAR          { $$ = TypeManager.system_char_expr; }
2412         | VOID          { $$ = TypeManager.system_void_expr; }*/
2413         ;
2414
2415 %%
2416
2417
2418 Tokenizer lexer;
2419
2420 public Tokenizer Lexer {
2421         get {
2422                 return lexer;
2423         }
2424 }                  
2425
2426 Expression DecomposeQI (string name, Location loc)
2427 {
2428         Expression o;
2429
2430         if (name.IndexOf ('.') == -1){
2431                 return new SimpleName (name, loc);
2432         } else {
2433                 int pos = name.LastIndexOf (".");
2434                 string left = name.Substring (0, pos);
2435                 string right = name.Substring (pos + 1);
2436
2437                 o = DecomposeQI (left, loc);
2438
2439                 return new MemberAccess (o, right, loc);
2440         }
2441 }
2442
2443 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
2444 {
2445         Block implicit_block;
2446         ArrayList inits = null;
2447
2448         //
2449         // We use the `Used' property to check whether statements
2450         // have been added to the current block.  If so, we need
2451         // to create another block to contain the new declaration
2452         // otherwise, as an optimization, we use the same block to
2453         // add the declaration.
2454         //
2455         // FIXME: A further optimization is to check if the statements
2456         // that were added were added as part of the initialization
2457         // below.  In which case, no other statements have been executed
2458         // and we might be able to reduce the number of blocks for
2459         // situations like this:
2460         //
2461         // int j = 1;  int k = j + 1;
2462         //
2463         
2464         VariableDeclaration.FixupTypes (variable_declarators);
2465         
2466         if (current_block.Used) {
2467                 implicit_block = new Block (current_block, true, loc, Location.Null);
2468                 implicit_block.AddChildVariableNames (current_block);
2469         } else
2470                 implicit_block = current_block;
2471
2472         foreach (VariableDeclaration decl in variable_declarators){
2473                 Expression type = decl.type;
2474                 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
2475                         if (decl.expression_or_array_initializer != null){
2476                                 if (inits == null)
2477                                         inits = new ArrayList ();
2478                                 inits.Add (decl);
2479                         }
2480                 }
2481         }
2482
2483         if (inits == null)
2484                 return implicit_block;
2485
2486         foreach (VariableDeclaration decl in inits){
2487                 Assign assign;
2488                 Expression expr;
2489                 Expression type = decl.type;
2490                 
2491                 if (decl.expression_or_array_initializer is Expression){
2492                         expr = (Expression) decl.expression_or_array_initializer;
2493
2494                 } else {
2495                         ArrayList init = (ArrayList) decl.expression_or_array_initializer;
2496                         
2497                         expr = new ArrayCreation (type, "", init, decl.Location);
2498                 }
2499
2500                 LocalVariableReference var;
2501                 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
2502
2503                 assign = new Assign (var, expr, decl.Location);
2504
2505                 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
2506         }
2507         
2508         return implicit_block;
2509 }
2510
2511
2512 Block declare_local_constant (Expression type, VariableDeclaration decl)
2513 {
2514         Block implicit_block;
2515
2516         if (current_block.Used)
2517                 implicit_block = new Block (current_block, true);
2518         else
2519                 implicit_block = current_block;
2520
2521         if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
2522                                           current_local_parameters, decl.Location))){
2523         }
2524         
2525         return implicit_block;
2526 }
2527
2528 // <summary>
2529 //   A class used to pass around variable declarations and constants
2530 // </summary>
2531 public class VariableDeclaration {
2532         public string identifier;
2533         public object expression_or_array_initializer;
2534         public Location Location;
2535         public Attributes OptAttributes;
2536         public Expression type;
2537         public ArrayList dims;
2538         
2539         public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this 
2540                                         (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
2541         {
2542         }
2543         
2544         public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
2545         {
2546                 this.identifier = id;
2547                 this.expression_or_array_initializer = eoai;
2548                 this.Location = l;
2549                 this.OptAttributes = opt_attrs;
2550                 this.type = t;
2551                 this.dims = null;
2552         }       
2553
2554         public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
2555         {
2556         }
2557         
2558         public static void FixupTypes (ArrayList vars)
2559         {
2560                 int varcount =  vars.Count;
2561                 VariableDeclaration lf = (VariableDeclaration) vars[varcount - 1];
2562                         
2563                 if (lf.type == null)
2564                         lf.type = TypeManager.system_object_expr;
2565                         
2566                 Expression cur_type = lf.type;
2567                 int n = varcount - 1;
2568                 
2569                 while (n >= 0) {
2570                         VariableDeclaration var = (VariableDeclaration) vars[n--];
2571                         if (var.type == null)
2572                                 var.type = cur_type;
2573                         else
2574                                 cur_type = var.type;
2575                 }
2576         }
2577         
2578         public static bool HasDimBounds (string varname)
2579         {
2580                 bool res = false;
2581                 
2582                 if (varname.IndexOf("[") >= 0) {
2583                         char[] ds = {'1','2','3','4','5','6','7','8','9'};
2584                         
2585                         string dimpart = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
2586                         if (dimpart.IndexOfAny (ds) >= 0) 
2587                                 res = true;
2588                 }
2589                 return (res);
2590         }
2591         
2592         public static string StripDims (string varname, ref string d)
2593         {
2594                 string res = varname;
2595                 string dres = "";
2596                 
2597                 if (varname.IndexOf("[") >= 0) {
2598                         dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
2599                         res = varname.Substring(0, varname.IndexOf("["));
2600                 }
2601                 d = dres;
2602                 return (res);
2603         }       
2604         
2605         public static string GetRank (string dims)
2606         {
2607                 string res = "";
2608                 int x;
2609                 
2610                 for (x = 0; x < dims.Length; x++) {
2611                         if (dims[x] == '[' || dims[x] == ']' || dims[x] == ',')
2612                                 res = res + dims[x];
2613                 }                               
2614                 return (res);
2615         }               
2616         
2617         public static ArrayList ParseDims (string dims)
2618         {
2619                 ArrayList res = new ArrayList();
2620                 string d = dims.Substring (1, dims.Length -2);
2621                 Array a = d.Split (',');
2622                 
2623                 if (a.GetLength(0) > 32) {
2624                         Report.Error (999, "Arrays cannot have more than 32 dimensions");
2625                 }
2626                 
2627                 foreach (string s in a)
2628                         res.Add (new IntLiteral ((Int32) Convert.ToInt32(s)));
2629                 
2630                 return (res);
2631         }               
2632         
2633         public static bool IsArrayDecl (string varname)
2634         {
2635                 return (varname.IndexOf("[") >= 0);
2636         }                       
2637         
2638         public static void FixupArrayTypes (ArrayList vars)
2639         {
2640                 int varcount =  vars.Count;
2641                 string dims;
2642                 
2643                 foreach (VariableDeclaration var in vars) {
2644                         if (var.identifier.EndsWith(",")) {
2645                                 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), 
2646                                                                 var.identifier.LastIndexOf(",")) + "]";
2647                                 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
2648                                 var.type = new ComposedCast (var.type, (string) dims, var.Location);
2649                         }
2650                 }
2651         }                               
2652 }
2653
2654 public Property BuildSimpleProperty (Expression p_type, string name, 
2655                                         Field p_fld, int mod_flags,
2656                                         Attributes attrs, Location loc) 
2657 {
2658         Property p;
2659         Block get_block, set_block;
2660         Accessor acc_set, acc_get;
2661         StatementExpression a_set;
2662         Statement a_get;
2663         Parameter [] args;
2664         
2665         // Build SET Block
2666         Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);    
2667         args  = new Parameter [1];
2668         args [0] = implicit_value_parameter;
2669                 
2670         Parameters set_params = new Parameters (args, null, loc);
2671         a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), 
2672                             (Expression) new SimpleName("value", loc), loc), loc);
2673                             
2674         set_block = new Block (current_block, set_params, loc, Location.Null);
2675         set_block.AddStatement ((Statement) a_set);                                         
2676         acc_set = new Accessor (set_block, attrs);
2677         
2678         // Build GET Block
2679         a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
2680         get_block = new Block (current_block, null, loc, Location.Null);
2681         get_block.AddStatement ((Statement) a_get);                                         
2682         acc_get = new Accessor (get_block, attrs);
2683                 
2684         p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
2685         
2686         return (p);
2687 }
2688                 
2689 void start_block () 
2690 {
2691         current_block = new Block (current_block, current_local_parameters,
2692                            lexer.Location, Location.Null);
2693
2694
2695 Block end_block ()
2696
2697         Block res;
2698         
2699         while (current_block.Implicit)
2700                 current_block = current_block.Parent;
2701
2702         res = current_block;
2703
2704         current_block.SetEndLocation (lexer.Location);
2705         current_block = current_block.Parent;
2706         
2707         return (res);
2708 }
2709
2710 private void AddHandler (Expression evt_definition, string handler_name)
2711 {
2712         AddHandler (current_block, evt_definition, handler_name);
2713 }
2714
2715 private void AddHandler (Block b, Expression evt_definition, string handler_name)
2716 {
2717         Location loc = lexer.Location;
2718         ArrayList neh_args = new ArrayList();
2719         neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
2720         
2721         ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
2722         
2723         CompoundAssign ca = new CompoundAssign (
2724                         Binary.Operator.Addition, evt_definition, (Expression) se, loc);
2725                         
2726         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
2727         b.AddStatement (s);     
2728 }
2729
2730 // FIXME: THIS DOES NOT WORK!!!
2731 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
2732 {
2733         Location loc = lexer.Location;
2734         ArrayList neh_args = new ArrayList();
2735         neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
2736         
2737         ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
2738         
2739         CompoundAssign ca = new CompoundAssign (
2740                         Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
2741                         
2742         Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
2743         b.AddStatement (s);     
2744 }
2745
2746 // <summary>
2747 //  This method is used to get at the complete string representation of
2748 //  a fully-qualified type name, hiding inside a MemberAccess ;-)
2749 //  This is necessary because local_variable_type admits primary_expression
2750 //  as the type of the variable. So we do some extra checking
2751 // </summary>
2752 string GetQualifiedIdentifier (Expression expr)
2753 {
2754         if (expr is SimpleName)
2755                 return ((SimpleName)expr).Name;
2756         else if (expr is MemberAccess)
2757                 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
2758         else 
2759                 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
2760         
2761 }
2762
2763 private void RemoveHandler (Expression evt_definition, string handler_name)
2764 {
2765         RemoveHandler (current_block, evt_definition, handler_name);
2766 }
2767
2768
2769
2770 void Error_ExpectingTypeName (Location l, Expression expr)
2771 {
2772         if (expr is Invocation){
2773                 Report.Error (1002, l, "; expected");
2774         } else {
2775                 Report.Error (-1, l, "Invalid Type definition");
2776         }
2777 }
2778
2779 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
2780         return true;
2781 }
2782
2783 public override int parse ()
2784 {
2785         current_namespace = new Namespace (null, "");
2786         current_container = RootContext.Tree.Types;
2787         current_container.Namespace = current_namespace;
2788         oob_stack = new Stack ();
2789         switch_stack = new Stack ();
2790         
2791         UseExtendedSyntax = name.EndsWith(".mbs");
2792
2793         lexer = new Tokenizer (input, name, defines);
2794         StringBuilder value = new StringBuilder ();
2795         //yacc_verbose_flag=true;
2796         try 
2797         {
2798                 if (yacc_verbose_flag)
2799                         yyparse (lexer, new yydebug.yyDebugSimple ());
2800                 else
2801                         yyparse (lexer);
2802         } 
2803         catch (Exception e)
2804         {
2805                 Console.WriteLine (lexer.location + "  : Parsing error in " + lexer.ref_name);
2806                 Report.Error (9999, lexer.Location, "");
2807                 Console.WriteLine (e);
2808         }
2809         
2810         return Report.Errors;
2811 }
2812
2813 /* end end end */
2814 }