3 // Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler
5 // Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
7 // Licensed under the terms of the GNU GPL
9 // Copyright (C) 2001 A Rafael D Teixeira
15 namespace Mono.MonoBASIC
19 using System.Reflection;
20 using System.Collections;
25 /// The MonoBASIC Parser
28 public class Parser : GenericParser
33 /// Current block is used to add statements as we find
39 /// Tmp block is used to store block endings in if/select's
44 /// Tmp block is used to store tmp copies of expressions
49 /// Tmp catch is used to store catch clauses in try..catch..finally
51 ArrayList tmp_catch_clauses;
54 /// Current interface is used by the various declaration
55 /// productions in the interface declaration to "add"
56 /// the interfaces as we find them.
58 Interface current_interface;
61 /// This is used by the unary_expression code to resolve
62 /// a name against a parameter.
64 Parameters current_local_parameters;
67 /// This are used when parsing parameters in property
70 Parameters set_parameters;
71 Parameters get_parameters;
74 /// This is used by the sub_header parser to store modifiers
75 /// to be passed to sub/constructor
77 int current_modifiers;
80 /// This is used by the sub_header parser to store attributes
81 /// to be passed to sub/constructor
83 Attributes current_attributes;
86 /// Using during property parsing to describe the implicit
87 /// value parameter that is passed to the "set" accessor
90 string get_implicit_value_parameter_name;
93 // Using during property parsing to describe the implicit
94 // value parameter that is passed to the "set" and "get"accesor
95 // methods (properties and indexers).
97 Expression get_implicit_value_parameter_type;
100 /// Using during property parsing to describe the implicit
101 /// value parameter that is passed to the "set" accessor
104 string set_implicit_value_parameter_name;
107 // Using during property parsing to describe the implicit
108 // value parameter that is passed to the "set" and "get"accesor
109 // methods (properties and indexers).
111 Expression set_implicit_value_parameter_type;
113 // An out-of-band stack.
117 ArrayList current_rank_specifiers;
125 // Expression stack for nested ifs
129 Stack statement_stack;
131 // A stack for With expressions.
136 static public bool InitialOptionExplicit = false;
137 static public bool InitialOptionStrict = false;
138 static public bool InitialOptionCompareBinary = true;
139 static public ArrayList ImportsList = null;
143 bool OptionCompareBinary;
145 static public bool UseExtendedSyntax; // for ".mbs" files
147 bool implicit_modifiers;
149 public override string[] extensions()
151 string [] list = { ".vb", ".mbs" };
158 %token NONE /* This token is never returned by our lexer */
159 %token ERROR // This is used not by the parser, but by the tokenizer.
163 *These are the MonoBASIC keywords
252 %token NOTINHERITABLE
253 %token NOTOVERRIDABLE
308 %token YIELD // MonoBASIC extension
310 /* MonoBASIC single character operators/punctuation. */
312 %token OPEN_BRACKET "["
313 %token CLOSE_BRACKET "]"
314 %token OPEN_PARENS "("
315 %token OPEN_BRACE "{"
316 %token CLOSE_BRACE "}"
317 %token CLOSE_PARENS ")"
333 %token EXCLAMATION "!"
336 %token LONGTYPECHAR "&"
338 %token SINGLETYPECHAR "!"
339 %token NUMBER_SIGN "#"
340 %token DOLAR_SIGN "$"
342 %token ATTR_ASSIGN ":="
344 /* MonoBASIC multi-character operators. */
349 //%token OP_MODULUS //"mod"
350 %token OP_MULT_ASSIGN "*="
351 %token OP_DIV_ASSIGN "/="
352 %token OP_IDIV_ASSIGN "\\="
353 %token OP_ADD_ASSIGN "+="
354 %token OP_SUB_ASSIGN "-="
355 %token OP_CONCAT_ASSIGN "&="
356 %token OP_EXP_ASSIGN "^="
358 /* VB.NET 2003 new bit-shift operators */
359 %token OP_SHIFT_LEFT "<<"
360 %token OP_SHIFT_RIGHT ">>"
363 %token LITERAL_INTEGER "int literal"
364 %token LITERAL_SINGLE "float literal"
365 %token LITERAL_DOUBLE "double literal"
366 %token LITERAL_DECIMAL "decimal literal"
367 %token LITERAL_CHARACTER "character literal"
368 %token LITERAL_STRING "string literal"
369 %token LITERAL_DATE "datetime literal"
373 /* Add precedence rules to solve dangling else s/r conflict */
382 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
384 %left STAR DIV PERCENT
385 %right BITWISE_NOT CARRET UMINUS
386 %nonassoc OP_INC OP_DEC
388 %left OPEN_BRACKET OPEN_BRACE
393 %start compilation_unit
397 : opt_option_directives
398 opt_imports_directives
407 opt_option_directives
414 | option_directives option_directive
418 : option_explicit_directive
419 | option_strict_directive
420 | option_compare_directive
449 option_explicit_directive
450 : OPTION EXPLICIT on_off EOL
452 if (!UseExtendedSyntax)
453 OptionExplicit = (bool)$3;
456 9999, lexer.Location,
457 "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");
462 option_strict_directive
463 : OPTION STRICT on_off EOL
465 if (!UseExtendedSyntax)
466 OptionStrict = (bool)$3;
469 9999, lexer.Location,
470 "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");
474 option_compare_directive
475 : OPTION COMPARE text_or_binary EOL
477 OptionCompareBinary = (bool)$3;
488 | declarations declaration
492 : namespace_declaration
498 if ($1 is Class || $1 is Struct || $1 is Module ){
499 TypeContainer c = (TypeContainer) $1;
500 mod_flags = c.ModFlags;
505 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
507 1527, lexer.Location,
508 "Namespace elements cannot be explicitly " +
509 "declared private or protected in '" + name + "'");
524 : PERCENT { $$ = TypeManager.system_int32_expr; }
525 | LONGTYPECHAR { $$ = TypeManager.system_int64_expr; }
526 | AT_SIGN { $$ = TypeManager.system_decimal_expr; }
527 | SINGLETYPECHAR { $$ = TypeManager.system_single_expr; }
528 | NUMBER_SIGN { $$ = TypeManager.system_double_expr; }
529 | DOLAR_SIGN { $$ = TypeManager.system_string_expr; }
533 : /* empty */ { $$ = null; }
534 | type_character { $$ = $1; }
540 | qualified_identifier DOT identifier
542 $$ = (($1).ToString ()) + "." + ($3.ToString ());
546 opt_imports_directives
553 | imports_directives imports_directive
557 : IMPORTS imports_terms EOL
562 | imports_terms COMMA imports_terms
566 : qualified_identifier
568 current_namespace.Using ((string) $1, lexer.Location);
570 | qualified_identifier ASSIGN qualified_identifier
572 current_namespace.UsingAlias ((string) $1, (string) $3, lexer.Location);
578 | attribute_sections { $$ = $1; }
584 AttributeSection sect = (AttributeSection) $1;
586 if (sect.Target == "assembly")
587 RootContext.AddGlobalAttributeSection (current_container, sect);
589 $$ = new Attributes ((AttributeSection) $1, lexer.Location);
593 FIXME: we should check if extended syntax is enabled;
594 otherwise an exception should be thrown since VB.NET
595 only allows one attribute section
597 | attribute_sections attribute_section
599 Attributes attrs = null;
600 AttributeSection sect = (AttributeSection) $2;
602 if (sect.Target == "assembly")
603 RootContext.AddGlobalAttributeSection (current_container, sect);
606 attrs = (Attributes) $1;
607 attrs.AddAttributeSection (sect);
615 : OP_LT attribute_target_specifier attribute_list OP_GT
617 string target = null;
620 target = (string) $2;
622 $$ = new AttributeSection (target, (ArrayList) $3);
624 | OP_LT attribute_list OP_GT
626 $$ = new AttributeSection (null, (ArrayList) $2);
630 attribute_target_specifier
631 : attribute_target COLON
640 CheckAttributeTarget ((string) $1);
643 | EVENT { $$ = "event"; }
644 | RETURN { $$ = "return"; }
650 ArrayList attrs = new ArrayList ();
656 | attribute_list COMMA attribute
658 ArrayList attrs = (ArrayList) $1;
670 opt_attribute_arguments
672 $$ = new Mono.MonoBASIC.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
680 opt_attribute_arguments
681 : /* empty */ { $$ = null; }
682 | OPEN_PARENS attribute_arguments CLOSE_PARENS
689 : opt_positional_argument_list
694 ArrayList args = new ArrayList ();
700 | positional_argument_list COMMA named_argument_list
702 ArrayList args = new ArrayList ();
708 | named_argument_list
710 ArrayList args = new ArrayList ();
719 opt_positional_argument_list
720 : /* empty */ { $$ = null; }
721 | positional_argument_list
724 positional_argument_list
727 ArrayList args = new ArrayList ();
728 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
732 | positional_argument_list COMMA expression
734 ArrayList args = (ArrayList) $1;
735 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
744 ArrayList args = new ArrayList ();
749 | named_argument_list COMMA named_argument
751 ArrayList args = (ArrayList) $1;
759 : identifier ATTR_ASSIGN expression
761 $$ = new DictionaryEntry (
763 new Argument ((Expression) $3, Argument.AType.Expression));
767 namespace_declaration
768 : opt_attributes NAMESPACE qualified_identifier EOL
770 Attributes attrs = (Attributes) $1;
773 foreach (AttributeSection asec in attrs.AttributeSections)
774 if (asec.Target == "assembly")
775 RootContext.AddGlobalAttributeSection (current_container, asec);
778 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$3);
780 opt_imports_directives
784 current_namespace = current_namespace.Parent;
792 current_attributes = (Attributes) $1;
793 current_modifiers = (int) $2;
795 type_spec_declaration
798 type_spec_declaration
801 | interface_declaration
802 | delegate_declaration
808 : CLASS identifier EOL opt_inherits opt_implements
813 name = MakeName ((string) $2);
814 new_class = new Class (current_container, name, current_modifiers,
815 (Attributes) current_attributes, lexer.Location);
817 current_container = new_class;
818 current_container.Namespace = current_namespace;
819 RootContext.Tree.RecordDecl (name, new_class);
821 opt_class_member_declarations
824 Class new_class = (Class) current_container;
825 new_class.Bases = (ArrayList) $4;
827 current_container = current_container.Parent;
828 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
835 : /* empty */ { $$ = null; }
836 | INHERITS type_list EOL { $$ = $2; }
840 : /* empty */ { $$ = null; }
841 | IMPLEMENTS type_list EOL { $$ = $2; }
845 : /* empty */ { $$ = (int) 0; current_modifiers = 0; }
846 | modifiers { $$ = $1; current_modifiers = (int) $1; }
856 if ((m1 & m2) != 0) {
857 Location l = lexer.Location;
858 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
860 $$ = (int) (m1 | m2);
865 : PUBLIC { $$ = Modifiers.PUBLIC; }
866 | PROTECTED { $$ = Modifiers.PROTECTED; }
867 | PRIVATE { $$ = Modifiers.PRIVATE; }
868 | SHARED { $$ = Modifiers.STATIC; }
869 | FRIEND { $$ = Modifiers.INTERNAL; }
870 | NOTINHERITABLE { $$ = Modifiers.SEALED; }
871 | OVERRIDABLE { $$ = Modifiers.VIRTUAL; }
872 | NOTOVERRIDABLE { $$ = Modifiers.NONVIRTUAL; }
873 | OVERRIDES { $$ = Modifiers.OVERRIDE; }
874 | OVERLOADS { $$ = Modifiers.OVERLOADS; }
875 | MUSTINHERIT { $$ = Modifiers.ABSTRACT; }
876 | READONLY { $$ = Modifiers.READONLY; }
877 | DEFAULT { $$ = Modifiers.DEFAULT; }
878 | WRITEONLY { $$ = Modifiers.WRITEONLY; }
882 : MODULE identifier EOL
886 name = MakeName((string) $2);
887 new_module = new Module(current_container,
889 current_modifiers, // already checks then
890 (Attributes) current_attributes,
892 current_container = new_module;
893 current_container.Namespace = current_namespace;
894 RootContext.Tree.RecordDecl(name, new_module);
896 opt_module_member_declarations
899 Module new_module = (Module)current_container;
901 current_container = current_container.Parent;
902 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
908 opt_module_member_declarations
910 | module_member_declarations
913 module_member_declarations
914 : module_member_declaration
915 | module_member_declarations module_member_declaration
918 module_member_declaration
922 current_attributes = (Attributes) $1;
923 current_modifiers = ((int)$2) | Modifiers.STATIC;
924 bool explicit_static = (((int) $2 & Modifiers.STATIC) > 0);
925 implicit_modifiers = (!explicit_static);
927 module_member_declarator
929 implicit_modifiers = false;
934 module_member_declarator
935 : static_constructor_declaration
938 Method method = (Method) $1;
939 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
942 | withevents_declaration /* This is a field but must be treated specially, see below */
943 | constant_declaration
944 | property_declaration
946 | type_spec_declaration
949 constant_declaration // TODO: implement truly the logic
950 : CONST identifier ASSIGN primary_expression EOL
951 | CONST identifier AS type ASSIGN constant_expression EOL
954 opt_class_member_declarations
956 | class_member_declarations
959 class_member_declarations
960 : class_member_declaration
961 | class_member_declarations class_member_declaration
964 class_member_declaration
968 current_attributes = (Attributes) $1;
969 current_modifiers = (int) $2;
971 class_member_declarator
977 class_member_declarator
978 : constructor_declaration
981 Method method = (Method) $1;
982 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
985 | constant_declaration
986 | property_declaration
988 | withevents_declaration /* This is a field but must be treated specially, see below */
989 /*| type_declaration */
998 | must_override_declaration
1001 must_override_declaration
1002 : must_override_sub_declaration
1003 | must_override_func_declaration
1006 must_override_sub_declaration
1007 : MUSTOVERRIDE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1009 if (current_container is Module)
1010 Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
1012 if (current_container is Struct)
1013 Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1015 current_modifiers |= Modifiers.ABSTRACT;
1017 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3,
1018 (Parameters) $5, null, null, lexer.Location);
1020 if (!(current_container is Class))
1021 Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1023 // FIXME ASAP: This will crash the compiler at resolution time
1028 must_override_func_declaration
1029 : MUSTOVERRIDE FUNCTION identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type EOL
1031 if (current_container is Module)
1032 Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
1034 if (current_container is Struct)
1035 Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1037 current_modifiers |= Modifiers.ABSTRACT;
1039 Method method = new Method ((Expression) $8, (int) current_modifiers, (string) $3,
1040 (Parameters) $5, null, null, lexer.Location);
1042 if (!(current_container is Class))
1043 Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1045 // FIXME ASAP: This will crash the compiler at resolution time
1051 : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
1053 current_local_parameters = (Parameters) $4;
1056 // Structure members are Public by default
1057 if ((current_container is Struct) && (current_modifiers == 0))
1058 current_modifiers = Modifiers.PUBLIC;
1063 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
1064 (Parameters) current_local_parameters, null, (Expression) $7,
1067 method.Block = (Block) end_block();
1070 if ($6 != null) { /* we have an event handler to take care of */
1071 // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
1072 string evt_def = ((MemberAccess)$6).ToString();
1073 int pos = evt_def.LastIndexOf (".");
1074 string evt_target = ((string) $2).Substring (0, pos);
1076 foreach (Property p in current_container.Properties) {
1077 if (p.Name == evt_target) {
1079 // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
1080 AddHandler (p.Set.Block, (Expression)$6, (string) $2);
1089 : FUNCTION identifier opt_type_character
1090 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks opt_implement_clause EOL
1093 current_local_parameters = (Parameters) $5;
1096 Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
1098 // Structure members are Public by default
1099 if ((current_container is Struct) && (current_modifiers == 0))
1100 current_modifiers = Modifiers.PUBLIC;
1101 // Add local var declaration
1103 ArrayList retval = new ArrayList ();
1104 retval.Add (new VariableDeclaration ((string) $2, (Expression) ftype, lexer.Location));
1105 declare_local_variables ((Expression) ftype, retval, lexer.Location);
1110 Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
1112 Method method = new Method ((Expression) ftype, (int) current_modifiers, (string) $2,
1113 (Parameters) current_local_parameters, null,
1114 (Expression) ftype, lexer.Location);
1115 method.Block = end_block();
1121 : STRUCTURE identifier EOL
1122 opt_implement_clause
1125 string full_struct_name = MakeName ((string) $2);
1127 // Module members are static by default, but structures *can't* be declared static
1128 // so we must fix it, if mbas was the one actually responsible for this
1129 // instead of triggering an error.
1130 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1131 current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1133 new_struct = new Struct (current_container, full_struct_name,
1134 (int) current_modifiers,
1135 (Attributes) current_attributes, lexer.Location);
1136 current_container = new_struct;
1137 current_container.Namespace = current_namespace;
1138 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1140 opt_struct_member_declarations
1142 Struct new_struct = (Struct) current_container;
1145 new_struct.Bases = (ArrayList) $4;
1147 current_container = current_container.Parent;
1148 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1154 opt_struct_member_declarations
1156 | struct_member_declarations
1159 struct_member_declarations
1160 : struct_member_declaration
1161 | struct_member_declarations struct_member_declaration
1164 struct_member_declaration
1166 struct_member_declarator
1168 struct_member_declarator
1170 //| constant_declaration
1171 | method_declaration
1172 | property_declaration
1174 | constructor_declaration
1178 * This is only included so we can flag error 575:
1179 * destructors only allowed on class types
1181 //| destructor_declaration
1185 : EVENT identifier AS type EOL
1187 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1189 Event e = new Event ((Expression) $4, var.identifier,
1190 null, current_modifiers, null, null,
1191 current_attributes, lexer.Location);
1193 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1196 // | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1198 // throw new NotSupportedException();
1203 : ENUM identifier opt_type_spec EOL
1204 opt_enum_member_declarations
1206 Location enum_location = lexer.Location;
1207 string full_name = MakeName ((string) $2);
1208 Expression enum_type = ($3 == null) ? TypeManager.system_int32_expr : (Expression) $3;
1209 ArrayList enum_members = (ArrayList) $5;
1211 // Module members are static by default, but enums *can't* be declared static
1212 // so we must fix it if mbas was the one actually responsible for this
1213 // instead of triggering an error.
1214 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1215 current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1217 Mono.MonoBASIC.Enum e = new Mono.MonoBASIC.Enum (current_container, enum_type,
1218 (int) current_modifiers, full_name,
1219 (Attributes) current_attributes, enum_location);
1221 foreach (VariableDeclaration ev in enum_members) {
1222 Location loc = (Location) ev.Location;
1224 CheckDef (e.AddEnumMember (ev.identifier,
1225 (Expression) ev.expression_or_array_initializer,
1226 loc, ev.OptAttributes), ev.identifier, loc);
1229 e.Namespace = current_namespace;
1231 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1232 RootContext.Tree.RecordDecl (full_name, e);
1238 opt_enum_member_declarations
1239 : /* empty */ { $$ = new ArrayList (); }
1240 | enum_member_declarations { $$ = $1; }
1243 enum_member_declarations
1244 : enum_member_declaration
1246 ArrayList l = new ArrayList ();
1251 | enum_member_declarations enum_member_declaration
1253 ArrayList l = (ArrayList) $1;
1261 enum_member_declaration
1262 : opt_attributes identifier EOL
1264 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1266 | opt_attributes identifier
1268 $$ = lexer.Location;
1270 ASSIGN expression EOL
1272 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1276 interface_declaration
1277 : INTERFACE identifier EOL
1279 Interface new_interface;
1280 string full_interface_name = MakeName ((string) $2);
1282 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1283 (Attributes) current_attributes, lexer.Location);
1284 if (current_interface != null) {
1285 Location l = lexer.Location;
1286 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1288 current_interface = new_interface;
1289 new_interface.Namespace = current_namespace;
1290 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1295 Interface new_interface = (Interface) current_interface;
1298 new_interface.Bases = (ArrayList) $5;
1300 current_interface = null;
1301 CheckDef (current_container.AddInterface (new_interface),
1302 new_interface.Name, new_interface.Location);
1309 : /* empty */ { $$ = null; }
1314 : INHERITS interface_type_list { $$ = $2; }
1320 ArrayList interfaces = new ArrayList ();
1322 interfaces.Add ($1);
1325 | interface_type_list COMMA interface_type
1327 ArrayList interfaces = (ArrayList) $1;
1328 interfaces.Add ($3);
1334 : opt_interface_member_declarations
1337 opt_interface_member_declarations
1339 | interface_member_declarations
1342 interface_member_declarations
1343 : interface_member_declaration
1344 | interface_member_declarations interface_member_declaration
1347 interface_member_declaration
1348 : interface_method_declaration
1350 InterfaceMethod m = (InterfaceMethod) $1;
1352 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1354 | interface_property_declaration
1356 InterfaceProperty p = (InterfaceProperty) $1;
1358 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1360 | interface_event_declaration
1362 InterfaceEvent e = (InterfaceEvent) $1;
1364 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1369 : /* empty */ { $$ = false; }
1370 | NEW { $$ = true; }
1373 interface_method_declaration
1375 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1377 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1378 (Parameters) $4, current_attributes, lexer.Location);
1380 | FUNCTION identifier opt_type_character
1381 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1383 if ($3 != null && $3 != $8)
1384 Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1386 $$ = new InterfaceMethod (
1387 (Expression) $8, (string) $2, false, (Parameters) $5,
1388 current_attributes, lexer.Location);
1390 | FUNCTION identifier type_character
1391 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1393 $$ = new InterfaceMethod (
1394 (Expression) $3, (string) $2, false, (Parameters) $5,
1395 current_attributes, lexer.Location);
1399 interface_property_declaration
1400 : opt_modifiers PROPERTY identifier
1402 opt_formal_parameter_list
1403 CLOSE_PARENS opt_type_spec EOL
1405 // FIXME we MUST pass property parameters
1406 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1407 true, true, current_attributes,
1412 interface_event_declaration
1413 : opt_attributes opt_new EVENT type identifier EOL
1415 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1420 property_declaration
1421 : opt_modifiers PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
1423 get_implicit_value_parameter_type = (Expression) $6;
1424 get_implicit_value_parameter_name = (string) $3;
1426 current_modifiers = (int) $1;
1428 current_local_parameters = (Parameters) $4;
1429 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
1430 get_parameters = current_local_parameters.Copy (lexer.Location);
1431 set_parameters = current_local_parameters.Copy (lexer.Location);
1435 get_parameters = Parameters.EmptyReadOnlyParameters;
1436 set_parameters = new Parameters (null, null ,lexer.Location);
1438 lexer.PropertyParsing = true;
1440 $$ = lexer.Location;
1442 accessor_declarations
1445 lexer.PropertyParsing = false;
1448 Pair pair = (Pair) $10;
1449 Accessor get_block = (Accessor) pair.First;
1450 Accessor set_block = (Accessor) pair.Second;
1452 Location loc = lexer.Location;
1454 // Structure members are Public by default
1455 if ((current_container is Struct) && (current_modifiers == 0))
1456 current_modifiers = Modifiers.PUBLIC;
1458 prop = new Property ((Expression) $6, (string) $3, current_modifiers, get_block, set_block,
1459 current_attributes, loc, set_implicit_value_parameter_name,
1460 get_parameters, set_parameters, (Expression) $7);
1462 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1463 get_implicit_value_parameter_type = null;
1464 set_implicit_value_parameter_type = null;
1465 get_parameters = null;
1466 set_parameters = null;
1467 current_local_parameters = null;
1471 opt_property_parameters
1474 $$ = Parameters.EmptyReadOnlyParameters;
1476 | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1482 opt_implement_clause
1487 | IMPLEMENTS qualified_identifier
1489 $$ = DecomposeQI ((string)$2, lexer.Location);
1493 accessor_declarations
1494 : get_accessor_declaration opt_set_accessor_declaration
1496 $$ = new Pair ($1, $2);
1498 | set_accessor_declaration opt_get_accessor_declaration
1500 $$ = new Pair ($2, $1);
1504 opt_get_accessor_declaration
1505 : /* empty */ { $$ = null; }
1506 | get_accessor_declaration
1509 opt_set_accessor_declaration
1510 : /* empty */ { $$ = null; }
1511 | set_accessor_declaration
1514 get_accessor_declaration
1515 : opt_attributes GET EOL
1517 current_local_parameters = get_parameters;
1519 lexer.PropertyParsing = false;
1522 // Add local var declaration
1524 ArrayList retval = new ArrayList ();
1525 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1526 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
1532 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1533 current_local_parameters = null;
1534 lexer.PropertyParsing = true;
1538 set_accessor_declaration
1539 : opt_attributes SET opt_set_parameter EOL
1541 Parameter implicit_value_parameter = new Parameter (
1542 set_implicit_value_parameter_type,
1543 set_implicit_value_parameter_name,
1544 Parameter.Modifier.NONE, null);
1546 current_local_parameters = set_parameters;
1547 current_local_parameters.AppendParameter (implicit_value_parameter);
1550 lexer.PropertyParsing = false;
1555 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1556 current_local_parameters = null;
1557 lexer.PropertyParsing = true;
1564 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
1565 set_implicit_value_parameter_name = "Value";
1567 | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
1569 /* FIXME: possible syntax error which must be caught
1570 Set ( As <type>) is currently (and wrongly so) legal
1572 set_implicit_value_parameter_type = (Expression) $3;
1574 set_implicit_value_parameter_name = (string) $2;
1576 set_implicit_value_parameter_name = "Value";
1582 variable_declarators EOL
1584 int mod = (int) current_modifiers;
1587 VariableDeclaration.FixupTypes ((ArrayList) $2);
1588 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1590 if (current_container is Module)
1591 mod = mod | Modifiers.STATIC;
1593 // Structure members are Public by default
1594 if ((current_container is Struct) && (mod == 0))
1595 mod = Modifiers.PUBLIC;
1597 foreach (VariableDeclaration var in (ArrayList) $2){
1598 Location l = var.Location;
1600 Field field = new Field (var.type, mod, var.identifier,
1601 var.expression_or_array_initializer,
1602 (Attributes) null, l);
1604 CheckDef (current_container.AddField (field), field.Name, l);
1609 withevents_declaration
1610 : WITHEVENTS variable_declarators EOL
1612 /* WithEvents Fields must be resolved into properties
1613 with a bit of magic behind the scenes */
1615 VariableDeclaration.FixupTypes ((ArrayList) $2);
1617 foreach (VariableDeclaration var in (ArrayList) $2) {
1618 // 1 - We create a private field
1619 Location l = var.Location;
1621 if ((current_modifiers & Modifiers.STATIC) > 0)
1622 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1624 Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier,
1625 var.expression_or_array_initializer,
1626 (Attributes) null, l);
1628 CheckDef (current_container.AddField (field), field.Name, l);
1630 // 2 - Public property
1632 prop = BuildSimpleProperty (var.type, (string) var.identifier,
1633 field, (int) current_modifiers,
1634 (Attributes) current_attributes, l);
1636 CheckDef (current_container.AddProperty (prop), prop.Name, l);
1646 delegate_declaration
1648 identifier OPEN_PARENS
1649 opt_formal_parameter_list
1653 Location l = lexer.Location;
1654 // Module members are static by default, but delegates *can't* be declared static
1655 // so we must fix it, if mbas was the one actually responsible for this
1656 // instead of triggering an error.
1657 if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
1658 current_modifiers = (current_modifiers & ~Modifiers.STATIC);
1660 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (current_container, TypeManager.system_void_expr,
1661 (int) current_modifiers,
1662 MakeName ((string) $3), (Parameters) $5,
1663 (Attributes) current_attributes, l);
1665 del.Namespace = current_namespace;
1666 CheckDef (current_container.AddDelegate (del), del.Name, l);
1669 identifier OPEN_PARENS
1670 opt_formal_parameter_list
1671 CLOSE_PARENS AS type
1673 Location l = lexer.Location;
1674 Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (
1676 (Expression) $8, (int) current_modifiers, MakeName ((string) $3),
1677 (Parameters) $5, (Attributes) current_attributes, l);
1679 del.Namespace = current_namespace;
1680 CheckDef (current_container.AddDelegate (del), del.Name, l);
1687 | HANDLES qualified_identifier
1689 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);
1691 | HANDLES MYBASE DOT qualified_identifier
1693 // FIXME: this is blatantly wrong and crash-prone
1694 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
1700 | OPEN_PARENS CLOSE_PARENS
1703 static_constructor_declaration
1704 : SHARED SUB NEW opt_empty_parens EOL
1706 current_local_parameters = Parameters.EmptyReadOnlyParameters;
1708 oob_stack.Push (lexer.Location);
1710 Location l = (Location) oob_stack.Pop ();
1711 $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
1715 Constructor c = (Constructor) $1;
1716 c.Block = (Block) end_block();
1717 c.ModFlags = (int) current_modifiers;
1718 c.OptAttributes = current_attributes;
1720 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1721 current_local_parameters = null;
1725 constructor_declaration
1726 : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1728 current_local_parameters = (Parameters) $4;
1730 oob_stack.Push (lexer.Location);
1732 Location l = (Location) oob_stack.Pop ();
1733 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1738 Constructor c = (Constructor) $1;
1739 c.Block = (Block) end_block();
1740 c.ModFlags = (int) current_modifiers;
1741 c.OptAttributes = current_attributes;
1743 // FIXME: This should happen at grammar level, but doing it
1744 // triggers a lot of conflicts/problems.
1745 c.Initializer = FixConstructorInitializer (ref c.Block.statements);
1747 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1748 current_local_parameters = null;
1753 opt_formal_parameter_list
1756 $$ = Parameters.EmptyReadOnlyParameters;
1758 | formal_parameter_list
1761 //Parameter p = ((Parameters) $1).FixedParameters[0];
1765 formal_parameter_list
1768 ArrayList pars_list = (ArrayList) $1;
1770 Parameter [] pars = new Parameter [pars_list.Count];
1771 pars_list.CopyTo (pars);
1772 $$ = new Parameters (pars, null, lexer.Location);
1774 | fixed_parameters COMMA parameter_array
1776 ArrayList pars_list = (ArrayList) $1;
1778 Parameter [] pars = new Parameter [pars_list.Count];
1779 pars_list.CopyTo (pars);
1781 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
1785 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1792 ArrayList pars = new ArrayList ();
1797 | fixed_parameters COMMA fixed_parameter
1799 ArrayList pars = (ArrayList) $1;
1808 opt_parameter_modifier
1809 identifier opt_type_character opt_rank_specifiers opt_type_spec opt_variable_initializer
1811 Parameter.Modifier pm = (Parameter.Modifier)$2;
1812 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1815 if (opt_parm && ($7 == null))
1816 Report.Error (999, "Optional parameters must have a default value");
1819 if ((pm & Parameter.Modifier.REF) !=0)
1820 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1822 pm = Parameter.Modifier.NONE; //FIXME: should take into account BYREF
1825 if ($4 != null && $6 != null && $4 != $6)
1826 Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
1828 ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6);
1830 string t = ptype.ToString() + VariableDeclaration.BuildRank ((ArrayList) $5);
1831 ptype = DecomposeQI (t, lexer.Location);
1833 $$ = new Parameter (ptype, (string) $3, pm,
1834 (Attributes) $1, (Expression) $7, opt_parm);
1839 : PARAM_ARRAY identifier opt_parens AS type
1841 string s_patype = ((Expression) $5).ToString();
1845 Expression patype = DecomposeQI (s_patype, Location.Null);
1846 $$ = new Parameter (patype, (string) $2, Parameter.Modifier.PARAMS, null);
1847 // note ("type must be a single-dimension array type");
1854 | OPEN_PARENS CLOSE_PARENS
1858 opt_parameter_modifier
1859 : /* empty */ { $$ = Parameter.Modifier.VAL; }
1860 | parameter_modifiers { $$ = $1; }
1864 : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1865 | parameter_modifier { $$ = $1; }
1869 : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1870 | BYVAL { $$ = Parameter.Modifier.VAL; }
1871 | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; }
1876 | statement_list end_of_stmt
1881 | statement_list end_of_stmt statement
1885 declaration_statement
1887 if ($1 != null && (Block) $1 != current_block){
1888 current_block.AddStatement ((Statement) $1);
1889 current_block = (Block) $1;
1892 | embedded_statement
1894 Statement s = (Statement) $1;
1896 current_block.AddStatement ((Statement) $1);
1899 | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1901 AddHandler ((Expression) $2, (string) $5);
1903 | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1905 RaiseEvent ((string) $2, (ArrayList) $4);
1907 /* | array_handling_statement */
1908 /* | empty_statement */
1911 Statement s = (Statement) $1;
1913 current_block.AddStatement ((Statement) $1);
1918 : identifier COLON end_of_stmt
1920 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1922 if (!current_block.AddLabel ((string) $1, labeled)){
1923 Location l = lexer.Location;
1924 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1926 current_block.AddStatement (labeled);
1932 : expression_statement
1933 | selection_statement
1934 | iteration_statement
1937 | array_handling_statement
1943 $$ = new EmptyStatement ();
1949 : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */
1951 // was : Expression e = DecomposeQI ((string) $2, lexer.Location);
1952 Expression e = (Expression) $2;
1959 Block b = end_block();
1966 array_handling_statement
1972 : REDIM opt_preserve redim_clauses
1974 ArrayList list = (ArrayList) $3;
1975 ReDim r = new ReDim (list, (bool) $2, lexer.Location);
1982 : /* empty */ { $$ = false; }
1983 | PRESERVE { $$ = true; }
1989 ArrayList clauses = new ArrayList ();
1994 | redim_clauses COMMA redim_clause
1996 ArrayList clauses = (ArrayList) ($1);
2004 : invocation_expression
2006 Invocation i = (Invocation) $1;
2007 RedimClause rc = new RedimClause (i.expr, i.Arguments);
2013 : ERASE erase_clauses
2015 ArrayList list = (ArrayList) $2;
2016 foreach(Expression e in list)
2018 Erase r = new Erase (e, lexer.Location);
2027 ArrayList clauses = new ArrayList ();
2032 | erase_clauses COMMA erase_clause
2034 ArrayList clauses = (ArrayList) ($1);
2042 : primary_expression
2047 | continue_statement
2048 | */return_statement
2058 $$ = new Goto (current_block, (string) $2, lexer.Location);
2063 : THROW opt_expression
2065 $$ = new Throw ((Expression) $2, lexer.Location);
2072 $$ = new Exit ((ExitType)$2, lexer.Location);
2077 : DO { $$ = ExitType.DO; }
2078 | FOR { $$ = ExitType.FOR; }
2079 | WHILE { $$ = ExitType.WHILE; }
2080 | SELECT { $$ = ExitType.SELECT; }
2081 | SUB { $$ = ExitType.SUB; }
2082 | FUNCTION { $$ = ExitType.FUNCTION; }
2083 | PROPERTY { $$ = ExitType.PROPERTY; }
2084 | TRY { $$ = ExitType.TRY; }
2087 : RETURN opt_expression
2089 $$ = new Return ((Expression) $2, lexer.Location);
2101 : FOR EACH identifier IN
2103 oob_stack.Push (lexer.Location);
2105 expression end_of_stmt
2109 Block foreach_block = current_block;
2110 Location l = lexer.Location;
2111 LocalVariableReference v = null;
2114 vi = foreach_block.GetVariableInfo ((string) $3);
2116 // Get a reference to this variable.
2117 v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2120 Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2127 Block foreach_block = current_block;
2128 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2129 Block prev_block = end_block();
2130 Location l = (Location) oob_stack.Pop ();
2134 f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
2144 if (!UseExtendedSyntax)
2150 if (iterator_container == null){
2151 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2154 iterator_container.SetYields ();
2155 $$ = new Yield ((Expression) $2, lexer.Location);
2160 if (!UseExtendedSyntax)
2166 if (iterator_container == null){
2167 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2170 iterator_container.SetYields ();
2171 $$ = new YieldBreak (lexer.Location);
2191 tmp_catch_clauses = (ArrayList) $5;
2200 ArrayList s = new ArrayList ();
2202 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2209 // Now s contains the list of specific catch clauses
2210 // and g contains the general one.
2211 Block b = end_block();
2213 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2220 tmp_block = end_block();
2230 ArrayList s = new ArrayList ();
2231 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2233 if (catch_list != null){
2234 foreach (Catch cc in catch_list) {
2242 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2248 : /* empty */ { $$ = null; }
2255 ArrayList l = new ArrayList ();
2260 | catch_clauses catch_clause
2262 ArrayList l = (ArrayList) $1;
2270 : /* empty */ { $$ = null; }
2275 : CATCH opt_catch_args end_of_stmt
2277 Expression type = null;
2281 DictionaryEntry cc = (DictionaryEntry) $2;
2282 type = (Expression) cc.Key;
2283 id = (string) cc.Value;
2286 ArrayList one = new ArrayList ();
2287 Location loc = lexer.Location;
2289 one.Add (new VariableDeclaration (id, type, loc));
2293 current_block = new Block (current_block);
2294 Block b = declare_local_variables (type, one, loc);
2300 opt_statement_list {
2301 Expression type = null;
2303 Block b_catch = current_block;
2306 DictionaryEntry cc = (DictionaryEntry) $2;
2307 type = (Expression) cc.Key;
2308 id = (string) cc.Value;
2312 // FIXME: I can change this for an assignment.
2314 while (current_block != (Block) $1)
2315 current_block = current_block.Parent;
2319 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2324 : /* empty */ { $$ = null; }
2329 : identifier AS type
2331 $$ = new DictionaryEntry ($3, $1);
2337 : DO opt_do_construct end_of_stmt
2340 oob_stack.Push (lexer.Location);
2343 LOOP opt_do_construct
2345 Expression t_before = (Expression) $2;
2346 Expression t_after = (Expression) $7;
2349 if ((t_before != null) && (t_after != null))
2350 Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2352 if ((t_before == null) && (t_after == null))
2353 t = new BoolLiteral (true);
2355 t = (t_before != null) ? t_before : t_after;
2357 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2359 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2360 ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2361 t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2363 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2368 : /* empty */ { $$ = null; }
2369 | while_or_until boolean_expression
2371 do_type = (DoOptions)$1;
2372 $$ = (Expression) $2;
2377 : WHILE { $$ = DoOptions.WHILE; }
2378 | UNTIL { $$ = DoOptions.UNTIL; }
2385 oob_stack.Push (lexer.Location);
2387 boolean_expression end_of_stmt
2391 Location l = (Location) oob_stack.Pop ();
2392 Block b = end_block();
2393 Expression e = (Expression) $3;
2394 $$ = new While ((Expression) e, (Statement) b, l);
2400 : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2407 Block statement = end_block();
2408 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2410 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2411 Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual,
2412 for_var, (Expression) $6, lexer.Location);
2413 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2414 for_var, (Expression) $7, lexer.Location), lexer.Location);
2416 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);
2417 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2419 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);
2424 : /* empty */ { $$ = new IntLiteral ((Int32) 1); }
2425 | STEP expression { $$ = $2; }
2434 : if_statement_open opt_then if_statement_rest
2438 | if_statement_open THEN pre_embedded_statement
2440 Location l = (Location) oob_stack.Pop ();
2441 tmp_expr = (Expression)expr_stack.Pop();
2442 $$ = new If ((Expression) tmp_expr, end_block(), l);
2446 pre_embedded_statement
2447 : embedded_statement
2449 Statement s = (Statement) $1;
2451 current_block.AddStatement ((Statement) $1);
2456 : IF boolean_expression
2458 oob_stack.Push (lexer.Location);
2460 tmp_expr = (Expression) $2;
2461 expr_stack.Push(tmp_expr);
2475 Location l = (Location) oob_stack.Pop ();
2476 Expression expr = (Expression)expr_stack.Pop();
2477 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2483 Block bl = end_block();
2484 tmp_blocks.Push(bl);
2490 Location l = (Location) oob_stack.Pop ();
2491 tmp_expr = (Expression)expr_stack.Pop();
2492 tmp_block = (Block) tmp_blocks.Pop();
2493 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2497 ELSEIF boolean_expression opt_then
2499 tmp_expr = (Expression) $4;
2500 expr_stack.Push(tmp_expr);
2501 tmp_block = end_block();
2502 tmp_blocks.Push(tmp_block);
2505 else_if_statement_rest
2507 Statement stmt = (Statement) statement_stack.Pop();
2508 Block bl = (Block) tmp_blocks.Pop();
2509 Expression expr = (Expression)expr_stack.Pop();
2510 Location l = (Location) oob_stack.Pop ();
2511 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l);
2516 else_if_statement_rest
2521 Location l = (Location) oob_stack.Pop ();
2523 Expression expr = (Expression)expr_stack.Pop();
2524 Statement stmt = (Statement) new If ((Expression) expr, (Statement) end_block(), l);
2525 statement_stack.Push(stmt);
2531 Block bl = end_block();
2532 tmp_blocks.Push(bl);
2538 Location l = (Location) oob_stack.Pop ();
2540 Expression expr = (Expression)expr_stack.Pop();
2541 Block bl = (Block)tmp_blocks.Pop();
2542 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl , (Statement) end_block(), l);
2543 statement_stack.Push(stmt);
2547 ELSEIF boolean_expression opt_then
2549 expr_stack.Push((Expression) $4);
2550 Block bl = end_block();
2551 tmp_blocks.Push(bl);
2554 else_if_statement_rest
2556 Location l = (Location) oob_stack.Pop ();
2558 Statement tmp_stmt = (Statement)statement_stack.Pop();
2559 Block bl = (Block) tmp_blocks.Pop();
2560 Expression expr = (Expression)expr_stack.Pop();
2561 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
2562 statement_stack.Push(stmt);
2567 : SELECT opt_case expression end_of_stmt
2569 oob_stack.Push (lexer.Location);
2570 switch_stack.Push (current_block);
2575 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2576 current_block = (Block) switch_stack.Pop ();
2581 : /* empty */ { $$ = null; }
2582 | case_sections { $$ = $1; }
2586 : case_sections case_section
2588 ArrayList sections = (ArrayList) $1;
2595 ArrayList sections = new ArrayList ();
2609 : CASE case_clauses ends
2615 //Block topmost = current_block;
2616 Block topmost = end_block();
2618 while (topmost.Implicit)
2619 topmost = topmost.Parent;
2621 // FIXME: This is a horrible hack which MUST go
2622 topmost.statements.Add (new Break (lexer.Location));
2623 $$ = new SwitchSection ((ArrayList) $2, topmost);
2626 /* FIXME: we should somehow flag an error
2627 (BC30321 'Case' cannot follow a 'Case Else'
2628 in the same 'Select' statement.)
2629 if Case Else is not the last of the Case clauses
2636 //Block topmost = current_block;
2637 Block topmost = end_block();
2639 while (topmost.Implicit)
2640 topmost = topmost.Parent;
2642 // FIXME: This is a horrible hack which MUST go
2643 topmost.statements.Add (new Break (lexer.Location));
2645 ArrayList a = new ArrayList();
2646 a.Add (new SwitchLabel (null, lexer.Location));
2647 $$ = new SwitchSection ((ArrayList) a, topmost);
2654 ArrayList labels = new ArrayList ();
2659 | case_clauses COMMA case_clause
2661 ArrayList labels = (ArrayList) ($1);
2669 : opt_is comparison_operator expression
2672 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2694 expression_statement
2695 : statement_expression
2702 statement_expression
2703 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2704 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2705 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2708 object_creation_expression
2709 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2711 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2715 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
2719 array_creation_expression
2720 : object_creation_expression array_initializer
2723 ArrayList dims = new ArrayList();
2725 if (n.Arguments != null) {
2726 foreach (Argument a in n.Arguments) {
2731 Expression atype = n.RequestedType;
2733 if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
2734 VariableDeclaration.VBFixIndexList (ref dims);
2735 $$ = new ArrayCreation (atype, dims, "", (ArrayList) $2, lexer.Location);
2739 string rank = VariableDeclaration.BuildRank (dims);
2740 $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location);
2742 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
2747 : object_creation_expression
2748 | array_creation_expression
2751 declaration_statement
2752 : local_variable_declaration
2755 DictionaryEntry de = (DictionaryEntry) $1;
2757 $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2761 | local_constant_declaration
2764 DictionaryEntry de = (DictionaryEntry) $1;
2766 $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
2771 local_variable_declaration
2772 : DIM variable_declarators
2774 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);
2779 local_constant_declaration
2780 : CONST constant_declarator
2783 $$ = new DictionaryEntry ($1, $2);
2790 : identifier ASSIGN constant_expression
2792 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
2796 variable_declarators
2797 : variable_declarator
2799 ArrayList decl = new ArrayList ();
2803 | variable_declarators COMMA variable_declarator
2805 ArrayList decls = (ArrayList) $1;
2812 : identifier opt_type_character opt_array_name_modifier opt_type_decl opt_variable_initializer
2814 string varname = (string)$1;
2815 current_rank_specifiers = (ArrayList) $3;
2816 object varinit = $5;
2818 ArrayList a_dims = null;
2820 // Some checking is required for particularly weird declarations
2821 // like Dim a As Integer(,)
2823 vartype = (Expression) ((Pair) $4).First;
2825 if ($5 != null && $5 is ArrayList)
2826 Report.Error (205, "End of statement expected.");
2828 ArrayList args = (ArrayList) ((Pair) $4).Second;
2829 if (VariableDeclaration.IndexesSpecifiedInRank (args))
2830 Report.Error (638, "Array bounds cannot appear in type specifiers.");
2832 string s_vartype = vartype.ToString();
2835 for (int x = 0; x < args.Count; x++)
2839 vartype = DecomposeQI(s_vartype, Location.Null);
2842 vartype = ($4 == null) ? (($2 == null) ? TypeManager.system_object_expr : (Expression) $2 ) : (Expression) $4;
2845 Check for a declaration like Dim a(2) or Dim a(2,3)
2846 If this is the case, we must generate an ArrayCreationExpression
2847 and, in case, add the initializer after the array has been created.
2849 if (VariableDeclaration.IsArrayDecl (this)) {
2850 if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) {
2851 a_dims = (ArrayList) current_rank_specifiers;
2852 VariableDeclaration.VBFixIndexLists (ref a_dims);
2853 varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
2856 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
2859 if (vartype is New) {
2860 if (varinit != null) {
2861 Report.Error (30205, lexer.Location, "End of statement expected");
2867 vartype = ((New)vartype).RequestedType;
2870 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
2882 $$ = (Expression) $2;
2888 | AS type rank_specifiers
2890 $$ = TypeManager.system_object_expr;
2899 | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS
2901 $$ = new Pair ($2, $4);
2905 New n = new New ((Expression)$3, null, lexer.Location);
2906 $$ = (Expression) n;
2908 | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2910 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
2911 $$ = (Expression) n;
2915 opt_array_name_modifier
2916 : /* empty */ { $$ = null; }
2917 | array_type_modifier { $$ = $1; }
2921 : rank_specifiers { $$ = $1; }
2924 opt_variable_initializer
2925 : /* empty */ { $$ = null; }
2926 | ASSIGN variable_initializer { $$ = $2; }
2929 variable_initializer
2942 : OPEN_BRACE CLOSE_BRACE
2944 ArrayList list = new ArrayList ();
2947 | OPEN_BRACE variable_initializer_list CLOSE_BRACE
2949 $$ = (ArrayList) $2;
2953 variable_initializer_list
2954 : variable_initializer
2956 ArrayList list = new ArrayList ();
2960 | variable_initializer_list COMMA variable_initializer
2962 ArrayList list = (ArrayList) $1;
2983 ArrayList rs = new ArrayList();
2987 | rank_specifiers rank_specifier
2989 ArrayList rs = (ArrayList) $1;
2996 : OPEN_PARENS opt_dim_separators CLOSE_PARENS
3005 ArrayList ds = new ArrayList();
3006 ds.Add (new EmptyExpression());
3011 ArrayList ds = (ArrayList) $1;
3012 ds.Add (new EmptyExpression());
3024 ArrayList ds = new ArrayList();
3025 ds.Add (new EmptyExpression());
3028 | dim_separators COMMA
3030 ArrayList ds = (ArrayList) $1;
3031 ds.Add (new EmptyExpression());
3039 ArrayList ds = new ArrayList();
3040 ds.Add ((Expression) $1);
3043 | dim_specifiers COMMA expression
3045 ArrayList ds = (ArrayList) $1;
3046 ds.Add ((Expression) $3);
3058 | qualified_identifier
3060 string name = (string) $1;
3062 $$ = DecomposeQI (name, lexer.Location);
3064 | parenthesized_expression
3066 | invocation_expression
3078 | LITERAL_DATE { $$ = new DateLiteral ((DateTime)lexer.Value); }
3079 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
3080 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
3081 | NOTHING { $$ = NullLiteral.Null; }
3085 : LITERAL_SINGLE { $$ = new FloatLiteral ((float) lexer.Value); }
3086 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
3087 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3092 object v = lexer.Value;
3095 $$ = new IntLiteral ((Int32)v);
3096 else if (v is short)
3097 $$ = new ShortLiteral ((Int16)v);
3099 $$ = new LongLiteral ((Int64)v);
3101 Console.WriteLine ("OOPS. Unexpected result from scanner");
3107 : TRUE { $$ = new BoolLiteral (true); }
3108 | FALSE { $$ = new BoolLiteral (false); }
3111 parenthesized_expression
3112 : OPEN_PARENS expression CLOSE_PARENS
3117 : primary_expression DOT identifier
3120 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3123 if (with_stack.Count > 0) {
3124 Expression e = (Expression) with_stack.Peek();
3125 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3133 | primary_expression DOT NEW
3135 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3137 | predefined_type DOT identifier
3140 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3143 if (with_stack.Count > 0) {
3144 Expression e = (Expression) with_stack.Peek();
3145 $$ = new MemberAccess (e, (string) $3, lexer.Location);
3159 invocation_expression
3160 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3163 Location l = lexer.Location;
3164 Report.Error (1, l, "THIS IS CRAZY");
3166 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3167 // Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3172 : MYBASE DOT IDENTIFIER
3174 $$ = new BaseAccess ((string) $3, lexer.Location);
3178 $$ = new BaseAccess ("New", lexer.Location);
3186 The 'argument' rule returns an 'empty' argument
3187 of type NoArg (used for default arguments in invocations)
3188 if no arguments are actually passed.
3190 If there is only one argument and it is o type NoArg,
3191 we return a null (empty) list
3193 ArrayList args = (ArrayList) $1;
3194 if (args.Count == 1 &&
3195 ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3205 ArrayList list = new ArrayList ();
3209 | argument_list COMMA argument
3211 ArrayList list = (ArrayList) $1;
3220 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3222 | BYREF variable_reference
3224 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3228 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3233 : expression {/* note ("section 5.4"); */ $$ = $1; }
3239 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3244 : conditional_expression { $$ = $1; }
3245 | negation_expression
3246 /*| assignment_expression*/
3257 $$ = new This (current_block, lexer.Location);
3261 // FIXME: This is actually somewhat different from Me
3262 // because it is for accessing static (classifier) methods/properties/fields
3263 $$ = new This (current_block, lexer.Location);
3268 : primary_expression
3269 /*| NOT prefixed_unary_expression
3271 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3273 | cast_expression */
3277 : cast_operator OPEN_PARENS expression CLOSE_PARENS
3279 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3281 | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3283 $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3288 : CBOOL { $$ = TypeManager.system_boolean_expr; }
3289 | CBYTE { $$ = TypeManager.system_byte_expr; }
3290 | CCHAR { $$ = TypeManager.system_char_expr; }
3291 | CDATE { $$ = TypeManager.system_date_expr; }
3292 | CDBL { $$ = TypeManager.system_double_expr; }
3293 | CDEC { $$ = TypeManager.system_decimal_expr; }
3294 | CINT { $$ = TypeManager.system_int32_expr; }
3295 | CLNG { $$ = TypeManager.system_int64_expr; }
3296 | COBJ { $$ = TypeManager.system_object_expr; }
3297 | CSHORT { $$ = TypeManager.system_int16_expr; }
3298 | CSNG { $$ = TypeManager.system_single_expr; }
3299 | CSTR { $$ = TypeManager.system_string_expr; }
3303 // The idea to split this out is from Rhys' grammar
3304 // to solve the problem with casts.
3306 prefixed_unary_expression
3308 | PLUS prefixed_unary_expression
3310 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3312 | MINUS prefixed_unary_expression
3314 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3316 | ADDRESSOF prefixed_unary_expression
3318 // FIXME: We should generate an error if AddressOf is NOT used
3319 // during delegate creation
3324 multiplicative_expression
3325 : prefixed_unary_expression
3326 | multiplicative_expression STAR prefixed_unary_expression
3328 $$ = new Binary (Binary.Operator.Multiply,
3329 (Expression) $1, (Expression) $3, lexer.Location);
3331 | multiplicative_expression DIV prefixed_unary_expression
3333 $$ = new Binary (Binary.Operator.Division,
3334 (Expression) $1, (Expression) $3, lexer.Location);
3336 | multiplicative_expression OP_IDIV prefixed_unary_expression
3338 $$ = new Binary (Binary.Operator.Division,
3339 (Expression) $1, (Expression) $3, lexer.Location);
3341 | multiplicative_expression MOD prefixed_unary_expression
3343 $$ = new Binary (Binary.Operator.Modulus,
3344 (Expression) $1, (Expression) $3, lexer.Location);
3349 : multiplicative_expression
3350 | additive_expression PLUS multiplicative_expression
3352 $$ = new Binary (Binary.Operator.Addition,
3353 (Expression) $1, (Expression) $3, lexer.Location);
3355 | additive_expression MINUS multiplicative_expression
3357 $$ = new Binary (Binary.Operator.Subtraction,
3358 (Expression) $1, (Expression) $3, lexer.Location);
3360 | additive_expression OP_CONCAT multiplicative_expression
3362 // FIXME: This should only work for String expressions
3363 // We probably need to use something from the runtime
3364 $$ = new Binary (Binary.Operator.Addition,
3365 (Expression) $1, (Expression) $3, lexer.Location);
3369 relational_expression
3370 : additive_expression
3371 | relational_expression OP_LT additive_expression
3373 $$ = new Binary (Binary.Operator.LessThan,
3374 (Expression) $1, (Expression) $3, lexer.Location);
3376 | relational_expression OP_GT additive_expression
3378 $$ = new Binary (Binary.Operator.GreaterThan,
3379 (Expression) $1, (Expression) $3, lexer.Location);
3381 | relational_expression OP_LE additive_expression
3383 $$ = new Binary (Binary.Operator.LessThanOrEqual,
3384 (Expression) $1, (Expression) $3, lexer.Location);
3386 | relational_expression OP_GE additive_expression
3388 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
3389 (Expression) $1, (Expression) $3, lexer.Location);
3391 | relational_expression IS unary_expression
3393 $$ = new Binary (Binary.Operator.Equality,
3394 (Expression) $1, (Expression) $3, lexer.Location);
3396 | relational_expression AS type_name
3398 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
3403 : relational_expression
3404 | equality_expression ASSIGN relational_expression
3406 $$ = new Binary (Binary.Operator.Equality,
3407 (Expression) $1, (Expression) $3, lexer.Location);
3409 | equality_expression OP_NE relational_expression
3411 $$ = new Binary (Binary.Operator.Inequality,
3412 (Expression) $1, (Expression) $3, lexer.Location);
3417 : equality_expression
3418 | and_expression AND equality_expression
3420 $$ = new Binary (Binary.Operator.BitwiseAnd,
3421 (Expression) $1, (Expression) $3, lexer.Location);
3425 exclusive_or_expression
3427 | exclusive_or_expression OP_XOR and_expression
3429 $$ = new Binary (Binary.Operator.ExclusiveOr,
3430 (Expression) $1, (Expression) $3, lexer.Location);
3434 conditional_and_expression
3435 : exclusive_or_expression
3436 | conditional_and_expression AND exclusive_or_expression
3438 $$ = new Binary (Binary.Operator.LogicalAnd,
3439 (Expression) $1, (Expression) $3, lexer.Location);
3441 | conditional_and_expression ANDALSO exclusive_or_expression
3442 { // FIXME: this is likely to be broken
3443 $$ = new Binary (Binary.Operator.LogicalAnd,
3444 (Expression) $1, (Expression) $3, lexer.Location);
3448 conditional_or_expression
3449 : conditional_and_expression
3450 | conditional_or_expression OR conditional_and_expression
3452 $$ = new Binary (Binary.Operator.LogicalOr,
3453 (Expression) $1, (Expression) $3, lexer.Location);
3455 | conditional_or_expression ORELSE conditional_and_expression
3456 { // FIXME: this is likely to be broken
3457 $$ = new Binary (Binary.Operator.LogicalOr,
3458 (Expression) $1, (Expression) $3, lexer.Location);
3462 conditional_expression
3463 : conditional_or_expression
3466 assignment_expression
3467 : prefixed_unary_expression ASSIGN expression
3469 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3471 | prefixed_unary_expression OP_MULT_ASSIGN expression
3473 Location l = lexer.Location;
3475 $$ = new CompoundAssign (
3476 Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
3478 | prefixed_unary_expression OP_DIV_ASSIGN expression
3480 Location l = lexer.Location;
3482 $$ = new CompoundAssign (
3483 Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3485 | prefixed_unary_expression OP_IDIV_ASSIGN expression
3487 Location l = lexer.Location;
3489 $$ = new CompoundAssign (
3490 Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3492 | prefixed_unary_expression OP_ADD_ASSIGN expression
3494 Location l = lexer.Location;
3496 $$ = new CompoundAssign (
3497 Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3499 | prefixed_unary_expression OP_SUB_ASSIGN expression
3501 Location l = lexer.Location;
3503 $$ = new CompoundAssign (
3504 Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
3506 | prefixed_unary_expression OP_CONCAT_ASSIGN expression
3508 Location l = lexer.Location;
3510 $$ = new CompoundAssign (
3511 Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3524 : type_name { /* class_type */
3526 This does interfaces, delegates, struct_types, class_types,
3527 parent classes, and more! 4.2
3529 $$ = DecomposeQI ((string) $1, lexer.Location);
3539 ArrayList types = new ArrayList ();
3544 | type_list COMMA type
3546 ArrayList types = (ArrayList) $1;
3554 : namespace_or_type_name
3557 namespace_or_type_name
3558 : qualified_identifier
3561 /* Built-in / Integral types */
3563 : OBJECT { $$ = TypeManager.system_object_expr; }
3564 | STRING { $$ = TypeManager.system_string_expr; }
3565 | BOOLEAN { $$ = TypeManager.system_boolean_expr; }
3566 | DECIMAL { $$ = TypeManager.system_decimal_expr; }
3567 | SINGLE { $$ = TypeManager.system_single_expr; }
3568 | DOUBLE { $$ = TypeManager.system_double_expr; }
3569 | DATE { $$ = TypeManager.system_date_expr; }
3575 | BYTE { $$ = TypeManager.system_byte_expr; }
3576 | SHORT { $$ = TypeManager.system_int16_expr; }
3577 | LONG { $$ = TypeManager.system_int64_expr; }
3578 | INTEGER { $$ = TypeManager.system_int32_expr; }
3579 | CHAR { $$ = TypeManager.system_char_expr; }
3595 public Tokenizer Lexer {
3601 public static Expression DecomposeQI (string name, Location loc)
3605 if (name.IndexOf ('.') == -1){
3606 return new SimpleName (name, loc);
3608 int pos = name.LastIndexOf (".");
3609 string left = name.Substring (0, pos);
3610 string right = name.Substring (pos + 1);
3612 o = DecomposeQI (left, loc);
3614 return new MemberAccess (o, right, loc);
3618 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3620 Block implicit_block;
3621 ArrayList inits = null;
3624 // We use the `Used' property to check whether statements
3625 // have been added to the current block. If so, we need
3626 // to create another block to contain the new declaration
3627 // otherwise, as an optimization, we use the same block to
3628 // add the declaration.
3630 // FIXME: A further optimization is to check if the statements
3631 // that were added were added as part of the initialization
3632 // below. In which case, no other statements have been executed
3633 // and we might be able to reduce the number of blocks for
3634 // situations like this:
3636 // int j = 1; int k = j + 1;
3639 VariableDeclaration.FixupTypes (variable_declarators);
3641 if (current_block.Used) {
3642 implicit_block = new Block (current_block, true, loc, Location.Null);
3643 implicit_block.AddChildVariableNames (current_block);
3645 implicit_block = current_block;
3647 foreach (VariableDeclaration decl in variable_declarators){
3648 Expression type = decl.type;
3649 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3650 if (decl.expression_or_array_initializer != null){
3652 inits = new ArrayList ();
3659 return implicit_block;
3661 foreach (VariableDeclaration decl in inits){
3664 Expression type = decl.type;
3666 if ((decl.expression_or_array_initializer is Expression) ||
3667 (decl.expression_or_array_initializer is New)) {
3668 expr = (Expression) decl.expression_or_array_initializer;
3670 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3672 expr = new ArrayCreation (type, "", init, decl.Location);
3675 LocalVariableReference var;
3676 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3678 assign = new Assign (var, expr, decl.Location);
3680 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3683 return implicit_block;
3687 Block declare_local_constant (Expression type, VariableDeclaration decl)
3689 Block implicit_block;
3691 if (current_block.Used)
3692 implicit_block = new Block (current_block, true);
3694 implicit_block = current_block;
3696 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3697 current_local_parameters, decl.Location))){
3700 return implicit_block;
3704 // A class used to pass around variable declarations and constants
3706 public class VariableDeclaration {
3707 public string identifier;
3708 public object expression_or_array_initializer;
3709 public Location Location;
3710 public Attributes OptAttributes;
3711 public Expression type;
3712 public ArrayList dims;
3714 public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
3716 this.identifier = id;
3717 this.expression_or_array_initializer = eoai;
3719 this.OptAttributes = opt_attrs;
3724 public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3728 public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
3732 public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this
3733 (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
3737 public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
3739 // FIXME : This is broken: only the first rank is parsed
3740 return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
3743 public static void FixupTypes (ArrayList vars)
3745 int varcount = vars.Count;
3746 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
3748 if (last_var.type == null)
3749 last_var.type = TypeManager.system_object_expr;
3751 Expression cur_type = last_var.type;
3752 int n = varcount - 1;
3755 VariableDeclaration var = (VariableDeclaration) vars[n--];
3756 if (var.type == null)
3757 var.type = cur_type;
3759 cur_type = var.type;
3763 public static bool IndexesSpecifiedInRank (ArrayList IndexList)
3767 if (IndexList != null) {
3768 foreach (Expression e in IndexList)
3769 if (!(e is EmptyExpression)) {
3778 public static bool IndexesSpecified (ArrayList ranks)
3782 if (ranks != null) {
3783 foreach (ArrayList IndexList in ranks) {
3784 if (IndexesSpecifiedInRank (IndexList)) {
3793 public static string StripDims (string varname, ref string d)
3795 string res = varname;
3798 if (varname.IndexOf("[") >= 0) {
3799 dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3800 res = varname.Substring(0, varname.IndexOf("["));
3806 public static string StripDims (string varname)
3810 return (StripDims(varname, ref dres));
3813 public static string StripIndexesFromDims (string dims)
3815 StringBuilder sb = new StringBuilder();
3817 foreach (char c in dims)
3818 if (c == ',' || c == ']' || c == '[')
3821 return sb.ToString();
3824 public static string BuildRank (ArrayList rank)
3829 for (int x = 0; x < (rank.Count -1 ); x++)
3836 public static string BuildRanks (Parser t)
3840 foreach (ArrayList rank in t.current_rank_specifiers)
3841 res += BuildRank (rank);
3846 public static void VBFixIndexList (ref ArrayList IndexList)
3848 if (IndexList != null) {
3849 for (int x = 0; x < IndexList.Count; x++) {
3850 Expression e = (Expression) IndexList[x];
3851 if (!(e is EmptyExpression)) {
3852 IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
3858 public static bool IsArrayDecl (Parser t)
3860 // return (varname.IndexOf("[") >= 0);
3861 return (t.current_rank_specifiers != null);
3864 public static void VBFixIndexLists (ref ArrayList ranks)
3866 if (ranks != null) {
3867 for (int x = 0; x < ranks.Count; x++) {
3868 ArrayList IndexList = (ArrayList) ranks[x];
3869 VBFixIndexList (ref IndexList);
3874 public static void FixupArrayTypes (ArrayList vars)
3876 int varcount = vars.Count;
3879 foreach (VariableDeclaration var in vars) {
3880 if (var.identifier.EndsWith(",")) {
3881 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","),
3882 var.identifier.LastIndexOf(",")) + "]";
3883 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
3884 var.type = new ComposedCast (var.type, (string) dims, var.Location);
3891 public Property BuildSimpleProperty (Expression p_type, string name,
3892 Field p_fld, int mod_flags,
3893 Attributes attrs, Location loc)
3896 Block get_block, set_block;
3897 Accessor acc_set, acc_get;
3898 StatementExpression a_set;
3903 Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
3904 args = new Parameter [1];
3905 args [0] = implicit_value_parameter;
3907 Parameters set_params = new Parameters (args, null, loc);
3908 a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
3909 (Expression) new SimpleName("value", loc), loc), loc);
3911 set_block = new Block (current_block, set_params, loc, Location.Null);
3912 set_block.AddStatement ((Statement) a_set);
3913 acc_set = new Accessor (set_block, attrs);
3916 a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
3917 get_block = new Block (current_block, null, loc, Location.Null);
3918 get_block.AddStatement ((Statement) a_get);
3919 acc_get = new Accessor (get_block, attrs);
3921 p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
3928 current_block = new Block (current_block, current_local_parameters,
3929 lexer.Location, Location.Null);
3936 while (current_block.Implicit)
3937 current_block = current_block.Parent;
3939 res = current_block;
3941 current_block.SetEndLocation (lexer.Location);
3942 current_block = current_block.Parent;
3947 private void AddHandler (Expression evt_definition, string handler_name)
3949 AddHandler (current_block, evt_definition, handler_name);
3952 void CheckAttributeTarget (string a)
3956 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3960 Location l = lexer.Location;
3961 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3966 private void AddHandler (Block b, Expression evt_id, string handler_name)
3968 Location loc = lexer.Location;
3969 string evt_target = evt_id.ToString();
3970 evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
3971 Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
3975 private void RaiseEvent (string evt_name, ArrayList args)
3977 Location loc = lexer.Location;
3979 Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
3980 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc));
3981 current_block.AddStatement (s);
3984 // FIXME: THIS DOES NOT WORK!!!
3985 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
3987 Location loc = lexer.Location;
3988 ArrayList neh_args = new ArrayList();
3989 neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
3991 ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
3993 CompoundAssign ca = new CompoundAssign (
3994 Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
3996 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc));
4001 // This method is used to get at the complete string representation of
4002 // a fully-qualified type name, hiding inside a MemberAccess ;-)
4003 // This is necessary because local_variable_type admits primary_expression
4004 // as the type of the variable. So we do some extra checking
4006 string GetQualifiedIdentifier (Expression expr)
4008 if (expr is SimpleName)
4009 return ((SimpleName)expr).Name;
4010 else if (expr is MemberAccess)
4011 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4013 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4017 private void RemoveHandler (Expression evt_definition, string handler_name)
4019 RemoveHandler (current_block, evt_definition, handler_name);
4022 private ConstructorInitializer FixConstructorInitializer (ref ArrayList s)
4024 ConstructorInitializer ci = null;
4027 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4028 Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4030 if (i.expr is BaseAccess) {
4031 BaseAccess ba = (BaseAccess) i.expr;
4032 if (ba.member == "New" || ba.member == ".ctor") {
4033 ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4037 if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
4038 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location);
4046 void Error_ExpectingTypeName (Location l, Expression expr)
4048 if (expr is Invocation){
4049 Report.Error (1002, l, "; expected");
4051 Report.Error (-1, l, "Invalid Type definition");
4055 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4059 private void ReportError9998()
4061 Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4064 protected override int parse ()
4066 current_namespace = new Namespace (null, RootContext.RootNamespace);
4067 foreach(string preImportedNamespace in ImportsList)
4068 current_namespace.Using(preImportedNamespace, Location.Null);
4069 current_container = RootContext.Tree.Types;
4070 current_container.Namespace = current_namespace;
4071 oob_stack = new Stack ();
4072 switch_stack = new Stack ();
4073 expr_stack = new Stack ();
4074 tmp_blocks = new Stack();
4075 with_stack = new Stack();
4076 statement_stack = new Stack();
4078 UseExtendedSyntax = name.EndsWith(".mbs");
4079 OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4080 OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4081 OptionCompareBinary = InitialOptionCompareBinary;
4083 lexer = new Tokenizer (input, name, defines);
4084 StringBuilder value = new StringBuilder ();
4085 //yacc_verbose_flag=true;
4088 if (yacc_verbose_flag)
4089 yyparse (lexer, new yydebug.yyDebugSimple ());
4095 Report.Error (29999, lexer.Location, lexer.location + "\nParsing error in " + lexer.ref_name + "\n" + e.ToString());
4098 return Report.Errors;