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.
122 static public bool InitialOptionExplicit = false;
123 static public bool InitialOptionStrict = false;
124 static public bool InitialOptionCompareBinary = true;
128 bool OptionCompareBinary;
130 static public bool UseExtendedSyntax; // for ".mbs" files
132 public override string[] extensions()
134 string [] list = { ".vb", ".mbs" };
141 %token NONE /* This token is never returned by our lexer */
142 %token ERROR // This is used not by the parser, but by the tokenizer.
146 *These are the MonoBASIC keywords
187 %token DESCRIPTION // MonoBASIC extension
236 %token NOTINHERITABLE
237 %token NOTOVERRIDABLE
248 %token PARAMETER // MonoBASIC extension
276 %token SUMMARY // MonoBASIC extension
295 /* MonoBASIC single character operators/punctuation. */
297 %token OPEN_BRACKET "["
298 %token CLOSE_BRACKET "]"
299 %token OPEN_PARENS "("
300 %token OPEN_BRACE "{"
301 %token CLOSE_BRACE "}"
302 %token CLOSE_PARENS ")"
319 %token ATTR_ASSIGN ":="
321 /* MonoBASIC multi-character operators. */
326 %token OP_AND //"and"
328 %token OP_XOR //"xor"
329 %token OP_MODULUS //"mod"
330 %token OP_MULT_ASSIGN "*="
331 %token OP_DIV_ASSIGN "/="
332 %token OP_IDIV_ASSIGN "\\="
333 %token OP_ADD_ASSIGN "+="
334 %token OP_SUB_ASSIGN "-="
335 %token OP_CONCAT_ASSIGN "&="
336 %token OP_EXP_ASSIGN "^="
339 %token LITERAL_INTEGER "int literal"
340 %token LITERAL_SINGLE "float literal"
341 %token LITERAL_DOUBLE "double literal"
342 %token LITERAL_DECIMAL "decimal literal"
343 %token LITERAL_CHARACTER "character literal"
344 %token LITERAL_STRING "string literal"
348 /* Add precedence rules to solve dangling else s/r conflict */
357 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
359 %left STAR DIV PERCENT
360 %right BITWISE_NOT CARRET UMINUS
361 %nonassoc OP_INC OP_DEC
363 %left OPEN_BRACKET OPEN_BRACE
367 %start compilation_unit
371 : opt_option_directives
372 opt_imports_directives
381 opt_option_directives
388 | option_directives option_directive
392 : option_explicit_directive
393 | option_strict_directive
394 | option_compare_directive
423 option_explicit_directive
424 : OPTION EXPLICIT on_off EOL
426 if (!UseExtendedSyntax)
427 OptionExplicit = (bool)$3;
430 9999, lexer.Location,
431 "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");
436 option_strict_directive
437 : OPTION STRICT on_off EOL
439 if (!UseExtendedSyntax)
440 OptionStrict = (bool)$3;
443 9999, lexer.Location,
444 "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");
448 option_compare_directive
449 : OPTION COMPARE text_or_binary EOL
451 OptionCompareBinary = (bool)$3;
462 | declarations declaration
466 : namespace_declaration
473 Class c = (Class) $1;
474 mod_flags = c.ModFlags;
476 } else if ($1 is Struct){
477 Struct s = (Struct) $1;
478 mod_flags = s.ModFlags;
480 } else if ($1 is Module){
481 Module m = (Module) $1;
482 mod_flags = m.ModFlags;
487 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
489 1527, lexer.Location,
490 "Namespace elements cannot be explicitly " +
491 "declared private or protected in '" + name + "'");
507 | qualified_identifier DOT identifier
509 $$ = (($1).ToString ()) + "." + ($3.ToString ());
512 opt_imports_directives
519 | imports_directives imports_directive
523 : IMPORTS imports_terms EOL
528 | imports_terms COMMA imports_terms
532 : qualified_identifier
534 current_namespace.Using ((string) $1, lexer.Location);
536 | qualified_identifier ASSIGN qualified_identifier
538 current_namespace.UsingAlias ((string) $1, (string) $3, lexer.Location);
544 | attribute_sections { $$ = $1; }
550 AttributeSection sect = (AttributeSection) $1;
552 if (sect.Target == "assembly")
553 RootContext.AddGlobalAttributeSection (current_container, sect);
555 $$ = new Attributes ((AttributeSection) $1, lexer.Location);
559 FIXME: we should check if extended syntax is enabled;
560 otherwise an exception should be thrown since VB.NET
561 only allows one attribute section
563 | attribute_sections attribute_section
565 Attributes attrs = null;
566 AttributeSection sect = (AttributeSection) $2;
568 if (sect.Target == "assembly")
569 RootContext.AddGlobalAttributeSection (current_container, sect);
572 attrs = (Attributes) $1;
573 attrs.AddAttributeSection (sect);
581 : OP_LT attribute_target_specifier attribute_list OP_GT
583 string target = null;
586 target = (string) $2;
588 $$ = new AttributeSection (target, (ArrayList) $3);
590 | OP_LT attribute_list OP_GT
592 $$ = new AttributeSection (null, (ArrayList) $2);
596 attribute_target_specifier
597 : attribute_target COLON
606 CheckAttributeTarget ((string) $1);
609 | EVENT { $$ = "event"; }
610 | RETURN { $$ = "return"; }
616 ArrayList attrs = new ArrayList ();
622 | attribute_list COMMA attribute
624 ArrayList attrs = (ArrayList) $1;
636 opt_attribute_arguments
638 $$ = new Mono.CSharp.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
646 opt_attribute_arguments
647 : /* empty */ { $$ = null; }
648 | OPEN_PARENS attribute_arguments CLOSE_PARENS
655 : opt_positional_argument_list
660 ArrayList args = new ArrayList ();
666 | positional_argument_list COMMA named_argument_list
668 ArrayList args = new ArrayList ();
674 | named_argument_list
676 ArrayList args = new ArrayList ();
685 opt_positional_argument_list
686 : /* empty */ { $$ = null; }
687 | positional_argument_list
690 positional_argument_list
693 ArrayList args = new ArrayList ();
694 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
698 | positional_argument_list COMMA expression
700 ArrayList args = (ArrayList) $1;
701 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
710 ArrayList args = new ArrayList ();
715 | named_argument_list COMMA named_argument
717 ArrayList args = (ArrayList) $1;
725 : identifier ATTR_ASSIGN expression
727 $$ = new DictionaryEntry (
729 new Argument ((Expression) $3, Argument.AType.Expression));
733 namespace_declaration
734 : opt_attributes NAMESPACE qualified_identifier EOL
736 Attributes attrs = (Attributes) $1;
739 foreach (AttributeSection asec in attrs.AttributeSections)
740 if (asec.Target == "assembly")
741 RootContext.AddGlobalAttributeSection (current_container, asec);
744 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$3);
746 opt_imports_directives
750 current_namespace = current_namespace.Parent;
758 current_attributes = (Attributes) $1;
759 current_modifiers = (int) $2;
761 type_spec_declaration
764 type_spec_declaration
767 | interface_declaration
768 | delegate_declaration
774 : CLASS identifier EOL opt_class_base
779 name = MakeName ((string) $2);
781 new_class = new Class (current_container, name, current_modifiers,
782 (Attributes) current_attributes, lexer.Location);
784 current_container = new_class;
785 current_container.Namespace = current_namespace;
786 RootContext.Tree.RecordDecl (name, new_class);
788 opt_class_member_declarations
791 Class new_class = (Class) current_container;
792 new_class.Bases = (ArrayList) $4;
794 current_container = current_container.Parent;
795 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
802 : /* empty */ { $$ = null; }
803 | class_base { $$ = $1; }
807 : inherits_or_implements type_list EOL { $$ = $2; }
810 inherits_or_implements
816 : /* empty */ { $$ = (int) 0; current_modifiers = 0; }
817 | modifiers { $$ = $1; current_modifiers = (int) $1; }
827 if ((m1 & m2) != 0) {
828 Location l = lexer.Location;
829 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
831 $$ = (int) (m1 | m2);
836 : PUBLIC { $$ = Modifiers.PUBLIC; }
837 | PROTECTED { $$ = Modifiers.PROTECTED; }
838 | PRIVATE { $$ = Modifiers.PRIVATE; }
839 | SHARED { $$ = Modifiers.STATIC; }
840 | FRIEND { $$ = Modifiers.INTERNAL; }
841 | OVERRIDES { $$ = Modifiers.OVERRIDE; }
842 | OVERRIDABLE { $$ = 0; }
843 | NOTOVERRIDABLE { $$ = 0; }
844 | MUSTOVERRIDE { $$ = 0; }
845 | OVERLOADS { $$ = 0; }
849 : MODULE identifier EOL
853 name = MakeName((string) $2);
854 new_module = new Module(current_container,
856 current_modifiers, // already checks then
857 (Attributes) current_attributes,
859 current_container = new_module;
860 current_container.Namespace = current_namespace;
861 RootContext.Tree.RecordDecl(name, new_module);
863 opt_module_member_declarations
866 Module new_module = (Module)current_container;
868 current_container = current_container.Parent;
869 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
875 opt_module_member_declarations
877 | module_member_declarations
880 module_member_declarations
881 : module_member_declaration
882 | module_member_declarations module_member_declaration
885 module_member_declaration
889 current_attributes = (Attributes) $1;
890 current_modifiers = (int) $2 | (int)Modifiers.STATIC; // FIXME: for type_declaration it can result in trouble
892 module_member_declarator
898 module_member_declarator
899 : static_constructor_declaration
902 Method method = (Method) $1;
903 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
906 | withevents_declaration /* This is a field but must be treated specially, see below */
907 | constant_declaration
908 | property_declaration
913 constant_declaration // TODO: implement truly the logic
914 : CONST identifier ASSIGN constant_expression
915 | CONST identifier AS qualified_identifier ASSIGN constant_expression
918 opt_class_member_declarations
920 | class_member_declarations
923 class_member_declarations
924 : class_member_declaration
925 | class_member_declarations class_member_declaration
928 class_member_declaration
932 current_attributes = (Attributes) $1;
933 current_modifiers = (int) $2;
935 class_member_declarator
941 class_member_declarator
942 : constructor_declaration
945 Method method = (Method) $1;
946 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
949 | constant_declaration
950 | property_declaration
952 | withevents_declaration /* This is a field but must be treated specially, see below */
963 : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
966 current_local_parameters = (Parameters) $4;
969 /* This is WEIRD: declaring a method (sub) in a module as static will
970 trigger a syntax error, but the same methods MUST be static in order
971 to be properly called
973 if (current_container is Module) {
974 if (current_modifiers == Modifiers.STATIC) {
975 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
979 current_modifiers = Modifiers.STATIC;
983 // Structure members are Public by default
984 if ((current_container is Struct) && (current_modifiers == 0))
985 current_modifiers = Modifiers.PUBLIC;
990 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
991 (Parameters) current_local_parameters, null, (Expression) $7,
994 method.Block = (Block) end_block();
997 if ($6 != null) { /* we have an event handler to take care of */
998 // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
999 string evt_def = ((MemberAccess)$6).ToString();
1000 int pos = evt_def.LastIndexOf (".");
1001 string evt_target = ((string) $2).Substring (0, pos);
1003 foreach (Property p in current_container.Properties) {
1004 if (p.Name == evt_target) {
1006 // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
1007 AddHandler (p.Set.Block, (Expression)$6, (string) $2);
1016 : FUNCTION identifier
1017 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type opt_implement_clause EOL
1020 current_local_parameters = (Parameters) $4;
1023 /* This is WEIRD: declaring a method (sub) in a module as static will
1024 trigger a syntax error, but the same methods MUST be static in order
1025 to be properly called
1027 if (current_container is Module) {
1028 if (current_modifiers == Modifiers.STATIC) {
1029 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1033 current_modifiers = Modifiers.STATIC;
1037 // Structure members are Public by default
1038 if ((current_container is Struct) && (current_modifiers == 0))
1039 current_modifiers = Modifiers.PUBLIC;
1040 // Add local var declaration
1042 ArrayList retval = new ArrayList ();
1043 retval.Add (new VariableDeclaration ((string) $2, (Expression) $7, lexer.Location));
1044 declare_local_variables ((Expression) $7, retval, lexer.Location);
1049 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
1050 (Parameters) current_local_parameters, null,
1051 (Expression) $7, lexer.Location);
1053 method.Block = end_block();
1060 : STRUCTURE identifier EOL
1061 opt_implement_clause
1064 string full_struct_name = MakeName ((string) $2);
1066 new_struct = new Struct (current_container, full_struct_name,
1067 (int) current_modifiers,
1068 (Attributes) current_attributes, lexer.Location);
1069 current_container = new_struct;
1070 current_container.Namespace = current_namespace;
1071 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1073 opt_struct_member_declarations
1075 Struct new_struct = (Struct) current_container;
1078 new_struct.Bases = (ArrayList) $4;
1080 current_container = current_container.Parent;
1081 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1087 opt_struct_member_declarations
1089 | struct_member_declarations
1092 struct_member_declarations
1093 : struct_member_declaration
1094 | struct_member_declarations struct_member_declaration
1097 struct_member_declaration
1099 struct_member_declarator
1101 struct_member_declarator
1103 //| constant_declaration
1104 | method_declaration
1105 | property_declaration
1107 | constructor_declaration
1111 * This is only included so we can flag error 575:
1112 * destructors only allowed on class types
1114 //| destructor_declaration
1118 : EVENT identifier AS type EOL
1120 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1122 Event e = new Event ((Expression) $4, var.identifier,
1123 null, current_modifiers, null, null,
1124 current_attributes, lexer.Location);
1126 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1129 // | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1131 // throw new NotSupportedException();
1136 : ENUM identifier opt_type_spec EOL
1137 opt_enum_member_declarations
1139 Location enum_location = lexer.Location;
1141 string full_name = MakeName ((string) $2);
1142 Mono.CSharp.Enum e = new Mono.CSharp.Enum (current_container, (Expression) $3, (int) current_modifiers, full_name,
1143 (Attributes) current_attributes, enum_location);
1145 foreach (VariableDeclaration ev in (ArrayList) $5) {
1146 Location loc = (Location) ev.Location;
1148 CheckDef (e.AddEnumMember (ev.identifier,
1149 (Expression) ev.expression_or_array_initializer,
1150 loc, ev.OptAttributes), ev.identifier, loc);
1153 e.Namespace = current_namespace;
1155 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1156 RootContext.Tree.RecordDecl (full_name, e);
1162 opt_enum_member_declarations
1163 : /* empty */ { $$ = new ArrayList (); }
1164 | enum_member_declarations { $$ = $1; }
1167 enum_member_declarations
1168 : enum_member_declaration
1170 ArrayList l = new ArrayList ();
1175 | enum_member_declarations enum_member_declaration
1177 ArrayList l = (ArrayList) $1;
1185 enum_member_declaration
1186 : opt_attributes identifier EOL
1188 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1190 | opt_attributes identifier
1192 $$ = lexer.Location;
1194 ASSIGN expression EOL
1196 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1200 interface_declaration
1201 : INTERFACE identifier EOL
1203 Interface new_interface;
1204 string full_interface_name = MakeName ((string) $2);
1206 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1207 (Attributes) current_attributes, lexer.Location);
1208 if (current_interface != null) {
1209 Location l = lexer.Location;
1210 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1212 current_interface = new_interface;
1213 new_interface.Namespace = current_namespace;
1214 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1219 Interface new_interface = (Interface) current_interface;
1222 new_interface.Bases = (ArrayList) $5;
1224 current_interface = null;
1225 CheckDef (current_container.AddInterface (new_interface),
1226 new_interface.Name, new_interface.Location);
1233 : /* empty */ { $$ = null; }
1238 : INHERITS interface_type_list { $$ = $2; }
1244 ArrayList interfaces = new ArrayList ();
1246 interfaces.Add ($1);
1249 | interface_type_list COMMA interface_type
1251 ArrayList interfaces = (ArrayList) $1;
1252 interfaces.Add ($3);
1258 : opt_interface_member_declarations
1261 opt_interface_member_declarations
1263 | interface_member_declarations
1266 interface_member_declarations
1267 : interface_member_declaration
1268 | interface_member_declarations interface_member_declaration
1271 interface_member_declaration
1272 : interface_method_declaration
1274 InterfaceMethod m = (InterfaceMethod) $1;
1276 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1278 | interface_property_declaration
1280 InterfaceProperty p = (InterfaceProperty) $1;
1282 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1284 | interface_event_declaration
1286 InterfaceEvent e = (InterfaceEvent) $1;
1288 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1293 : /* empty */ { $$ = false; }
1294 | NEW { $$ = true; }
1297 interface_method_declaration
1299 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1301 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1302 (Parameters) $4, current_attributes, lexer.Location);
1304 | FUNCTION identifier
1305 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1307 $$ = new InterfaceMethod (
1308 (Expression) $7, (string) $2, false, (Parameters) $4,
1309 current_attributes, lexer.Location);
1313 interface_property_declaration
1314 : PROPERTY identifier
1316 opt_formal_parameter_list
1317 CLOSE_PARENS opt_type_spec EOL
1319 // FIXME we MUST pass property parameters
1320 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1321 true, true, current_attributes,
1326 interface_event_declaration
1327 : opt_attributes opt_new EVENT type identifier EOL
1329 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1334 property_declaration
1335 : PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
1337 get_implicit_value_parameter_type = (Expression) $5;
1338 get_implicit_value_parameter_name = (string) $2;
1340 current_local_parameters = (Parameters) $3;
1341 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
1342 get_parameters = current_local_parameters.Copy (lexer.Location);
1343 set_parameters = current_local_parameters.Copy (lexer.Location);
1347 get_parameters = Parameters.EmptyReadOnlyParameters;
1348 set_parameters = new Parameters (null, null ,lexer.Location);
1350 lexer.PropertyParsing = true;
1352 $$ = lexer.Location;
1354 accessor_declarations
1357 lexer.PropertyParsing = false;
1360 Pair pair = (Pair) $9;
1361 Accessor get_block = (Accessor) pair.First;
1362 Accessor set_block = (Accessor) pair.Second;
1364 Location loc = lexer.Location;
1366 // Structure members are Public by default
1367 if ((current_container is Struct) && (current_modifiers == 0))
1368 current_modifiers = Modifiers.PUBLIC;
1370 prop = new Property ((Expression) $5, (string) $2, current_modifiers, get_block, set_block,
1371 current_attributes, loc, set_implicit_value_parameter_name,
1372 get_parameters, set_parameters, (Expression) $6);
1374 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1375 get_implicit_value_parameter_type = null;
1376 set_implicit_value_parameter_type = null;
1377 get_parameters = null;
1378 set_parameters = null;
1379 current_local_parameters = null;
1383 opt_property_parameters
1386 $$ = Parameters.EmptyReadOnlyParameters;
1388 | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1394 opt_implement_clause
1399 | IMPLEMENTS qualified_identifier
1401 $$ = DecomposeQI ((string)$2, lexer.Location);
1405 accessor_declarations
1406 : get_accessor_declaration opt_set_accessor_declaration
1408 $$ = new Pair ($1, $2);
1410 | set_accessor_declaration opt_get_accessor_declaration
1412 $$ = new Pair ($2, $1);
1416 opt_get_accessor_declaration
1417 : /* empty */ { $$ = null; }
1418 | get_accessor_declaration
1421 opt_set_accessor_declaration
1422 : /* empty */ { $$ = null; }
1423 | set_accessor_declaration
1426 get_accessor_declaration
1427 : opt_attributes GET EOL
1429 current_local_parameters = get_parameters;
1431 lexer.PropertyParsing = false;
1434 // Add local var declaration
1436 ArrayList retval = new ArrayList ();
1437 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1438 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
1444 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1445 current_local_parameters = null;
1446 lexer.PropertyParsing = true;
1450 set_accessor_declaration
1451 : opt_attributes SET opt_set_parameter EOL
1453 Parameter implicit_value_parameter = new Parameter (
1454 set_implicit_value_parameter_type,
1455 set_implicit_value_parameter_name,
1456 Parameter.Modifier.NONE, null);
1458 current_local_parameters = set_parameters;
1459 current_local_parameters.AppendParameter (implicit_value_parameter);
1462 lexer.PropertyParsing = false;
1467 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1468 current_local_parameters = null;
1469 lexer.PropertyParsing = true;
1476 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
1477 set_implicit_value_parameter_name = "Value";
1479 | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
1481 /* FIXME: possible syntax error which must be caught
1482 Set ( As <type>) is currently (and wrongly so) legal
1484 set_implicit_value_parameter_type = (Expression) $3;
1486 set_implicit_value_parameter_name = (string) $2;
1488 set_implicit_value_parameter_name = "Value";
1494 variable_declarators EOL
1496 int mod = (int) current_modifiers;
1499 VariableDeclaration.FixupTypes ((ArrayList) $2);
1500 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1502 if (current_container is Module)
1503 mod = mod | Modifiers.STATIC;
1505 // Structure members are Public by default
1506 if ((current_container is Struct) && (mod == 0))
1507 mod = Modifiers.PUBLIC;
1509 foreach (VariableDeclaration var in (ArrayList) $2){
1510 Location l = var.Location;
1512 Field field = new Field (var.type, mod, var.identifier,
1513 var.expression_or_array_initializer,
1514 (Attributes) null, l);
1516 CheckDef (current_container.AddField (field), field.Name, l);
1521 withevents_declaration
1522 : WITHEVENTS variable_declarators EOL
1524 /* WithEvents Fields must be resolved into properties
1525 with a bit of magic behind the scenes */
1527 VariableDeclaration.FixupTypes ((ArrayList) $2);
1529 foreach (VariableDeclaration var in (ArrayList) $2) {
1530 // 1 - We create a private field
1531 Location l = var.Location;
1533 if ((current_modifiers & Modifiers.STATIC) > 0)
1534 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1536 Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier,
1537 var.expression_or_array_initializer,
1538 (Attributes) null, l);
1540 CheckDef (current_container.AddField (field), field.Name, l);
1542 // 2 - Public property
1544 prop = BuildSimpleProperty (var.type, (string) var.identifier,
1545 field, (int) current_modifiers,
1546 (Attributes) current_attributes, l);
1548 CheckDef (current_container.AddProperty (prop), prop.Name, l);
1558 delegate_declaration
1560 identifier OPEN_PARENS
1561 opt_formal_parameter_list
1565 Location l = lexer.Location;
1566 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr,
1567 (int) current_modifiers,
1568 MakeName ((string) $3), (Parameters) $5,
1569 (Attributes) current_attributes, l);
1571 del.Namespace = current_namespace;
1572 CheckDef (current_container.AddDelegate (del), del.Name, l);
1575 identifier OPEN_PARENS
1576 opt_formal_parameter_list
1577 CLOSE_PARENS AS type
1579 Location l = lexer.Location;
1580 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
1582 (Expression) $8, (int) current_modifiers, MakeName ((string) $3),
1583 (Parameters) $5, (Attributes) current_attributes, l);
1585 del.Namespace = current_namespace;
1586 CheckDef (current_container.AddDelegate (del), del.Name, l);
1593 | HANDLES qualified_identifier
1595 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);
1601 | OPEN_PARENS CLOSE_PARENS
1604 static_constructor_declaration
1605 : SHARED SUB NEW opt_empty_parens EOL
1607 current_local_parameters = Parameters.EmptyReadOnlyParameters;
1609 oob_stack.Push (lexer.Location);
1611 Location l = (Location) oob_stack.Pop ();
1612 $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
1616 Constructor c = (Constructor) $1;
1617 c.Block = (Block) end_block();
1618 c.ModFlags = (int) current_modifiers;
1619 c.OptAttributes = current_attributes;
1621 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1622 current_local_parameters = null;
1626 constructor_declaration
1627 : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1629 current_local_parameters = (Parameters) $4;
1631 oob_stack.Push (lexer.Location);
1633 Location l = (Location) oob_stack.Pop ();
1634 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1639 Constructor c = (Constructor) $1;
1640 c.Block = (Block) end_block();
1641 c.ModFlags = (int) current_modifiers;
1642 c.OptAttributes = current_attributes;
1644 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1645 current_local_parameters = null;
1650 opt_formal_parameter_list
1653 $$ = Parameters.EmptyReadOnlyParameters;
1655 | formal_parameter_list
1658 //Parameter p = ((Parameters) $1).FixedParameters[0];
1662 formal_parameter_list
1665 ArrayList pars_list = (ArrayList) $1;
1667 Parameter [] pars = new Parameter [pars_list.Count];
1668 pars_list.CopyTo (pars);
1669 $$ = new Parameters (pars, null, lexer.Location);
1671 | fixed_parameters COMMA parameter_array
1673 ArrayList pars_list = (ArrayList) $1;
1675 Parameter [] pars = new Parameter [pars_list.Count];
1676 pars_list.CopyTo (pars);
1678 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
1682 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1689 ArrayList pars = new ArrayList ();
1694 | fixed_parameters COMMA fixed_parameter
1696 ArrayList pars = (ArrayList) $1;
1705 opt_parameter_modifier
1706 identifier opt_type_spec opt_variable_initializer
1708 Parameter.Modifier pm = (Parameter.Modifier)$2;
1709 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1711 if (opt_parm && ($5 == null))
1712 Report.Error (999, "Optional parameters must have a default value");
1715 if ((pm & Parameter.Modifier.REF) !=0)
1716 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1718 pm = Parameter.Modifier.NONE; //FIXME: should take into account BYREF
1720 $$ = new Parameter ((Expression) $4, (string) $3,
1721 pm, (Attributes) $1, (Expression) $5, opt_parm);
1726 : PARAM_ARRAY identifier opt_parens AS type
1728 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1729 // note ("type must be a single-dimension array type");
1735 | OPEN_PARENS CLOSE_PARENS
1738 opt_parameter_modifier
1739 : /* empty */ { $$ = Parameter.Modifier.VAL; }
1740 | parameter_modifiers { $$ = $1; }
1744 : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1745 | parameter_modifier { $$ = $1; }
1749 : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1750 | BYVAL { $$ = Parameter.Modifier.VAL; }
1751 | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; }
1756 | statement_list EOL
1761 | statement_list EOL statement
1765 declaration_statement
1767 if ($1 != null && (Block) $1 != current_block){
1768 current_block.AddStatement ((Statement) $1);
1769 current_block = (Block) $1;
1772 | embedded_statement
1774 Statement s = (Statement) $1;
1776 current_block.AddStatement ((Statement) $1);
1779 | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1781 AddHandler ((Expression) $2, (string) $5);
1783 | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1785 RaiseEvent ((string) $2, (ArrayList) $4);
1792 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1794 if (!current_block.AddLabel ((string) $1, labeled)){
1795 Location l = lexer.Location;
1796 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1798 current_block.AddStatement (labeled);
1804 : expression_statement
1805 | selection_statement
1806 | iteration_statement
1813 | continue_statement
1816 | */return_statement
1823 $$ = new Exit ((ExitType)$2, lexer.Location);
1828 : DO { $$ = ExitType.DO; }
1829 | FOR { $$ = ExitType.FOR; }
1830 | WHILE { $$ = ExitType.WHILE; }
1831 | SELECT { $$ = ExitType.SELECT; }
1832 | SUB { $$ = ExitType.SUB; }
1833 | FUNCTION { $$ = ExitType.FUNCTION; }
1834 | PROPERTY { $$ = ExitType.PROPERTY; }
1835 | TRY { $$ = ExitType.TRY; }
1838 : RETURN opt_expression
1840 $$ = new Return ((Expression) $2, lexer.Location);
1852 : FOR EACH IDENTIFIER IN
1854 oob_stack.Push (lexer.Location);
1858 oob_stack.Push (current_block);
1860 Block foreach_block = new Block (current_block, true);
1861 LocalVariableReference v = null;
1862 Location l = lexer.Location;
1863 v = new LocalVariableReference (foreach_block, (string) $3, l, null, false);
1864 current_block = foreach_block;
1867 oob_stack.Push (current_block);
1872 Block foreach_block = (Block) oob_stack.Pop ();
1873 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
1874 Block prev_block = (Block) oob_stack.Pop ();
1875 Location l = (Location) oob_stack.Pop ();
1877 current_block = prev_block;
1880 Foreach f = new Foreach (null, v, (Expression) $6, (Statement) $9, l);
1881 foreach_block.AddStatement (f);
1899 ArrayList s = new ArrayList ();
1901 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
1908 // Now s contains the list of specific catch clauses
1909 // and g contains the general one.
1910 Block b = end_block();
1912 $$ = new Try ((Block) b, s, g, null, lexer.Location);
1919 tmp_block = end_block();
1929 ArrayList s = new ArrayList ();
1930 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
1932 if (catch_list != null){
1933 foreach (Catch cc in catch_list) {
1941 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
1954 tmp_catch_clauses = (ArrayList) $5;
1959 : /* empty */ { $$ = null; }
1966 ArrayList l = new ArrayList ();
1971 | catch_clauses catch_clause
1973 ArrayList l = (ArrayList) $1;
1981 : /* empty */ { $$ = null; }
1986 : CATCH opt_catch_args EOL
1988 Expression type = null;
1992 DictionaryEntry cc = (DictionaryEntry) $2;
1993 type = (Expression) cc.Key;
1994 id = (string) cc.Value;
1997 ArrayList one = new ArrayList ();
1998 Location loc = lexer.Location;
2000 one.Add (new VariableDeclaration (id, null, loc));
2004 current_block = new Block (current_block);
2005 Block b = declare_local_variables (type, one, loc);
2011 opt_statement_list {
2012 Expression type = null;
2014 Block b_catch = current_block;
2017 DictionaryEntry cc = (DictionaryEntry) $2;
2018 type = (Expression) cc.Key;
2019 id = (string) cc.Value;
2023 // FIXME: I can change this for an assignment.
2025 while (current_block != (Block) $1)
2026 current_block = current_block.Parent;
2030 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
2035 : /* empty */ { $$ = null; }
2040 : identifier AS type
2042 $$ = new DictionaryEntry ($3, $1);
2048 : DO opt_do_construct EOL
2051 oob_stack.Push (lexer.Location);
2054 LOOP opt_do_construct
2056 Expression t_before = (Expression) $2;
2057 Expression t_after = (Expression) $7;
2060 if ((t_before != null) && (t_after != null))
2061 Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2063 if ((t_before == null) && (t_after == null))
2064 t = new BoolLiteral (true);
2066 t = (t_before != null) ? t_before : t_after;
2068 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2070 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2071 ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2072 t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2074 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2079 : /* empty */ { $$ = null; }
2080 | while_or_until boolean_expression
2082 do_type = (DoOptions)$1;
2083 $$ = (Expression) $2;
2088 : WHILE { $$ = DoOptions.WHILE; }
2089 | UNTIL { $$ = DoOptions.UNTIL; }
2096 oob_stack.Push (lexer.Location);
2098 boolean_expression EOL
2102 Location l = (Location) oob_stack.Pop ();
2103 Block b = end_block();
2104 Expression e = (Expression) $3;
2105 $$ = new While ((Expression) e, (Statement) b, l);
2111 : FOR qualified_identifier ASSIGN expression TO expression opt_step EOL
2116 NEXT opt_next_identifier
2118 Block statement = end_block();
2119 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2121 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2122 Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual,
2123 for_var, (Expression) $6, lexer.Location);
2124 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2125 for_var, (Expression) $7, lexer.Location), lexer.Location);
2127 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);
2128 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2130 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);
2135 : /* empty */ { $$ = new IntLiteral ((Int32) 1); }
2136 | STEP expression { $$ = $2; }
2141 | qualified_identifier
2150 : if_statement_open if_statement_rest
2157 : IF boolean_expression THEN EOL
2159 oob_stack.Push (lexer.Location);
2161 tmp_expr = (Expression) $2;
2170 Location l = (Location) oob_stack.Pop ();
2172 $$ = new If ((Expression) tmp_expr, (Statement) end_block(), l);
2179 tmp_block = end_block();
2185 Location l = (Location) oob_stack.Pop ();
2187 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2192 : SELECT opt_case expression EOL
2194 oob_stack.Push (lexer.Location);
2195 switch_stack.Push (current_block);
2200 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2201 current_block = (Block) switch_stack.Pop ();
2206 : /* empty */ { $$ = null; }
2207 | case_sections { $$ = $1; }
2211 : case_sections case_section
2213 ArrayList sections = (ArrayList) $1;
2220 ArrayList sections = new ArrayList ();
2228 : CASE case_clauses EOL
2234 Block topmost = current_block;
2236 while (topmost.Implicit)
2237 topmost = topmost.Parent;
2239 // FIXME: This is a horrible hack which MUST go
2240 topmost.statements.Add (new Break (lexer.Location));
2241 $$ = new SwitchSection ((ArrayList) $2, topmost);
2244 /* FIXME: we should somehow flag an error
2245 (BC30321 'Case' cannot follow a 'Case Else'
2246 in the same 'Select' statement.)
2247 if Case Else is not the last of the Case clauses
2254 Block topmost = current_block;
2256 while (topmost.Implicit)
2257 topmost = topmost.Parent;
2259 // FIXME: This is a horrible hack which MUST go
2260 topmost.statements.Add (new Break (lexer.Location));
2262 ArrayList a = new ArrayList();
2263 a.Add (new SwitchLabel (null, lexer.Location));
2264 $$ = new SwitchSection ((ArrayList) a, topmost);
2271 ArrayList labels = new ArrayList ();
2276 | case_clauses COMMA case_clause
2278 ArrayList labels = (ArrayList) ($1);
2286 : opt_is comparison_operator expression
2289 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2311 expression_statement
2312 : statement_expression
2318 statement_expression
2319 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2320 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2321 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2324 object_creation_expression
2325 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2327 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2332 : object_creation_expression
2333 /* | array_creation_expression */
2336 declaration_statement
2337 : local_variable_declaration
2340 DictionaryEntry de = (DictionaryEntry) $1;
2342 $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2346 | local_constant_declaration
2349 DictionaryEntry de = (DictionaryEntry) $1;
2351 $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
2356 local_variable_declaration
2357 : DIM variable_declarators
2359 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);
2361 /*| DIM variable_declarators
2363 $$ = new DictionaryEntry (TypeManager.system_object_expr, $2);
2365 | DIM variable_declarators AS object_creation_expression
2368 $$ = new DictionaryEntry ($4, $2);
2376 local_constant_declaration
2377 : CONST constant_declarator
2380 $$ = new DictionaryEntry ($1, $2);
2387 : identifier ASSIGN constant_expression
2389 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
2393 variable_declarators
2394 : variable_declarator
2396 ArrayList decl = new ArrayList ();
2400 | variable_declarators COMMA variable_declarator
2402 ArrayList decls = (ArrayList) $1;
2409 : variable_identifier opt_type_decl opt_variable_initializer
2411 string varname = (string)$1;
2413 object varinit = $3;
2414 Expression vartype = (Expression) $2;
2417 Check for a declaration like Dim a(2) or Dim a(2,3)
2418 If this is the case, we must generate an ArrayCreationExpression
2419 and, in case, add the initializer after the array has been created.
2421 if (VariableDeclaration.IsArrayDecl (varname)) {
2422 if (VariableDeclaration.DimsSpecified(varname)) {
2423 varname = VariableDeclaration.StripDims (varname, ref dims);
2424 ArrayList a_dims = VariableDeclaration.ParseDimList(dims);
2425 varinit = new ArrayCreation (vartype, a_dims,"", (ArrayList) varinit, lexer.Location);
2427 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.GetRank (dims), lexer.Location);
2430 if (vartype is New) {
2431 if (varinit != null) {
2432 Report.Error (30205, lexer.Location, "End of statement expected");
2438 vartype = ((New)vartype).RequestedType;
2441 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
2446 : identifier opt_array_name_modifier
2450 $$ = (string)$$ + (string)$2;
2455 : /* empty */ { $$ = null; }
2456 | AS type { $$ = (Expression) $2; };
2464 | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS
2466 Report.Error (30638, "Array bounds cannot appear in type specifiers");
2471 New n = new New ((Expression)$3, null, lexer.Location);
2472 $$ = (Expression) n;
2474 | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2476 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
2477 $$ = (Expression) n;
2481 opt_array_name_modifier
2482 : /* empty */ { $$ = null; }
2483 | array_type_modifier { $$ = $1; }
2487 : rank_specifiers { $$ = $1; }
2490 opt_variable_initializer
2491 : /* empty */ { $$ = null; }
2492 | ASSIGN variable_initializer { $$ = $2; }
2495 variable_initializer
2508 : OPEN_BRACE CLOSE_BRACE
2510 ArrayList list = new ArrayList ();
2513 | OPEN_BRACE variable_initializer_list CLOSE_BRACE
2515 $$ = (ArrayList) $2;
2519 variable_initializer_list
2520 : variable_initializer
2522 ArrayList list = new ArrayList ();
2526 | variable_initializer_list COMMA variable_initializer
2528 ArrayList list = (ArrayList) $1;
2535 * The following is from Rhys' grammar:
2536 * > Types in local variable declarations must be recognized as
2537 * > expressions to prevent reduce/reduce errors in the grammar.
2538 * > The expressions are converted into types during semantic analysis.
2541 : primary_expression opt_rank_specifier
2543 // FIXME: Do something smart here regarding the composition of the type.
2545 // Ok, the above "primary_expression" is there to get rid of
2546 // both reduce/reduce and shift/reduces in the grammar, it should
2547 // really just be "type_name". If you use type_name, a reduce/reduce
2548 // creeps up. If you use qualified_identifier (which is all we need
2549 // really) two shift/reduces appear.
2552 // So the super-trick is that primary_expression
2553 // can only be either a SimpleName or a MemberAccess.
2554 // The MemberAccess case arises when you have a fully qualified type-name like :
2556 // SimpleName is when you have
2559 Expression expr = (Expression) $1;
2560 if (!(expr is SimpleName || expr is MemberAccess)) {
2561 Error_ExpectingTypeName (lexer.Location, expr);
2565 // So we extract the string corresponding to the SimpleName
2568 if ((string) $2 == "")
2571 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2574 | builtin_types opt_rank_specifier
2576 if ((string) $2 == "")
2579 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2588 | rank_specifiers rank_specifier
2590 $$ = (string) $2 + (string) $1;
2595 : OPEN_PARENS opt_dim_separators CLOSE_PARENS
2597 $$ = "[" + (string) $2 + "]";
2632 | dim_separators COMMA
2634 $$ = (string) $1 + ",";
2639 : integer_literal { $$ = ((IntLiteral)$1).AsString(); }
2640 | dim_specifiers COMMA integer_literal { $$ = $1 + "," + ((IntLiteral)$3).AsString(); }
2650 | qualified_identifier
2652 string name = (string) $1;
2654 $$ = DecomposeQI (name, lexer.Location);
2656 | parenthesized_expression
2658 | invocation_expression
2669 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
2670 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
2671 | NOTHING { $$ = NullLiteral.Null; }
2675 : LITERAL_SINGLE { $$ = new FloatLiteral ((float) lexer.Value); }
2676 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
2677 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
2682 object v = lexer.Value;
2685 $$ = new IntLiteral ((Int32) v);
2687 $$ = new UIntLiteral ((UInt32) v);
2689 $$ = new LongLiteral ((Int64) v);
2690 else if (v is ulong)
2691 $$ = new ULongLiteral ((UInt64) v);
2693 Console.WriteLine ("OOPS. Unexpected result from scanner");
2699 : TRUE { $$ = new BoolLiteral (true); }
2700 | FALSE { $$ = new BoolLiteral (false); }
2703 parenthesized_expression
2704 : OPEN_PARENS expression CLOSE_PARENS
2709 : primary_expression DOT identifier
2711 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2713 | predefined_type DOT identifier
2715 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2723 invocation_expression
2724 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2727 Location l = lexer.Location;
2728 Report.Error (1, l, "THIS IS CRAZY");
2730 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2732 | MYBASE DOT identifier OPEN_PARENS opt_argument_list CLOSE_PARENS
2734 BaseAccess ba = new BaseAccess ((string) $3, lexer.Location);
2735 $$ = new Invocation ((Expression) ba, (ArrayList) $5, lexer.Location);
2737 | MYBASE DOT NEW OPEN_PARENS opt_argument_list CLOSE_PARENS
2739 BaseAccess ba = new BaseAccess ("New", lexer.Location);
2740 $$ = new Invocation ((Expression) ba, (ArrayList) $5, lexer.Location);
2748 The 'argument' rule returns an 'empty' argument
2749 of type NoArg (used for default arguments in invocations)
2750 if no arguments are actually passed.
2752 If there is only one argument and it is o type NoArg,
2753 we return a null (empty) list
2755 ArrayList args = (ArrayList) $1;
2756 if (args.Count == 1 &&
2757 ((Argument)args[0]).ArgType == Argument.AType.NoArg)
2767 ArrayList list = new ArrayList ();
2771 | argument_list COMMA argument
2773 ArrayList list = (ArrayList) $1;
2782 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2784 | BYREF variable_reference
2786 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2790 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
2795 : expression {/* note ("section 5.4"); */ $$ = $1; }
2799 : primary_expression OPEN_PARENS expression_list CLOSE_PARENS
2802 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2804 /* | primary_expression rank_specifiers
2806 // So the super-trick is that primary_expression
2807 // can only be either a SimpleName or a MemberAccess.
2808 // The MemberAccess case arises when you have a fully qualified type-name like :
2810 // SimpleName is when you have
2812 Expression expr = (Expression) $1;
2814 if (!(expr is SimpleName || expr is MemberAccess)) {
2815 Error_ExpectingTypeName (lexer.Location, expr);
2816 $$ = TypeManager.system_object_expr;
2819 // So we extract the string corresponding to the SimpleName
2822 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2828 : conditional_expression { $$ = $1; }
2829 /*| assignment_expression*/
2840 ArrayList list = new ArrayList ();
2844 | expression_list COMMA expression
2846 ArrayList list = (ArrayList) $1;
2853 : /*empty */ { $$ = null; }
2860 $$ = new This (current_block, lexer.Location);
2865 : primary_expression
2866 | NOT prefixed_unary_expression
2868 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2874 : cast_operator OPEN_PARENS expression CLOSE_PARENS
2876 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2878 | CTYPE OPEN_PARENS expression COMMA expression CLOSE_PARENS
2880 $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
2885 : CBOOL { $$ = TypeManager.system_boolean_expr; }
2886 | CBYTE { $$ = TypeManager.system_byte_expr; }
2887 | CCHAR { $$ = TypeManager.system_char_expr; }
2888 | CDATE { $$ = TypeManager.system_decimal_expr; } //FIXME
2889 | CDBL { $$ = TypeManager.system_double_expr; }
2890 | CDEC { $$ = TypeManager.system_decimal_expr; }
2891 | CINT { $$ = TypeManager.system_int32_expr; }
2892 | CLNG { $$ = TypeManager.system_int64_expr; }
2893 | COBJ { $$ = TypeManager.system_object_expr; }
2894 | CSHORT { $$ = TypeManager.system_int16_expr; }
2895 | CSNG { $$ = TypeManager.system_single_expr; }
2896 | CSTR { $$ = TypeManager.system_string_expr; }
2900 // The idea to split this out is from Rhys' grammar
2901 // to solve the problem with casts.
2903 prefixed_unary_expression
2905 | PLUS prefixed_unary_expression
2907 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2909 | MINUS prefixed_unary_expression
2911 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2913 | ADDRESSOF prefixed_unary_expression
2915 // FIXME: We should generate an error if AddressOf is NOT used
2916 // during delegate creation
2921 multiplicative_expression
2922 : prefixed_unary_expression
2923 | multiplicative_expression STAR prefixed_unary_expression
2925 $$ = new Binary (Binary.Operator.Multiply,
2926 (Expression) $1, (Expression) $3, lexer.Location);
2928 | multiplicative_expression DIV prefixed_unary_expression
2930 $$ = new Binary (Binary.Operator.Division,
2931 (Expression) $1, (Expression) $3, lexer.Location);
2933 | multiplicative_expression OP_MODULUS prefixed_unary_expression
2935 $$ = new Binary (Binary.Operator.Modulus,
2936 (Expression) $1, (Expression) $3, lexer.Location);
2941 : multiplicative_expression
2942 | additive_expression PLUS multiplicative_expression
2944 $$ = new Binary (Binary.Operator.Addition,
2945 (Expression) $1, (Expression) $3, lexer.Location);
2947 | additive_expression MINUS multiplicative_expression
2949 $$ = new Binary (Binary.Operator.Subtraction,
2950 (Expression) $1, (Expression) $3, lexer.Location);
2952 | additive_expression OP_CONCAT multiplicative_expression
2954 // FIXME: This should only work for String expressions
2955 // We probably need to use something from the runtime
2956 $$ = new Binary (Binary.Operator.Addition,
2957 (Expression) $1, (Expression) $3, lexer.Location);
2961 relational_expression
2962 : additive_expression
2963 | relational_expression OP_LT additive_expression
2965 $$ = new Binary (Binary.Operator.LessThan,
2966 (Expression) $1, (Expression) $3, lexer.Location);
2968 | relational_expression OP_GT additive_expression
2970 $$ = new Binary (Binary.Operator.GreaterThan,
2971 (Expression) $1, (Expression) $3, lexer.Location);
2973 | relational_expression OP_LE additive_expression
2975 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2976 (Expression) $1, (Expression) $3, lexer.Location);
2978 | relational_expression OP_GE additive_expression
2980 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2981 (Expression) $1, (Expression) $3, lexer.Location);
2983 | relational_expression IS type_name
2985 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2987 | relational_expression IS NOTHING
2989 $$ = new Binary (Binary.Operator.Equality,
2990 (Expression) $1, (Expression) NullLiteral.Null, lexer.Location);
2992 | relational_expression AS type_name
2994 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2999 : relational_expression
3000 | equality_expression ASSIGN relational_expression
3002 $$ = new Binary (Binary.Operator.Equality,
3003 (Expression) $1, (Expression) $3, lexer.Location);
3008 : equality_expression
3009 | and_expression OP_AND equality_expression
3011 $$ = new Binary (Binary.Operator.BitwiseAnd,
3012 (Expression) $1, (Expression) $3, lexer.Location);
3016 exclusive_or_expression
3018 | exclusive_or_expression OP_XOR and_expression
3020 $$ = new Binary (Binary.Operator.ExclusiveOr,
3021 (Expression) $1, (Expression) $3, lexer.Location);
3025 conditional_and_expression
3026 : exclusive_or_expression
3027 | conditional_and_expression OP_AND exclusive_or_expression
3029 $$ = new Binary (Binary.Operator.LogicalAnd,
3030 (Expression) $1, (Expression) $3, lexer.Location);
3034 conditional_or_expression
3035 : conditional_and_expression
3036 | conditional_or_expression OP_OR conditional_and_expression
3038 $$ = new Binary (Binary.Operator.LogicalOr,
3039 (Expression) $1, (Expression) $3, lexer.Location);
3043 conditional_expression
3044 : conditional_or_expression
3047 assignment_expression
3048 : prefixed_unary_expression ASSIGN expression
3050 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3063 : type_name { /* class_type */
3065 This does interfaces, delegates, struct_types, class_types,
3066 parent classes, and more! 4.2
3068 $$ = DecomposeQI ((string) $1, lexer.Location);
3078 ArrayList types = new ArrayList ();
3083 | type_list COMMA type
3085 ArrayList types = (ArrayList) $1;
3093 : namespace_or_type_name
3096 namespace_or_type_name
3097 : qualified_identifier
3101 : type bracketed_rank_specifiers
3103 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3107 bracketed_rank_specifiers
3108 : bracketed_rank_specifier bracketed_opt_rank_specifier
3110 $$ = (string) $2 + (string) $1;
3114 bracketed_rank_specifier
3115 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
3117 $$ = "[" + (string) $2 + "]";
3121 bracketed_opt_rank_specifier
3126 | bracketed_rank_specifiers
3132 /* Built-in / Integral types */
3134 : OBJECT { $$ = TypeManager.system_object_expr; }
3135 | STRING { $$ = TypeManager.system_string_expr; }
3136 | BOOLEAN { $$ = TypeManager.system_boolean_expr; }
3137 | DECIMAL { $$ = TypeManager.system_decimal_expr; }
3138 | SINGLE { $$ = TypeManager.system_single_expr; }
3139 | DOUBLE { $$ = TypeManager.system_double_expr; }
3144 : /*SBYTE { $$ = TypeManager.system_sbyte_expr; }
3145 | BYTE { $$ = TypeManager.system_byte_expr; }
3146 | SHORT { $$ = TypeManager.system_int16_expr; }
3147 | USHORT { $$ = TypeManager.system_uint16_expr; }
3148 | */ INTEGER { $$ = TypeManager.system_int32_expr; }/*
3149 | UINT { $$ = TypeManager.system_uint32_expr; }
3150 | LONG { $$ = TypeManager.system_int64_expr; }
3151 | ULONG { $$ = TypeManager.system_uint64_expr; }
3152 | CHAR { $$ = TypeManager.system_char_expr; }
3153 | VOID { $$ = TypeManager.system_void_expr; }*/
3164 public Tokenizer Lexer {
3170 public static Expression DecomposeQI (string name, Location loc)
3174 if (name.IndexOf ('.') == -1){
3175 return new SimpleName (name, loc);
3177 int pos = name.LastIndexOf (".");
3178 string left = name.Substring (0, pos);
3179 string right = name.Substring (pos + 1);
3181 o = DecomposeQI (left, loc);
3183 return new MemberAccess (o, right, loc);
3187 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3189 Block implicit_block;
3190 ArrayList inits = null;
3193 // We use the `Used' property to check whether statements
3194 // have been added to the current block. If so, we need
3195 // to create another block to contain the new declaration
3196 // otherwise, as an optimization, we use the same block to
3197 // add the declaration.
3199 // FIXME: A further optimization is to check if the statements
3200 // that were added were added as part of the initialization
3201 // below. In which case, no other statements have been executed
3202 // and we might be able to reduce the number of blocks for
3203 // situations like this:
3205 // int j = 1; int k = j + 1;
3208 VariableDeclaration.FixupTypes (variable_declarators);
3210 if (current_block.Used) {
3211 implicit_block = new Block (current_block, true, loc, Location.Null);
3212 implicit_block.AddChildVariableNames (current_block);
3214 implicit_block = current_block;
3216 foreach (VariableDeclaration decl in variable_declarators){
3217 Expression type = decl.type;
3218 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3219 if (decl.expression_or_array_initializer != null){
3221 inits = new ArrayList ();
3228 return implicit_block;
3230 foreach (VariableDeclaration decl in inits){
3233 Expression type = decl.type;
3235 if ((decl.expression_or_array_initializer is Expression) ||
3236 (decl.expression_or_array_initializer is New)) {
3237 expr = (Expression) decl.expression_or_array_initializer;
3239 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3241 expr = new ArrayCreation (type, "", init, decl.Location);
3244 LocalVariableReference var;
3245 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3247 assign = new Assign (var, expr, decl.Location);
3249 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3252 return implicit_block;
3256 Block declare_local_constant (Expression type, VariableDeclaration decl)
3258 Block implicit_block;
3260 if (current_block.Used)
3261 implicit_block = new Block (current_block, true);
3263 implicit_block = current_block;
3265 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3266 current_local_parameters, decl.Location))){
3269 return implicit_block;
3273 // A class used to pass around variable declarations and constants
3275 public class VariableDeclaration {
3276 public string identifier;
3277 public object expression_or_array_initializer;
3278 public Location Location;
3279 public Attributes OptAttributes;
3280 public Expression type;
3281 public ArrayList dims;
3283 public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
3285 this.identifier = id;
3286 this.expression_or_array_initializer = eoai;
3288 this.OptAttributes = opt_attrs;
3293 public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3297 public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
3301 public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this
3302 (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
3306 public static void FixupTypes (ArrayList vars)
3308 int varcount = vars.Count;
3309 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
3311 if (last_var.type == null)
3312 last_var.type = TypeManager.system_object_expr;
3314 Expression cur_type = last_var.type;
3315 int n = varcount - 1;
3318 VariableDeclaration var = (VariableDeclaration) vars[n--];
3319 if (var.type == null)
3320 var.type = cur_type;
3322 cur_type = var.type;
3326 public static bool DimsSpecified (string varname)
3330 if (varname.IndexOf("[") >= 0) {
3331 char[] ds = {'1','2','3','4','5','6','7','8','9'};
3333 string dimpart = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3334 if (dimpart.IndexOfAny (ds) >= 0)
3340 public static string StripDims (string varname, ref string d)
3342 string res = varname;
3345 if (varname.IndexOf("[") >= 0) {
3346 dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3347 res = varname.Substring(0, varname.IndexOf("["));
3353 public static string StripDims (string varname)
3357 return (StripDims(varname, ref dres));
3360 public static string GetRank (string dims)
3365 for (x = 0; x < dims.Length; x++) {
3366 if (dims[x] == '[' || dims[x] == ']' || dims[x] == ',')
3367 res = res + dims[x];
3372 public static ArrayList ParseDimList (string dims)
3374 ArrayList res = new ArrayList();
3375 string d = dims.Substring (1, dims.Length -2);
3376 Array a = d.Split (',');
3378 if (a.GetLength(0) > 32) {
3379 Report.Error (999, "Arrays cannot have more than 32 dimensions");
3382 foreach (string s in a)
3384 res.Add (new IntLiteral ((Int32) Convert.ToInt32(s)));
3386 res.Add (new IntLiteral ((Int32) 0));
3391 public static bool IsArrayDecl (string varname)
3393 return (varname.IndexOf("[") >= 0);
3396 public static void FixupArrayTypes (ArrayList vars)
3398 int varcount = vars.Count;
3401 foreach (VariableDeclaration var in vars) {
3402 if (var.identifier.EndsWith(",")) {
3403 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","),
3404 var.identifier.LastIndexOf(",")) + "]";
3405 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
3406 var.type = new ComposedCast (var.type, (string) dims, var.Location);
3412 public Property BuildSimpleProperty (Expression p_type, string name,
3413 Field p_fld, int mod_flags,
3414 Attributes attrs, Location loc)
3417 Block get_block, set_block;
3418 Accessor acc_set, acc_get;
3419 StatementExpression a_set;
3424 Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
3425 args = new Parameter [1];
3426 args [0] = implicit_value_parameter;
3428 Parameters set_params = new Parameters (args, null, loc);
3429 a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
3430 (Expression) new SimpleName("value", loc), loc), loc);
3432 set_block = new Block (current_block, set_params, loc, Location.Null);
3433 set_block.AddStatement ((Statement) a_set);
3434 acc_set = new Accessor (set_block, attrs);
3437 a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
3438 get_block = new Block (current_block, null, loc, Location.Null);
3439 get_block.AddStatement ((Statement) a_get);
3440 acc_get = new Accessor (get_block, attrs);
3442 p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
3449 current_block = new Block (current_block, current_local_parameters,
3450 lexer.Location, Location.Null);
3457 while (current_block.Implicit)
3458 current_block = current_block.Parent;
3460 res = current_block;
3462 current_block.SetEndLocation (lexer.Location);
3463 current_block = current_block.Parent;
3468 private void AddHandler (Expression evt_definition, string handler_name)
3470 AddHandler (current_block, evt_definition, handler_name);
3473 void CheckAttributeTarget (string a)
3477 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3481 Location l = lexer.Location;
3482 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3487 private void AddHandler (Block b, Expression evt_id, string handler_name)
3489 Location loc = lexer.Location;
3490 string evt_target = evt_id.ToString();
3491 evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
3492 Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
3496 private void RaiseEvent (string evt_name, ArrayList args)
3498 Location loc = lexer.Location;
3500 Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
3501 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc));
3502 current_block.AddStatement (s);
3505 // FIXME: THIS DOES NOT WORK!!!
3506 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
3508 Location loc = lexer.Location;
3509 ArrayList neh_args = new ArrayList();
3510 neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
3512 ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
3514 CompoundAssign ca = new CompoundAssign (
3515 Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
3517 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc));
3522 // This method is used to get at the complete string representation of
3523 // a fully-qualified type name, hiding inside a MemberAccess ;-)
3524 // This is necessary because local_variable_type admits primary_expression
3525 // as the type of the variable. So we do some extra checking
3527 string GetQualifiedIdentifier (Expression expr)
3529 if (expr is SimpleName)
3530 return ((SimpleName)expr).Name;
3531 else if (expr is MemberAccess)
3532 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3534 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3538 private void RemoveHandler (Expression evt_definition, string handler_name)
3540 RemoveHandler (current_block, evt_definition, handler_name);
3545 void Error_ExpectingTypeName (Location l, Expression expr)
3547 if (expr is Invocation){
3548 Report.Error (1002, l, "; expected");
3550 Report.Error (-1, l, "Invalid Type definition");
3554 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
3558 public override int parse ()
3560 current_namespace = new Namespace (null, RootContext.RootNamespace);
3561 current_container = RootContext.Tree.Types;
3562 current_container.Namespace = current_namespace;
3563 oob_stack = new Stack ();
3564 switch_stack = new Stack ();
3566 UseExtendedSyntax = name.EndsWith(".mbs");
3567 OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
3568 OptionStrict = InitialOptionStrict || UseExtendedSyntax;
3569 OptionCompareBinary = InitialOptionCompareBinary;
3571 lexer = new Tokenizer (input, name, defines);
3572 StringBuilder value = new StringBuilder ();
3573 //yacc_verbose_flag=true;
3576 if (yacc_verbose_flag)
3577 yyparse (lexer, new yydebug.yyDebugSimple ());
3583 Console.WriteLine (lexer.location + " : Parsing error in " + lexer.ref_name);
3584 Report.Error (9999, lexer.Location, "");
3585 Console.WriteLine (e);
3588 return Report.Errors;