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
27 public class Parser : GenericParser
32 /// Current block is used to add statements as we find
38 /// Tmp block is used to store block endings in if/select's
43 /// Tmp block is used to store tmp copies of expressions
48 /// Tmp catch is used to store catch clauses in try..catch..finally
50 ArrayList tmp_catch_clauses;
53 /// Current interface is used by the various declaration
54 /// productions in the interface declaration to "add"
55 /// the interfaces as we find them.
57 Interface current_interface;
60 /// This is used by the unary_expression code to resolve
61 /// a name against a parameter.
63 Parameters current_local_parameters;
66 /// This are used when parsing parameters in property
69 Parameters set_parameters;
70 Parameters get_parameters;
73 /// This is used by the sub_header parser to store modifiers
74 /// to be passed to sub/constructor
76 int current_modifiers;
79 /// This is used by the sub_header parser to store attributes
80 /// to be passed to sub/constructor
82 Attributes current_attributes;
85 /// Using during property parsing to describe the implicit
86 /// value parameter that is passed to the "set" accessor
89 string get_implicit_value_parameter_name;
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).
96 Expression get_implicit_value_parameter_type;
99 /// Using during property parsing to describe the implicit
100 /// value parameter that is passed to the "set" accessor
103 string set_implicit_value_parameter_name;
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).
110 Expression set_implicit_value_parameter_type;
112 // An out-of-band stack.
116 ArrayList current_rank_specifiers;
124 // Expression stack for nested ifs
128 Stack statement_stack;
132 static public bool InitialOptionExplicit = false;
133 static public bool InitialOptionStrict = false;
134 static public bool InitialOptionCompareBinary = true;
138 bool OptionCompareBinary;
140 static public bool UseExtendedSyntax; // for ".mbs" files
142 public override string[] extensions()
144 string [] list = { ".vb", ".mbs" };
151 %token NONE /* This token is never returned by our lexer */
152 %token ERROR // This is used not by the parser, but by the tokenizer.
156 *These are the MonoBASIC keywords
245 %token NOTINHERITABLE
246 %token NOTOVERRIDABLE
301 %token YIELD // MonoBASIC extension
303 /* MonoBASIC single character operators/punctuation. */
305 %token OPEN_BRACKET "["
306 %token CLOSE_BRACKET "]"
307 %token OPEN_PARENS "("
308 %token OPEN_BRACE "{"
309 %token CLOSE_BRACE "}"
310 %token CLOSE_PARENS ")"
327 %token ATTR_ASSIGN ":="
329 /* MonoBASIC multi-character operators. */
334 //%token OP_AND "and"
337 //%token OP_MODULUS //"mod"
338 %token OP_MULT_ASSIGN "*="
339 %token OP_DIV_ASSIGN "/="
340 %token OP_IDIV_ASSIGN "\\="
341 %token OP_ADD_ASSIGN "+="
342 %token OP_SUB_ASSIGN "-="
343 %token OP_CONCAT_ASSIGN "&="
344 %token OP_EXP_ASSIGN "^="
347 %token LITERAL_INTEGER "int literal"
348 %token LITERAL_SINGLE "float literal"
349 %token LITERAL_DOUBLE "double literal"
350 %token LITERAL_DECIMAL "decimal literal"
351 %token LITERAL_CHARACTER "character literal"
352 %token LITERAL_STRING "string literal"
356 /* Add precedence rules to solve dangling else s/r conflict */
365 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
367 %left STAR DIV PERCENT
368 %right BITWISE_NOT CARRET UMINUS
369 %nonassoc OP_INC OP_DEC
371 %left OPEN_BRACKET OPEN_BRACE
376 %start compilation_unit
380 : opt_option_directives
381 opt_imports_directives
390 opt_option_directives
397 | option_directives option_directive
401 : option_explicit_directive
402 | option_strict_directive
403 | option_compare_directive
432 option_explicit_directive
433 : OPTION EXPLICIT on_off EOL
435 if (!UseExtendedSyntax)
436 OptionExplicit = (bool)$3;
439 9999, lexer.Location,
440 "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");
445 option_strict_directive
446 : OPTION STRICT on_off EOL
448 if (!UseExtendedSyntax)
449 OptionStrict = (bool)$3;
452 9999, lexer.Location,
453 "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");
457 option_compare_directive
458 : OPTION COMPARE text_or_binary EOL
460 OptionCompareBinary = (bool)$3;
471 | declarations declaration
475 : namespace_declaration
482 Class c = (Class) $1;
483 mod_flags = c.ModFlags;
485 } else if ($1 is Struct){
486 Struct s = (Struct) $1;
487 mod_flags = s.ModFlags;
489 } else if ($1 is Module){
490 Module m = (Module) $1;
491 mod_flags = m.ModFlags;
496 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
498 1527, lexer.Location,
499 "Namespace elements cannot be explicitly " +
500 "declared private or protected in '" + name + "'");
516 | qualified_identifier DOT identifier
518 $$ = (($1).ToString ()) + "." + ($3.ToString ());
521 opt_imports_directives
528 | imports_directives imports_directive
532 : IMPORTS imports_terms EOL
537 | imports_terms COMMA imports_terms
541 : qualified_identifier
543 current_namespace.Using ((string) $1, lexer.Location);
545 | qualified_identifier ASSIGN qualified_identifier
547 current_namespace.UsingAlias ((string) $1, (string) $3, lexer.Location);
553 | attribute_sections { $$ = $1; }
559 AttributeSection sect = (AttributeSection) $1;
561 if (sect.Target == "assembly")
562 RootContext.AddGlobalAttributeSection (current_container, sect);
564 $$ = new Attributes ((AttributeSection) $1, lexer.Location);
568 FIXME: we should check if extended syntax is enabled;
569 otherwise an exception should be thrown since VB.NET
570 only allows one attribute section
572 | attribute_sections attribute_section
574 Attributes attrs = null;
575 AttributeSection sect = (AttributeSection) $2;
577 if (sect.Target == "assembly")
578 RootContext.AddGlobalAttributeSection (current_container, sect);
581 attrs = (Attributes) $1;
582 attrs.AddAttributeSection (sect);
590 : OP_LT attribute_target_specifier attribute_list OP_GT
592 string target = null;
595 target = (string) $2;
597 $$ = new AttributeSection (target, (ArrayList) $3);
599 | OP_LT attribute_list OP_GT
601 $$ = new AttributeSection (null, (ArrayList) $2);
605 attribute_target_specifier
606 : attribute_target COLON
615 CheckAttributeTarget ((string) $1);
618 | EVENT { $$ = "event"; }
619 | RETURN { $$ = "return"; }
625 ArrayList attrs = new ArrayList ();
631 | attribute_list COMMA attribute
633 ArrayList attrs = (ArrayList) $1;
645 opt_attribute_arguments
647 $$ = new Mono.CSharp.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
655 opt_attribute_arguments
656 : /* empty */ { $$ = null; }
657 | OPEN_PARENS attribute_arguments CLOSE_PARENS
664 : opt_positional_argument_list
669 ArrayList args = new ArrayList ();
675 | positional_argument_list COMMA named_argument_list
677 ArrayList args = new ArrayList ();
683 | named_argument_list
685 ArrayList args = new ArrayList ();
694 opt_positional_argument_list
695 : /* empty */ { $$ = null; }
696 | positional_argument_list
699 positional_argument_list
702 ArrayList args = new ArrayList ();
703 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
707 | positional_argument_list COMMA expression
709 ArrayList args = (ArrayList) $1;
710 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
719 ArrayList args = new ArrayList ();
724 | named_argument_list COMMA named_argument
726 ArrayList args = (ArrayList) $1;
734 : identifier ATTR_ASSIGN expression
736 $$ = new DictionaryEntry (
738 new Argument ((Expression) $3, Argument.AType.Expression));
742 namespace_declaration
743 : opt_attributes NAMESPACE qualified_identifier EOL
745 Attributes attrs = (Attributes) $1;
748 foreach (AttributeSection asec in attrs.AttributeSections)
749 if (asec.Target == "assembly")
750 RootContext.AddGlobalAttributeSection (current_container, asec);
753 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$3);
755 opt_imports_directives
759 current_namespace = current_namespace.Parent;
767 current_attributes = (Attributes) $1;
768 current_modifiers = (int) $2;
770 type_spec_declaration
773 type_spec_declaration
776 | interface_declaration
777 | delegate_declaration
783 : CLASS identifier EOL opt_class_base
788 name = MakeName ((string) $2);
789 new_class = new Class (current_container, name, current_modifiers,
790 (Attributes) current_attributes, lexer.Location);
792 current_container = new_class;
793 current_container.Namespace = current_namespace;
794 RootContext.Tree.RecordDecl (name, new_class);
796 opt_class_member_declarations
799 Class new_class = (Class) current_container;
800 new_class.Bases = (ArrayList) $4;
802 current_container = current_container.Parent;
803 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
810 : /* empty */ { $$ = null; }
811 | class_base { $$ = $1; }
815 : inherits_or_implements type_list EOL { $$ = $2; }
818 inherits_or_implements
824 : /* empty */ { $$ = (int) 0; current_modifiers = 0; }
825 | modifiers { $$ = $1; current_modifiers = (int) $1; }
835 if ((m1 & m2) != 0) {
836 Location l = lexer.Location;
837 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
839 $$ = (int) (m1 | m2);
844 : PUBLIC { $$ = Modifiers.PUBLIC; }
845 | PROTECTED { $$ = Modifiers.PROTECTED; }
846 | PRIVATE { $$ = Modifiers.PRIVATE; }
847 | SHARED { $$ = Modifiers.STATIC; }
848 | FRIEND { $$ = Modifiers.INTERNAL; }
849 | OVERRIDES { $$ = Modifiers.OVERRIDE; }
850 | OVERRIDABLE { $$ = Modifiers.VIRTUAL; }
851 | NOTOVERRIDABLE { $$ = 0; }
852 | OVERLOADS { $$ = 0; }
853 | MUSTINHERIT { $$ = Modifiers.ABSTRACT; }
857 : MODULE identifier EOL
861 name = MakeName((string) $2);
862 new_module = new Module(current_container,
864 current_modifiers, // already checks then
865 (Attributes) current_attributes,
867 current_container = new_module;
868 current_container.Namespace = current_namespace;
869 RootContext.Tree.RecordDecl(name, new_module);
871 opt_module_member_declarations
874 Module new_module = (Module)current_container;
876 current_container = current_container.Parent;
877 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
883 opt_module_member_declarations
885 | module_member_declarations
888 module_member_declarations
889 : module_member_declaration
890 | module_member_declarations module_member_declaration
893 module_member_declaration
897 current_attributes = (Attributes) $1;
898 current_modifiers = (int) $2 | (int)Modifiers.STATIC; // FIXME: for type_declaration it can result in trouble
900 module_member_declarator
906 module_member_declarator
907 : static_constructor_declaration
910 Method method = (Method) $1;
911 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
914 | withevents_declaration /* This is a field but must be treated specially, see below */
915 | constant_declaration
916 | property_declaration
921 constant_declaration // TODO: implement truly the logic
922 : CONST identifier ASSIGN primary_expression EOL
923 | CONST identifier AS type ASSIGN constant_expression EOL
926 opt_class_member_declarations
928 | class_member_declarations
931 class_member_declarations
932 : class_member_declaration
933 | class_member_declarations class_member_declaration
936 class_member_declaration
940 current_attributes = (Attributes) $1;
941 current_modifiers = (int) $2;
943 class_member_declarator
949 class_member_declarator
950 : constructor_declaration
953 Method method = (Method) $1;
954 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
957 | constant_declaration
958 | property_declaration
960 | withevents_declaration /* This is a field but must be treated specially, see below */
961 /*| type_declaration */
970 | must_override_declaration
973 must_override_declaration
974 : must_override_sub_declaration
975 | must_override_func_declaration
978 must_override_sub_declaration
979 : MUSTOVERRIDE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
981 if (current_container is Module)
982 Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
984 if (current_container is Struct)
985 Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
987 current_modifiers |= Modifiers.ABSTRACT;
989 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3,
990 (Parameters) $5, null, null, lexer.Location);
992 if (!(current_container is Class))
993 Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
995 // FIXME ASAP: This will crash the compiler at resolution time
1000 must_override_func_declaration
1001 : MUSTOVERRIDE FUNCTION identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type EOL
1003 if (current_container is Module)
1004 Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
1006 if (current_container is Struct)
1007 Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
1009 current_modifiers |= Modifiers.ABSTRACT;
1011 Method method = new Method ((Expression) $8, (int) current_modifiers, (string) $3,
1012 (Parameters) $5, null, null, lexer.Location);
1014 if (!(current_container is Class))
1015 Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
1017 // FIXME ASAP: This will crash the compiler at resolution time
1023 : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
1025 current_local_parameters = (Parameters) $4;
1028 /* This is WEIRD: declaring a method (sub) in a module as static will
1029 trigger a syntax error, but the same methods MUST be static in order
1030 to be properly called
1032 /* THIS SHOULD NOT BE NEEDED ANYMORE
1033 if (current_container is Module) {
1034 if ((current_modifiers & Modifiers.STATIC) != 0) {
1035 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1039 current_modifiers = Modifiers.STATIC;
1044 // Structure members are Public by default
1045 if ((current_container is Struct) && (current_modifiers == 0))
1046 current_modifiers = Modifiers.PUBLIC;
1051 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
1052 (Parameters) current_local_parameters, null, (Expression) $7,
1055 method.Block = (Block) end_block();
1058 if ($6 != null) { /* we have an event handler to take care of */
1059 // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
1060 string evt_def = ((MemberAccess)$6).ToString();
1061 int pos = evt_def.LastIndexOf (".");
1062 string evt_target = ((string) $2).Substring (0, pos);
1064 foreach (Property p in current_container.Properties) {
1065 if (p.Name == evt_target) {
1067 // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
1068 AddHandler (p.Set.Block, (Expression)$6, (string) $2);
1077 : FUNCTION identifier
1078 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type opt_implement_clause EOL
1081 current_local_parameters = (Parameters) $4;
1084 /* This is WEIRD: declaring a method (sub) in a module as static will
1085 trigger a syntax error, but the same methods MUST be static in order
1086 to be properly called
1088 /* THIS SHOULD NOT BE NEEDED ANYMORE
1089 if (current_container is Module) {
1090 if ((current_modifiers & Modifiers.STATIC) != 0) {
1091 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1095 current_modifiers |= Modifiers.STATIC;
1099 // Structure members are Public by default
1100 if ((current_container is Struct) && (current_modifiers == 0))
1101 current_modifiers = Modifiers.PUBLIC;
1102 // Add local var declaration
1104 ArrayList retval = new ArrayList ();
1105 retval.Add (new VariableDeclaration ((string) $2, (Expression) $7, lexer.Location));
1106 declare_local_variables ((Expression) $7, retval, lexer.Location);
1111 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
1112 (Parameters) current_local_parameters, null,
1113 (Expression) $7, lexer.Location);
1114 method.Block = end_block();
1116 /*Console.WriteLine ("Declaring Function '{0}' with {1} statements and {2} arguments",
1117 current_container.Name + "." + (string) $2,
1118 method.Block.statements.Count,
1119 current_local_parameters.FixedParameters != null ? current_local_parameters.FixedParameters.Length : 0);
1125 : STRUCTURE identifier EOL
1126 opt_implement_clause
1129 string full_struct_name = MakeName ((string) $2);
1131 new_struct = new Struct (current_container, full_struct_name,
1132 (int) current_modifiers,
1133 (Attributes) current_attributes, lexer.Location);
1134 current_container = new_struct;
1135 current_container.Namespace = current_namespace;
1136 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1138 opt_struct_member_declarations
1140 Struct new_struct = (Struct) current_container;
1143 new_struct.Bases = (ArrayList) $4;
1145 current_container = current_container.Parent;
1146 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1152 opt_struct_member_declarations
1154 | struct_member_declarations
1157 struct_member_declarations
1158 : struct_member_declaration
1159 | struct_member_declarations struct_member_declaration
1162 struct_member_declaration
1164 struct_member_declarator
1166 struct_member_declarator
1168 //| constant_declaration
1169 | method_declaration
1170 | property_declaration
1172 | constructor_declaration
1176 * This is only included so we can flag error 575:
1177 * destructors only allowed on class types
1179 //| destructor_declaration
1183 : EVENT identifier AS type EOL
1185 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1187 Event e = new Event ((Expression) $4, var.identifier,
1188 null, current_modifiers, null, null,
1189 current_attributes, lexer.Location);
1191 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1194 // | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1196 // throw new NotSupportedException();
1201 : ENUM identifier opt_type_spec EOL
1202 opt_enum_member_declarations
1204 Location enum_location = lexer.Location;
1205 string full_name = MakeName ((string) $2);
1206 Expression enum_type = ($3 == null) ? TypeManager.system_int32_expr : (Expression) $3;
1207 ArrayList enum_members = (ArrayList) $5;
1209 Mono.CSharp.Enum e = new Mono.CSharp.Enum (current_container, enum_type,
1210 (int) current_modifiers, full_name,
1211 (Attributes) current_attributes, enum_location);
1213 foreach (VariableDeclaration ev in enum_members) {
1214 Location loc = (Location) ev.Location;
1216 CheckDef (e.AddEnumMember (ev.identifier,
1217 (Expression) ev.expression_or_array_initializer,
1218 loc, ev.OptAttributes), ev.identifier, loc);
1221 e.Namespace = current_namespace;
1223 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1224 RootContext.Tree.RecordDecl (full_name, e);
1230 opt_enum_member_declarations
1231 : /* empty */ { $$ = new ArrayList (); }
1232 | enum_member_declarations { $$ = $1; }
1235 enum_member_declarations
1236 : enum_member_declaration
1238 ArrayList l = new ArrayList ();
1243 | enum_member_declarations enum_member_declaration
1245 ArrayList l = (ArrayList) $1;
1253 enum_member_declaration
1254 : opt_attributes identifier EOL
1256 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1258 | opt_attributes identifier
1260 $$ = lexer.Location;
1262 ASSIGN expression EOL
1264 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1268 interface_declaration
1269 : INTERFACE identifier EOL
1271 Interface new_interface;
1272 string full_interface_name = MakeName ((string) $2);
1274 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1275 (Attributes) current_attributes, lexer.Location);
1276 if (current_interface != null) {
1277 Location l = lexer.Location;
1278 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1280 current_interface = new_interface;
1281 new_interface.Namespace = current_namespace;
1282 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1287 Interface new_interface = (Interface) current_interface;
1290 new_interface.Bases = (ArrayList) $5;
1292 current_interface = null;
1293 CheckDef (current_container.AddInterface (new_interface),
1294 new_interface.Name, new_interface.Location);
1301 : /* empty */ { $$ = null; }
1306 : INHERITS interface_type_list { $$ = $2; }
1312 ArrayList interfaces = new ArrayList ();
1314 interfaces.Add ($1);
1317 | interface_type_list COMMA interface_type
1319 ArrayList interfaces = (ArrayList) $1;
1320 interfaces.Add ($3);
1326 : opt_interface_member_declarations
1329 opt_interface_member_declarations
1331 | interface_member_declarations
1334 interface_member_declarations
1335 : interface_member_declaration
1336 | interface_member_declarations interface_member_declaration
1339 interface_member_declaration
1340 : interface_method_declaration
1342 InterfaceMethod m = (InterfaceMethod) $1;
1344 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1346 | interface_property_declaration
1348 InterfaceProperty p = (InterfaceProperty) $1;
1350 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1352 | interface_event_declaration
1354 InterfaceEvent e = (InterfaceEvent) $1;
1356 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1361 : /* empty */ { $$ = false; }
1362 | NEW { $$ = true; }
1365 interface_method_declaration
1367 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1369 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1370 (Parameters) $4, current_attributes, lexer.Location);
1372 | FUNCTION identifier
1373 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1375 $$ = new InterfaceMethod (
1376 (Expression) $7, (string) $2, false, (Parameters) $4,
1377 current_attributes, lexer.Location);
1381 interface_property_declaration
1382 : PROPERTY identifier
1384 opt_formal_parameter_list
1385 CLOSE_PARENS opt_type_spec EOL
1387 // FIXME we MUST pass property parameters
1388 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1389 true, true, current_attributes,
1394 opt_access_specifier
1396 | READONLY { $$ = Modifiers.READONLY; }
1397 | WRITEONLY { $$ = 0; }
1398 | DEFAULT { $$ = 0; }
1401 interface_event_declaration
1402 : opt_attributes opt_new EVENT type identifier EOL
1404 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1409 property_declaration
1410 : opt_access_specifier opt_modifiers PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
1412 get_implicit_value_parameter_type = (Expression) $7;
1413 get_implicit_value_parameter_name = (string) $4;
1415 current_modifiers = (int) $2;
1417 current_local_parameters = (Parameters) $5;
1418 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
1419 get_parameters = current_local_parameters.Copy (lexer.Location);
1420 set_parameters = current_local_parameters.Copy (lexer.Location);
1424 get_parameters = Parameters.EmptyReadOnlyParameters;
1425 set_parameters = new Parameters (null, null ,lexer.Location);
1427 lexer.PropertyParsing = true;
1429 $$ = lexer.Location;
1431 accessor_declarations
1434 lexer.PropertyParsing = false;
1437 Pair pair = (Pair) $11;
1438 Accessor get_block = (Accessor) pair.First;
1439 Accessor set_block = (Accessor) pair.Second;
1441 Location loc = lexer.Location;
1443 // Structure members are Public by default
1444 if ((current_container is Struct) && (current_modifiers == 0))
1445 current_modifiers = Modifiers.PUBLIC;
1447 prop = new Property ((Expression) $7, (string) $4, current_modifiers, get_block, set_block,
1448 current_attributes, loc, set_implicit_value_parameter_name,
1449 get_parameters, set_parameters, (Expression) $8);
1451 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1452 get_implicit_value_parameter_type = null;
1453 set_implicit_value_parameter_type = null;
1454 get_parameters = null;
1455 set_parameters = null;
1456 current_local_parameters = null;
1460 opt_property_parameters
1463 $$ = Parameters.EmptyReadOnlyParameters;
1465 | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1471 opt_implement_clause
1476 | IMPLEMENTS qualified_identifier
1478 $$ = DecomposeQI ((string)$2, lexer.Location);
1482 accessor_declarations
1483 : get_accessor_declaration opt_set_accessor_declaration
1485 $$ = new Pair ($1, $2);
1487 | set_accessor_declaration opt_get_accessor_declaration
1489 $$ = new Pair ($2, $1);
1493 opt_get_accessor_declaration
1494 : /* empty */ { $$ = null; }
1495 | get_accessor_declaration
1498 opt_set_accessor_declaration
1499 : /* empty */ { $$ = null; }
1500 | set_accessor_declaration
1503 get_accessor_declaration
1504 : opt_attributes GET EOL
1506 current_local_parameters = get_parameters;
1508 lexer.PropertyParsing = false;
1511 // Add local var declaration
1513 ArrayList retval = new ArrayList ();
1514 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1515 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
1521 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1522 current_local_parameters = null;
1523 lexer.PropertyParsing = true;
1527 set_accessor_declaration
1528 : opt_attributes SET opt_set_parameter EOL
1530 Parameter implicit_value_parameter = new Parameter (
1531 set_implicit_value_parameter_type,
1532 set_implicit_value_parameter_name,
1533 Parameter.Modifier.NONE, null);
1535 current_local_parameters = set_parameters;
1536 current_local_parameters.AppendParameter (implicit_value_parameter);
1539 lexer.PropertyParsing = false;
1544 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1545 current_local_parameters = null;
1546 lexer.PropertyParsing = true;
1553 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
1554 set_implicit_value_parameter_name = "Value";
1556 | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
1558 /* FIXME: possible syntax error which must be caught
1559 Set ( As <type>) is currently (and wrongly so) legal
1561 set_implicit_value_parameter_type = (Expression) $3;
1563 set_implicit_value_parameter_name = (string) $2;
1565 set_implicit_value_parameter_name = "Value";
1571 variable_declarators EOL
1573 int mod = (int) current_modifiers;
1576 VariableDeclaration.FixupTypes ((ArrayList) $2);
1577 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1579 if (current_container is Module)
1580 mod = mod | Modifiers.STATIC;
1582 // Structure members are Public by default
1583 if ((current_container is Struct) && (mod == 0))
1584 mod = Modifiers.PUBLIC;
1586 foreach (VariableDeclaration var in (ArrayList) $2){
1587 Location l = var.Location;
1589 Field field = new Field (var.type, mod, var.identifier,
1590 var.expression_or_array_initializer,
1591 (Attributes) null, l);
1593 CheckDef (current_container.AddField (field), field.Name, l);
1598 withevents_declaration
1599 : WITHEVENTS variable_declarators EOL
1601 /* WithEvents Fields must be resolved into properties
1602 with a bit of magic behind the scenes */
1604 VariableDeclaration.FixupTypes ((ArrayList) $2);
1606 foreach (VariableDeclaration var in (ArrayList) $2) {
1607 // 1 - We create a private field
1608 Location l = var.Location;
1610 if ((current_modifiers & Modifiers.STATIC) > 0)
1611 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1613 Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier,
1614 var.expression_or_array_initializer,
1615 (Attributes) null, l);
1617 CheckDef (current_container.AddField (field), field.Name, l);
1619 // 2 - Public property
1621 prop = BuildSimpleProperty (var.type, (string) var.identifier,
1622 field, (int) current_modifiers,
1623 (Attributes) current_attributes, l);
1625 CheckDef (current_container.AddProperty (prop), prop.Name, l);
1635 delegate_declaration
1637 identifier OPEN_PARENS
1638 opt_formal_parameter_list
1642 Location l = lexer.Location;
1643 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr,
1644 (int) current_modifiers,
1645 MakeName ((string) $3), (Parameters) $5,
1646 (Attributes) current_attributes, l);
1648 del.Namespace = current_namespace;
1649 CheckDef (current_container.AddDelegate (del), del.Name, l);
1652 identifier OPEN_PARENS
1653 opt_formal_parameter_list
1654 CLOSE_PARENS AS type
1656 Location l = lexer.Location;
1657 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
1659 (Expression) $8, (int) current_modifiers, MakeName ((string) $3),
1660 (Parameters) $5, (Attributes) current_attributes, l);
1662 del.Namespace = current_namespace;
1663 CheckDef (current_container.AddDelegate (del), del.Name, l);
1670 | HANDLES qualified_identifier
1672 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);
1674 | HANDLES MYBASE DOT qualified_identifier
1676 // FIXME: this is blatantly wrong and crash-prone
1677 $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
1683 | OPEN_PARENS CLOSE_PARENS
1686 static_constructor_declaration
1687 : SHARED SUB NEW opt_empty_parens EOL
1689 current_local_parameters = Parameters.EmptyReadOnlyParameters;
1691 oob_stack.Push (lexer.Location);
1693 Location l = (Location) oob_stack.Pop ();
1694 $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
1698 Constructor c = (Constructor) $1;
1699 c.Block = (Block) end_block();
1700 c.ModFlags = (int) current_modifiers;
1701 c.OptAttributes = current_attributes;
1703 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1704 current_local_parameters = null;
1708 constructor_declaration
1709 : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1711 current_local_parameters = (Parameters) $4;
1713 oob_stack.Push (lexer.Location);
1715 Location l = (Location) oob_stack.Pop ();
1716 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1721 Constructor c = (Constructor) $1;
1722 c.Block = (Block) end_block();
1723 c.ModFlags = (int) current_modifiers;
1724 c.OptAttributes = current_attributes;
1726 // FIXME: This should happen at grammar level, but doing it
1727 // triggers a lot of conflicts/problems.
1728 c.Initializer = FixConstructorInitializer (ref c.Block.statements);
1730 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1731 current_local_parameters = null;
1736 opt_formal_parameter_list
1739 $$ = Parameters.EmptyReadOnlyParameters;
1741 | formal_parameter_list
1744 //Parameter p = ((Parameters) $1).FixedParameters[0];
1748 formal_parameter_list
1751 ArrayList pars_list = (ArrayList) $1;
1753 Parameter [] pars = new Parameter [pars_list.Count];
1754 pars_list.CopyTo (pars);
1755 $$ = new Parameters (pars, null, lexer.Location);
1757 | fixed_parameters COMMA parameter_array
1759 ArrayList pars_list = (ArrayList) $1;
1761 Parameter [] pars = new Parameter [pars_list.Count];
1762 pars_list.CopyTo (pars);
1764 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
1768 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1775 ArrayList pars = new ArrayList ();
1780 | fixed_parameters COMMA fixed_parameter
1782 ArrayList pars = (ArrayList) $1;
1791 opt_parameter_modifier
1792 identifier opt_rank_specifiers opt_type_spec opt_variable_initializer
1794 Parameter.Modifier pm = (Parameter.Modifier)$2;
1795 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1798 if (opt_parm && ($6 == null))
1799 Report.Error (999, "Optional parameters must have a default value");
1802 if ((pm & Parameter.Modifier.REF) !=0)
1803 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1805 pm = Parameter.Modifier.NONE; //FIXME: should take into account BYREF
1809 ptype = (Expression) $5;
1812 //string t = ((Expression) $5).ToString() + (string) $4;
1813 string t = ((Expression) $5).ToString() + VariableDeclaration.BuildRank ((ArrayList) $4);
1814 ptype = DecomposeQI (t, lexer.Location);
1816 $$ = new Parameter (ptype, (string) $3, pm,
1817 (Attributes) $1, (Expression) $6, opt_parm);
1822 : PARAM_ARRAY identifier opt_parens AS type
1824 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1825 // note ("type must be a single-dimension array type");
1831 | OPEN_PARENS CLOSE_PARENS
1834 opt_parameter_modifier
1835 : /* empty */ { $$ = Parameter.Modifier.VAL; }
1836 | parameter_modifiers { $$ = $1; }
1840 : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1841 | parameter_modifier { $$ = $1; }
1845 : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1846 | BYVAL { $$ = Parameter.Modifier.VAL; }
1847 | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; }
1852 | statement_list end_of_stmt
1857 | statement_list end_of_stmt statement
1861 declaration_statement
1863 if ($1 != null && (Block) $1 != current_block){
1864 current_block.AddStatement ((Statement) $1);
1865 current_block = (Block) $1;
1868 | embedded_statement
1870 Statement s = (Statement) $1;
1872 current_block.AddStatement ((Statement) $1);
1875 | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1877 AddHandler ((Expression) $2, (string) $5);
1879 | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1881 RaiseEvent ((string) $2, (ArrayList) $4);
1883 | array_handling_statement
1884 /* | empty_statement */
1888 : identifier COLON end_of_stmt
1890 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1892 if (!current_block.AddLabel ((string) $1, labeled)){
1893 Location l = lexer.Location;
1894 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1896 current_block.AddStatement (labeled);
1902 : expression_statement
1903 | selection_statement
1904 | iteration_statement
1912 $$ = new EmptyStatement ();
1917 array_handling_statement
1923 : REDIM opt_preserve invocation_expression opt_array_initializer
1925 Invocation i = (Invocation) $3;
1926 ReDim r = new ReDim (i.expr, i.Arguments, (bool) $2, (ArrayList) $4, lexer.Location);
1927 current_block.AddStatement (r);
1932 : /* empty */ { $$ = false; }
1933 | PRESERVE { $$ = true; }
1939 ArrayList clauses = new ArrayList ();
1944 | redim_clauses COMMA redim_clause
1946 ArrayList clauses = (ArrayList) ($1);
1954 : invocation_expression
1955 /* : identifier OPEN_PARENS expression_list CLOSE_PARENS opt_array_initializer */
1958 opt_array_initializer
1964 : ERASE primary_expression
1969 | continue_statement
1970 | */return_statement
1980 $$ = new Goto (current_block, (string) $2, lexer.Location);
1985 : THROW opt_expression
1987 $$ = new Throw ((Expression) $2, lexer.Location);
1994 $$ = new Exit ((ExitType)$2, lexer.Location);
1999 : DO { $$ = ExitType.DO; }
2000 | FOR { $$ = ExitType.FOR; }
2001 | WHILE { $$ = ExitType.WHILE; }
2002 | SELECT { $$ = ExitType.SELECT; }
2003 | SUB { $$ = ExitType.SUB; }
2004 | FUNCTION { $$ = ExitType.FUNCTION; }
2005 | PROPERTY { $$ = ExitType.PROPERTY; }
2006 | TRY { $$ = ExitType.TRY; }
2009 : RETURN opt_expression
2011 $$ = new Return ((Expression) $2, lexer.Location);
2023 : FOR EACH identifier IN
2025 oob_stack.Push (lexer.Location);
2027 expression end_of_stmt
2031 Block foreach_block = current_block;
2032 Location l = lexer.Location;
2033 LocalVariableReference v = null;
2036 vi = foreach_block.GetVariableInfo ((string) $3);
2038 // Get a reference to this variable.
2039 v = new LocalVariableReference (foreach_block, (string) $3, l, vi, false);
2042 Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
2049 Block foreach_block = current_block;
2050 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
2051 Block prev_block = end_block();
2052 Location l = (Location) oob_stack.Pop ();
2056 f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
2066 if (!UseExtendedSyntax)
2072 if (iterator_container == null){
2073 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2076 iterator_container.SetYields ();
2077 $$ = new Yield ((Expression) $2, lexer.Location);
2082 if (!UseExtendedSyntax)
2088 if (iterator_container == null){
2089 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
2092 iterator_container.SetYields ();
2093 $$ = new YieldBreak (lexer.Location);
2113 tmp_catch_clauses = (ArrayList) $5;
2122 ArrayList s = new ArrayList ();
2124 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
2131 // Now s contains the list of specific catch clauses
2132 // and g contains the general one.
2133 Block b = end_block();
2135 $$ = new Try ((Block) b, s, g, null, lexer.Location);
2142 tmp_block = end_block();
2152 ArrayList s = new ArrayList ();
2153 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
2155 if (catch_list != null){
2156 foreach (Catch cc in catch_list) {
2164 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
2170 : /* empty */ { $$ = null; }
2177 ArrayList l = new ArrayList ();
2182 | catch_clauses catch_clause
2184 ArrayList l = (ArrayList) $1;
2192 : /* empty */ { $$ = null; }
2197 : CATCH opt_catch_args end_of_stmt
2199 Expression type = null;
2203 DictionaryEntry cc = (DictionaryEntry) $2;
2204 type = (Expression) cc.Key;
2205 id = (string) cc.Value;
2208 ArrayList one = new ArrayList ();
2209 Location loc = lexer.Location;
2211 one.Add (new VariableDeclaration (id, type, loc));
2215 current_block = new Block (current_block);
2216 Block b = declare_local_variables (type, one, loc);
2222 opt_statement_list {
2223 Expression type = null;
2225 Block b_catch = current_block;
2228 DictionaryEntry cc = (DictionaryEntry) $2;
2229 type = (Expression) cc.Key;
2230 id = (string) cc.Value;
2234 // FIXME: I can change this for an assignment.
2236 while (current_block != (Block) $1)
2237 current_block = current_block.Parent;
2241 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2246 : /* empty */ { $$ = null; }
2251 : identifier AS type
2253 $$ = new DictionaryEntry ($3, $1);
2259 : DO opt_do_construct end_of_stmt
2262 oob_stack.Push (lexer.Location);
2265 LOOP opt_do_construct
2267 Expression t_before = (Expression) $2;
2268 Expression t_after = (Expression) $7;
2271 if ((t_before != null) && (t_after != null))
2272 Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2274 if ((t_before == null) && (t_after == null))
2275 t = new BoolLiteral (true);
2277 t = (t_before != null) ? t_before : t_after;
2279 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2281 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2282 ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2283 t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2285 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2290 : /* empty */ { $$ = null; }
2291 | while_or_until boolean_expression
2293 do_type = (DoOptions)$1;
2294 $$ = (Expression) $2;
2299 : WHILE { $$ = DoOptions.WHILE; }
2300 | UNTIL { $$ = DoOptions.UNTIL; }
2307 oob_stack.Push (lexer.Location);
2309 boolean_expression end_of_stmt
2313 Location l = (Location) oob_stack.Pop ();
2314 Block b = end_block();
2315 Expression e = (Expression) $3;
2316 $$ = new While ((Expression) e, (Statement) b, l);
2322 : FOR identifier ASSIGN expression TO expression opt_step end_of_stmt
2329 Block statement = end_block();
2330 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2332 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2333 Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual,
2334 for_var, (Expression) $6, lexer.Location);
2335 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2336 for_var, (Expression) $7, lexer.Location), lexer.Location);
2338 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);
2339 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2341 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);
2346 : /* empty */ { $$ = new IntLiteral ((Int32) 1); }
2347 | STEP expression { $$ = $2; }
2352 | qualified_identifier
2361 : if_statement_open opt_then if_statement_rest
2365 | if_statement_open THEN pre_embedded_statement
2367 Location l = (Location) oob_stack.Pop ();
2368 tmp_expr = (Expression)expr_stack.Pop();
2369 $$ = new If ((Expression) tmp_expr, end_block(), l);
2373 pre_embedded_statement
2374 : embedded_statement
2376 Statement s = (Statement) $1;
2378 current_block.AddStatement ((Statement) $1);
2383 : IF boolean_expression
2385 oob_stack.Push (lexer.Location);
2387 tmp_expr = (Expression) $2;
2388 expr_stack.Push(tmp_expr);
2402 Location l = (Location) oob_stack.Pop ();
2403 Expression expr = (Expression)expr_stack.Pop();
2404 $$ = new If ((Expression) expr, (Statement) end_block(), l);
2410 Block bl = end_block();
2411 tmp_blocks.Push(bl);
2417 Location l = (Location) oob_stack.Pop ();
2418 tmp_expr = (Expression)expr_stack.Pop();
2419 tmp_block = (Block) tmp_blocks.Pop();
2420 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2424 ELSEIF boolean_expression opt_then
2426 tmp_expr = (Expression) $4;
2427 expr_stack.Push(tmp_expr);
2428 tmp_block = end_block();
2429 tmp_blocks.Push(tmp_block);
2432 else_if_statement_rest
2434 Statement stmt = (Statement) statement_stack.Pop();
2435 Block bl = (Block) tmp_blocks.Pop();
2436 Expression expr = (Expression)expr_stack.Pop();
2437 Location l = (Location) oob_stack.Pop ();
2438 $$ = (Statement) new If ((Expression) expr, (Statement) bl , stmt , l);
2443 else_if_statement_rest
2448 Location l = (Location) oob_stack.Pop ();
2450 Expression expr = (Expression)expr_stack.Pop();
2451 Statement stmt = (Statement) new If ((Expression) expr, (Statement) end_block(), l);
2452 statement_stack.Push(stmt);
2458 Block bl = end_block();
2459 tmp_blocks.Push(bl);
2465 Location l = (Location) oob_stack.Pop ();
2467 Expression expr = (Expression)expr_stack.Pop();
2468 Block bl = (Block)tmp_blocks.Pop();
2469 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl , (Statement) end_block(), l);
2470 statement_stack.Push(stmt);
2474 ELSEIF boolean_expression opt_then
2476 expr_stack.Push((Expression) $4);
2477 Block bl = end_block();
2478 tmp_blocks.Push(bl);
2481 else_if_statement_rest
2483 Location l = (Location) oob_stack.Pop ();
2485 Statement tmp_stmt = (Statement)statement_stack.Pop();
2486 Block bl = (Block) tmp_blocks.Pop();
2487 Expression expr = (Expression)expr_stack.Pop();
2488 Statement stmt = (Statement) new If ((Expression) expr, (Statement) bl, tmp_stmt , l);
2489 statement_stack.Push(stmt);
2494 : SELECT opt_case expression end_of_stmt
2496 oob_stack.Push (lexer.Location);
2497 switch_stack.Push (current_block);
2502 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2503 current_block = (Block) switch_stack.Pop ();
2508 : /* empty */ { $$ = null; }
2509 | case_sections { $$ = $1; }
2513 : case_sections case_section
2515 ArrayList sections = (ArrayList) $1;
2522 ArrayList sections = new ArrayList ();
2530 : CASE case_clauses end_of_stmt
2536 Block topmost = current_block;
2538 while (topmost.Implicit)
2539 topmost = topmost.Parent;
2541 // FIXME: This is a horrible hack which MUST go
2542 topmost.statements.Add (new Break (lexer.Location));
2543 $$ = new SwitchSection ((ArrayList) $2, topmost);
2545 | CASE ELSE end_of_stmt
2546 /* FIXME: we should somehow flag an error
2547 (BC30321 'Case' cannot follow a 'Case Else'
2548 in the same 'Select' statement.)
2549 if Case Else is not the last of the Case clauses
2556 Block topmost = current_block;
2558 while (topmost.Implicit)
2559 topmost = topmost.Parent;
2561 // FIXME: This is a horrible hack which MUST go
2562 topmost.statements.Add (new Break (lexer.Location));
2564 ArrayList a = new ArrayList();
2565 a.Add (new SwitchLabel (null, lexer.Location));
2566 $$ = new SwitchSection ((ArrayList) a, topmost);
2573 ArrayList labels = new ArrayList ();
2578 | case_clauses COMMA case_clause
2580 ArrayList labels = (ArrayList) ($1);
2588 : opt_is comparison_operator expression
2591 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2613 expression_statement
2614 : statement_expression
2621 statement_expression
2622 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2623 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2624 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2627 object_creation_expression
2628 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2630 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2634 $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
2638 array_creation_expression
2639 : object_creation_expression array_initializer
2642 ArrayList dims = new ArrayList();
2644 if (n.Arguments != null) {
2645 foreach (Argument a in n.Arguments) {
2650 Expression atype = n.RequestedType;
2652 if (VariableDeclaration.IndexesSpecified(this)) {
2653 $$ = new ArrayCreation (atype, dims, "", (ArrayList) $2, lexer.Location);
2657 string rank = VariableDeclaration.BuildRank (dims);
2658 $$ = new ArrayCreation (atype, rank, (ArrayList) $2, lexer.Location);
2660 //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
2665 : object_creation_expression
2666 | array_creation_expression
2669 declaration_statement
2670 : local_variable_declaration
2673 DictionaryEntry de = (DictionaryEntry) $1;
2675 $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2679 | local_constant_declaration
2682 DictionaryEntry de = (DictionaryEntry) $1;
2684 $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
2689 local_variable_declaration
2690 : DIM variable_declarators
2692 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);
2697 local_constant_declaration
2698 : CONST constant_declarator
2701 $$ = new DictionaryEntry ($1, $2);
2708 : identifier ASSIGN constant_expression
2710 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
2714 variable_declarators
2715 : variable_declarator
2717 ArrayList decl = new ArrayList ();
2721 | variable_declarators COMMA variable_declarator
2723 ArrayList decls = (ArrayList) $1;
2730 : variable_identifier opt_type_decl opt_variable_initializer
2732 string varname = (string)$1;
2733 object varinit = $3;
2735 ArrayList a_dims = null;
2737 // Some checking is required for particularly weird declarations
2738 // like Dim a As Integer(,)
2740 vartype = (Expression) ((Pair) $2).First;
2741 if ($3 != null && $3 is ArrayList)
2742 Report.Error (205, "End of statement expected.");
2744 ArrayList args = (ArrayList) ((Pair) $2).Second;
2745 if (VariableDeclaration.HasExplicitIndexes (args))
2746 Report.Error (638, "Array bounds cannot appear in type specifiers.");
2748 string s_vartype = vartype.ToString();
2751 for (int x = 0; x < args.Count; x++)
2755 vartype = DecomposeQI(s_vartype, Location.Null);
2758 vartype = (Expression) $2;
2761 Check for a declaration like Dim a(2) or Dim a(2,3)
2762 If this is the case, we must generate an ArrayCreationExpression
2763 and, in case, add the initializer after the array has been created.
2765 if (VariableDeclaration.IsArrayDecl (this)) {
2766 if (VariableDeclaration.IndexesSpecified(this)) {
2767 a_dims = (ArrayList) current_rank_specifiers;
2768 //varinit = new ArrayCreation (vartype, a_dims, "", (ArrayList) varinit, lexer.Location);
2769 varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
2772 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (this), lexer.Location);
2775 if (vartype is New) {
2776 if (varinit != null) {
2777 Report.Error (30205, lexer.Location, "End of statement expected");
2783 vartype = ((New)vartype).RequestedType;
2786 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
2787 //Console.WriteLine ("varname: {0} - vartype: {1} - init: {2}", varname, vartype, varinit);
2792 : identifier opt_array_name_modifier
2795 current_rank_specifiers = (ArrayList) $2;
2806 $$ = (Expression) $2;
2815 | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS
2817 $$ = new Pair ($2, $4);;
2821 New n = new New ((Expression)$3, null, lexer.Location);
2822 $$ = (Expression) n;
2824 | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2826 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
2827 $$ = (Expression) n;
2831 opt_array_name_modifier
2832 : /* empty */ { $$ = null; }
2833 | array_type_modifier { $$ = $1; }
2837 : rank_specifiers { $$ = $1; }
2840 opt_variable_initializer
2841 : /* empty */ { $$ = null; }
2842 | ASSIGN variable_initializer { $$ = $2; }
2845 variable_initializer
2858 : OPEN_BRACE CLOSE_BRACE
2860 ArrayList list = new ArrayList ();
2863 | OPEN_BRACE variable_initializer_list CLOSE_BRACE
2865 $$ = (ArrayList) $2;
2869 variable_initializer_list
2870 : variable_initializer
2872 ArrayList list = new ArrayList ();
2876 | variable_initializer_list COMMA variable_initializer
2878 ArrayList list = (ArrayList) $1;
2885 * The following is from Rhys' grammar:
2886 * > Types in local variable declarations must be recognized as
2887 * > expressions to prevent reduce/reduce errors in the grammar.
2888 * > The expressions are converted into types during semantic analysis.
2891 : primary_expression opt_rank_specifiers
2893 // FIXME: Do something smart here regarding the composition of the type.
2895 // Ok, the above "primary_expression" is there to get rid of
2896 // both reduce/reduce and shift/reduces in the grammar, it should
2897 // really just be "type_name". If you use type_name, a reduce/reduce
2898 // creeps up. If you use qualified_identifier (which is all we need
2899 // really) two shift/reduces appear.
2902 // So the super-trick is that primary_expression
2903 // can only be either a SimpleName or a MemberAccess.
2904 // The MemberAccess case arises when you have a fully qualified type-name like :
2906 // SimpleName is when you have
2909 Expression expr = (Expression) $1;
2910 if (!(expr is SimpleName || expr is MemberAccess)) {
2911 Error_ExpectingTypeName (lexer.Location, expr);
2915 // So we extract the string corresponding to the SimpleName
2918 if ((string) $2 == "")
2921 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2924 | builtin_types opt_rank_specifiers
2926 if ((string) $2 == "")
2929 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2948 ArrayList rs = new ArrayList();
2952 | rank_specifiers rank_specifier
2954 ArrayList rs = (ArrayList) $1;
2961 : OPEN_PARENS opt_dim_separators CLOSE_PARENS
2970 ArrayList ds = new ArrayList();
2971 ds.Add (new EmptyExpression());
2976 ArrayList ds = (ArrayList) $1;
2977 ds.Add (new EmptyExpression());
2989 ArrayList ds = new ArrayList();
2990 ds.Add (new EmptyExpression());
2993 | dim_separators COMMA
2995 ArrayList ds = (ArrayList) $1;
2996 ds.Add (new EmptyExpression());
3004 ArrayList ds = new ArrayList();
3005 ds.Add ((Expression) $1);
3008 | dim_specifiers COMMA expression
3010 ArrayList ds = (ArrayList) $1;
3011 ds.Add ((Expression) $3);
3023 | qualified_identifier
3025 string name = (string) $1;
3027 $$ = DecomposeQI (name, lexer.Location);
3029 | parenthesized_expression
3031 | invocation_expression
3043 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
3044 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
3045 | NOTHING { $$ = NullLiteral.Null; }
3049 : LITERAL_SINGLE { $$ = new FloatLiteral ((float) lexer.Value); }
3050 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
3051 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
3056 object v = lexer.Value;
3059 $$ = new IntLiteral ((Int32) v);
3061 $$ = new UIntLiteral ((UInt32) v);
3063 $$ = new LongLiteral ((Int64) v);
3064 else if (v is ulong)
3065 $$ = new ULongLiteral ((UInt64) v);
3067 Console.WriteLine ("OOPS. Unexpected result from scanner");
3073 : TRUE { $$ = new BoolLiteral (true); }
3074 | FALSE { $$ = new BoolLiteral (false); }
3077 parenthesized_expression
3078 : OPEN_PARENS expression CLOSE_PARENS
3083 : primary_expression DOT identifier
3085 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3087 | primary_expression DOT NEW
3089 $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
3091 | predefined_type DOT identifier
3093 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
3101 invocation_expression
3102 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
3105 Location l = lexer.Location;
3106 Report.Error (1, l, "THIS IS CRAZY");
3108 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
3109 // Console.WriteLine ("Invocation: {0} with {1} arguments", $1, ($3 != null) ? ((ArrayList) $3).Count : 0);
3114 : MYBASE DOT IDENTIFIER
3116 $$ = new BaseAccess ((string) $3, lexer.Location);
3120 $$ = new BaseAccess ("New", lexer.Location);
3128 The 'argument' rule returns an 'empty' argument
3129 of type NoArg (used for default arguments in invocations)
3130 if no arguments are actually passed.
3132 If there is only one argument and it is o type NoArg,
3133 we return a null (empty) list
3135 ArrayList args = (ArrayList) $1;
3136 if (args.Count == 1 &&
3137 ((Argument)args[0]).ArgType == Argument.AType.NoArg)
3147 ArrayList list = new ArrayList ();
3151 | argument_list COMMA argument
3153 ArrayList list = (ArrayList) $1;
3162 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
3164 | BYREF variable_reference
3166 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
3170 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
3175 : expression {/* note ("section 5.4"); */ $$ = $1; }
3181 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3186 : conditional_expression { $$ = $1; }
3187 | negation_expression
3188 /*| assignment_expression*/
3199 ArrayList list = new ArrayList ();
3203 | expression_list COMMA expression
3205 ArrayList list = (ArrayList) $1;
3212 : /*empty */ { $$ = null; }
3219 $$ = new This (current_block, lexer.Location);
3223 // FIXME: This is actually somewhat different from Me
3224 $$ = new This (current_block, lexer.Location);
3229 : primary_expression
3230 /*| NOT prefixed_unary_expression
3232 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
3234 | cast_expression */
3238 : cast_operator OPEN_PARENS expression CLOSE_PARENS
3240 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
3242 | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
3244 $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
3249 : CBOOL { $$ = TypeManager.system_boolean_expr; }
3250 | CBYTE { $$ = TypeManager.system_byte_expr; }
3251 | CCHAR { $$ = TypeManager.system_char_expr; }
3252 | CDATE { $$ = TypeManager.system_decimal_expr; } //FIXME
3253 | CDBL { $$ = TypeManager.system_double_expr; }
3254 | CDEC { $$ = TypeManager.system_decimal_expr; }
3255 | CINT { $$ = TypeManager.system_int32_expr; }
3256 | CLNG { $$ = TypeManager.system_int64_expr; }
3257 | COBJ { $$ = TypeManager.system_object_expr; }
3258 | CSHORT { $$ = TypeManager.system_int16_expr; }
3259 | CSNG { $$ = TypeManager.system_single_expr; }
3260 | CSTR { $$ = TypeManager.system_string_expr; }
3264 // The idea to split this out is from Rhys' grammar
3265 // to solve the problem with casts.
3267 prefixed_unary_expression
3269 | PLUS prefixed_unary_expression
3271 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
3273 | MINUS prefixed_unary_expression
3275 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
3277 | ADDRESSOF prefixed_unary_expression
3279 // FIXME: We should generate an error if AddressOf is NOT used
3280 // during delegate creation
3285 multiplicative_expression
3286 : prefixed_unary_expression
3287 | multiplicative_expression STAR prefixed_unary_expression
3289 $$ = new Binary (Binary.Operator.Multiply,
3290 (Expression) $1, (Expression) $3, lexer.Location);
3292 | multiplicative_expression DIV prefixed_unary_expression
3294 $$ = new Binary (Binary.Operator.Division,
3295 (Expression) $1, (Expression) $3, lexer.Location);
3297 | multiplicative_expression OP_IDIV prefixed_unary_expression
3299 $$ = new Binary (Binary.Operator.Division,
3300 (Expression) $1, (Expression) $3, lexer.Location);
3302 | multiplicative_expression MOD prefixed_unary_expression
3304 $$ = new Binary (Binary.Operator.Modulus,
3305 (Expression) $1, (Expression) $3, lexer.Location);
3310 : multiplicative_expression
3311 | additive_expression PLUS multiplicative_expression
3313 $$ = new Binary (Binary.Operator.Addition,
3314 (Expression) $1, (Expression) $3, lexer.Location);
3316 | additive_expression MINUS multiplicative_expression
3318 $$ = new Binary (Binary.Operator.Subtraction,
3319 (Expression) $1, (Expression) $3, lexer.Location);
3321 | additive_expression OP_CONCAT multiplicative_expression
3323 // FIXME: This should only work for String expressions
3324 // We probably need to use something from the runtime
3325 $$ = new Binary (Binary.Operator.Addition,
3326 (Expression) $1, (Expression) $3, lexer.Location);
3330 relational_expression
3331 : additive_expression
3332 | relational_expression OP_LT additive_expression
3334 $$ = new Binary (Binary.Operator.LessThan,
3335 (Expression) $1, (Expression) $3, lexer.Location);
3337 | relational_expression OP_GT additive_expression
3339 $$ = new Binary (Binary.Operator.GreaterThan,
3340 (Expression) $1, (Expression) $3, lexer.Location);
3342 | relational_expression OP_LE additive_expression
3344 $$ = new Binary (Binary.Operator.LessThanOrEqual,
3345 (Expression) $1, (Expression) $3, lexer.Location);
3347 | relational_expression OP_GE additive_expression
3349 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
3350 (Expression) $1, (Expression) $3, lexer.Location);
3352 | relational_expression IS unary_expression
3354 $$ = new Binary (Binary.Operator.Equality,
3355 (Expression) $1, (Expression) $3, lexer.Location);
3357 | relational_expression AS type_name
3359 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
3364 : relational_expression
3365 | equality_expression ASSIGN relational_expression
3367 $$ = new Binary (Binary.Operator.Equality,
3368 (Expression) $1, (Expression) $3, lexer.Location);
3370 | equality_expression OP_NE relational_expression
3372 $$ = new Binary (Binary.Operator.Inequality,
3373 (Expression) $1, (Expression) $3, lexer.Location);
3378 : equality_expression
3379 | and_expression AND equality_expression
3381 $$ = new Binary (Binary.Operator.BitwiseAnd,
3382 (Expression) $1, (Expression) $3, lexer.Location);
3386 exclusive_or_expression
3388 | exclusive_or_expression OP_XOR and_expression
3390 $$ = new Binary (Binary.Operator.ExclusiveOr,
3391 (Expression) $1, (Expression) $3, lexer.Location);
3395 conditional_and_expression
3396 : exclusive_or_expression
3397 | conditional_and_expression AND exclusive_or_expression
3399 $$ = new Binary (Binary.Operator.LogicalAnd,
3400 (Expression) $1, (Expression) $3, lexer.Location);
3402 | conditional_and_expression ANDALSO exclusive_or_expression
3403 { // FIXME: this is likely to be broken
3404 $$ = new Binary (Binary.Operator.LogicalAnd,
3405 (Expression) $1, (Expression) $3, lexer.Location);
3409 conditional_or_expression
3410 : conditional_and_expression
3411 | conditional_or_expression OR conditional_and_expression
3413 $$ = new Binary (Binary.Operator.LogicalOr,
3414 (Expression) $1, (Expression) $3, lexer.Location);
3416 | conditional_or_expression ORELSE conditional_and_expression
3417 { // FIXME: this is likely to be broken
3418 $$ = new Binary (Binary.Operator.LogicalOr,
3419 (Expression) $1, (Expression) $3, lexer.Location);
3423 conditional_expression
3424 : conditional_or_expression
3427 assignment_expression
3428 : prefixed_unary_expression ASSIGN expression
3430 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3432 | prefixed_unary_expression OP_MULT_ASSIGN expression
3434 Location l = lexer.Location;
3436 $$ = new CompoundAssign (
3437 Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
3439 | prefixed_unary_expression OP_DIV_ASSIGN expression
3441 Location l = lexer.Location;
3443 $$ = new CompoundAssign (
3444 Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3446 | prefixed_unary_expression OP_IDIV_ASSIGN expression
3448 Location l = lexer.Location;
3450 $$ = new CompoundAssign (
3451 Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
3453 | prefixed_unary_expression OP_ADD_ASSIGN expression
3455 Location l = lexer.Location;
3457 $$ = new CompoundAssign (
3458 Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3460 | prefixed_unary_expression OP_SUB_ASSIGN expression
3462 Location l = lexer.Location;
3464 $$ = new CompoundAssign (
3465 Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
3467 | prefixed_unary_expression OP_CONCAT_ASSIGN expression
3469 Location l = lexer.Location;
3471 $$ = new CompoundAssign (
3472 Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
3485 : type_name { /* class_type */
3487 This does interfaces, delegates, struct_types, class_types,
3488 parent classes, and more! 4.2
3490 $$ = DecomposeQI ((string) $1, lexer.Location);
3500 ArrayList types = new ArrayList ();
3505 | type_list COMMA type
3507 ArrayList types = (ArrayList) $1;
3515 : namespace_or_type_name
3518 namespace_or_type_name
3519 : qualified_identifier
3523 : type bracketed_rank_specifiers
3525 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3529 bracketed_rank_specifiers
3530 : bracketed_rank_specifier bracketed_opt_rank_specifier
3532 $$ = (string) $2 + (string) $1;
3536 bracketed_rank_specifier
3537 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
3539 $$ = "[" + (string) $2 + "]";
3543 bracketed_opt_rank_specifier
3548 | bracketed_rank_specifiers
3554 /* Built-in / Integral types */
3556 : OBJECT { $$ = TypeManager.system_object_expr; }
3557 | STRING { $$ = TypeManager.system_string_expr; }
3558 | BOOLEAN { $$ = TypeManager.system_boolean_expr; }
3559 | DECIMAL { $$ = TypeManager.system_decimal_expr; }
3560 | SINGLE { $$ = TypeManager.system_single_expr; }
3561 | DOUBLE { $$ = TypeManager.system_double_expr; }
3567 | BYTE { $$ = TypeManager.system_byte_expr; }
3568 | SHORT { $$ = TypeManager.system_int16_expr; }
3569 | LONG { $$ = TypeManager.system_int64_expr; }
3570 | INTEGER { $$ = TypeManager.system_int32_expr; }
3571 | CHAR { $$ = TypeManager.system_char_expr; }
3573 | SBYTE { $$ = TypeManager.system_sbyte_expr; }
3574 | UINT { $$ = TypeManager.system_uint32_expr; }
3575 | ULONG { $$ = TypeManager.system_uint64_expr; }
3576 | USHORT { $$ = TypeManager.system_uint16_expr; }
3577 | CHAR { $$ = TypeManager.system_char_expr; }
3578 | VOID { $$ = TypeManager.system_void_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 IndexesSpecified (Parser t)
3766 ArrayList ranks = t.current_rank_specifiers;
3768 if (ranks != null) {
3769 foreach (ArrayList IndexList in ranks) {
3770 foreach (Expression e in IndexList)
3771 if (!(e is EmptyExpression)) {
3780 public static string StripDims (string varname, ref string d)
3782 string res = varname;
3785 if (varname.IndexOf("[") >= 0) {
3786 dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3787 res = varname.Substring(0, varname.IndexOf("["));
3793 public static string StripDims (string varname)
3797 return (StripDims(varname, ref dres));
3800 public static string StripIndexesFromDims (string dims)
3802 StringBuilder sb = new StringBuilder();
3804 foreach (char c in dims)
3805 if (c == ',' || c == ']' || c == '[')
3808 return sb.ToString();
3811 public static string BuildRank (ArrayList rank)
3816 for (int x = 0; x < (rank.Count -1 ); x++)
3823 public static string BuildRanks (Parser t)
3827 foreach (ArrayList rank in t.current_rank_specifiers)
3828 res += BuildRank (rank);
3833 public static bool HasExplicitIndexes (ArrayList a)
3838 foreach (Expression e in a)
3839 if (!(e is EmptyExpression)) {
3847 public static ArrayList ParseIndexList (Parser t)
3849 ArrayList res = new ArrayList();
3850 //string d = dims.Substring (1, dims.Length -2);
3851 //Array a = d.Split (',');
3853 return t.current_rank_specifiers;
3855 if (a.GetLength(0) > 32) {
3856 Report.Error (999, "Arrays cannot have more than 32 dimensions");
3859 foreach (string s in a)
3861 res.Add (new IntLiteral ((Int32) Convert.ToInt32(s) + 1));
3863 res.Add (new IntLiteral ((Int32) 0));
3868 public static bool IsArrayDecl (Parser t)
3870 // return (varname.IndexOf("[") >= 0);
3871 return (t.current_rank_specifiers != null);
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);
3890 public Property BuildSimpleProperty (Expression p_type, string name,
3891 Field p_fld, int mod_flags,
3892 Attributes attrs, Location loc)
3895 Block get_block, set_block;
3896 Accessor acc_set, acc_get;
3897 StatementExpression a_set;
3902 Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
3903 args = new Parameter [1];
3904 args [0] = implicit_value_parameter;
3906 Parameters set_params = new Parameters (args, null, loc);
3907 a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
3908 (Expression) new SimpleName("value", loc), loc), loc);
3910 set_block = new Block (current_block, set_params, loc, Location.Null);
3911 set_block.AddStatement ((Statement) a_set);
3912 acc_set = new Accessor (set_block, attrs);
3915 a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
3916 get_block = new Block (current_block, null, loc, Location.Null);
3917 get_block.AddStatement ((Statement) a_get);
3918 acc_get = new Accessor (get_block, attrs);
3920 p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
3927 current_block = new Block (current_block, current_local_parameters,
3928 lexer.Location, Location.Null);
3935 while (current_block.Implicit)
3936 current_block = current_block.Parent;
3938 res = current_block;
3940 current_block.SetEndLocation (lexer.Location);
3941 current_block = current_block.Parent;
3946 private void AddHandler (Expression evt_definition, string handler_name)
3948 AddHandler (current_block, evt_definition, handler_name);
3951 void CheckAttributeTarget (string a)
3955 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3959 Location l = lexer.Location;
3960 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3965 private void AddHandler (Block b, Expression evt_id, string handler_name)
3967 Location loc = lexer.Location;
3968 string evt_target = evt_id.ToString();
3969 evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
3970 Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
3974 private void RaiseEvent (string evt_name, ArrayList args)
3976 Location loc = lexer.Location;
3978 Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
3979 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc));
3980 current_block.AddStatement (s);
3983 // FIXME: THIS DOES NOT WORK!!!
3984 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
3986 Location loc = lexer.Location;
3987 ArrayList neh_args = new ArrayList();
3988 neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
3990 ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
3992 CompoundAssign ca = new CompoundAssign (
3993 Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
3995 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc));
4000 // This method is used to get at the complete string representation of
4001 // a fully-qualified type name, hiding inside a MemberAccess ;-)
4002 // This is necessary because local_variable_type admits primary_expression
4003 // as the type of the variable. So we do some extra checking
4005 string GetQualifiedIdentifier (Expression expr)
4007 if (expr is SimpleName)
4008 return ((SimpleName)expr).Name;
4009 else if (expr is MemberAccess)
4010 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
4012 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
4016 private void RemoveHandler (Expression evt_definition, string handler_name)
4018 RemoveHandler (current_block, evt_definition, handler_name);
4021 private ConstructorInitializer FixConstructorInitializer (ref ArrayList s)
4023 ConstructorInitializer ci = null;
4026 if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
4027 Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
4029 if (i.expr is BaseAccess) {
4030 BaseAccess ba = (BaseAccess) i.expr;
4031 if (ba.member == "New" || ba.member == ".ctor") {
4032 ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
4036 if (i.expr.ToString() == "Mono.CSharp.This..ctor") {
4037 ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location);
4045 void Error_ExpectingTypeName (Location l, Expression expr)
4047 if (expr is Invocation){
4048 Report.Error (1002, l, "; expected");
4050 Report.Error (-1, l, "Invalid Type definition");
4054 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
4058 private void ReportError9998()
4060 Report.Error (9998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
4063 public override int parse ()
4065 current_namespace = new Namespace (null, RootContext.RootNamespace);
4066 current_container = RootContext.Tree.Types;
4067 current_container.Namespace = current_namespace;
4068 oob_stack = new Stack ();
4069 switch_stack = new Stack ();
4070 expr_stack = new Stack ();
4071 tmp_blocks = new Stack();
4072 statement_stack = new Stack();
4074 UseExtendedSyntax = name.EndsWith(".mbs");
4075 OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
4076 OptionStrict = InitialOptionStrict || UseExtendedSyntax;
4077 OptionCompareBinary = InitialOptionCompareBinary;
4079 lexer = new Tokenizer (input, name, defines);
4080 StringBuilder value = new StringBuilder ();
4081 //yacc_verbose_flag=true;
4084 if (yacc_verbose_flag)
4085 yyparse (lexer, new yydebug.yyDebugSimple ());
4091 Console.WriteLine (lexer.location + " : Parsing error in " + lexer.ref_name);
4092 Report.Error (9999, lexer.Location, "\n");
4093 //Console.WriteLine (e);
4096 return Report.Errors;