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; }
844 : MODULE identifier EOL
848 name = MakeName((string) $2);
849 new_module = new Module(current_container,
851 current_modifiers, // already checks then
852 (Attributes) current_attributes,
854 current_container = new_module;
855 current_container.Namespace = current_namespace;
856 RootContext.Tree.RecordDecl(name, new_module);
858 opt_class_member_declarations
861 Module new_module = (Module)current_container;
863 current_container = current_container.Parent;
864 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
870 opt_module_member_declarations
872 | module_member_declarations
875 module_member_declarations
876 : module_member_declaration
877 | module_member_declarations module_member_declaration
880 module_member_declaration
884 current_attributes = (Attributes) $1;
885 current_modifiers = (int) $2 | (int)Modifiers.STATIC; // FIXME: for type_declaration it can result in trouble
887 module_member_declarator
893 module_member_declarator
894 : static_constructor_declaration
897 Method method = (Method) $1;
898 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
901 | withevents_declaration /* This is a field but must be treated specially, see below */
902 | constant_declaration
903 | property_declaration
908 constant_declaration // TODO: implement truly the logic
909 : CONST identifier ASSIGN constant_expression
910 | CONST identifier AS qualified_identifier ASSIGN constant_expression
913 opt_class_member_declarations
915 | class_member_declarations
918 class_member_declarations
919 : class_member_declaration
920 | class_member_declarations class_member_declaration
923 class_member_declaration
927 current_attributes = (Attributes) $1;
928 current_modifiers = (int) $2;
930 class_member_declarator
936 class_member_declarator
937 : constructor_declaration
940 Method method = (Method) $1;
941 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
944 | constant_declaration
945 | property_declaration
947 | withevents_declaration /* This is a field but must be treated specially, see below */
958 : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
961 current_local_parameters = (Parameters) $4;
964 /* This is WEIRD: declaring a method (sub) in a module as static will
965 trigger a syntax error, but the same methods MUST be static in order
966 to be properly called
968 if (current_container is Module) {
969 if (current_modifiers == Modifiers.STATIC) {
970 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
974 current_modifiers = Modifiers.STATIC;
978 // Structure members are Public by default
979 if ((current_container is Struct) && (current_modifiers == 0))
980 current_modifiers = Modifiers.PUBLIC;
985 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
986 (Parameters) current_local_parameters, null, (Expression) $7,
989 method.Block = (Block) end_block();
992 if ($6 != null) { /* we have an event handler to take care of */
993 // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
994 string evt_def = ((MemberAccess)$6).ToString();
995 int pos = evt_def.LastIndexOf (".");
996 string evt_target = ((string) $2).Substring (0, pos);
998 foreach (Property p in current_container.Properties) {
999 if (p.Name == evt_target) {
1001 // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
1002 AddHandler (p.Set.Block, (Expression)$6, (string) $2);
1011 : FUNCTION identifier
1012 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type opt_implement_clause EOL
1015 current_local_parameters = (Parameters) $4;
1018 /* This is WEIRD: declaring a method (sub) in a module as static will
1019 trigger a syntax error, but the same methods MUST be static in order
1020 to be properly called
1022 if (current_container is Module) {
1023 if (current_modifiers == Modifiers.STATIC) {
1024 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
1028 current_modifiers = Modifiers.STATIC;
1032 // Structure members are Public by default
1033 if ((current_container is Struct) && (current_modifiers == 0))
1034 current_modifiers = Modifiers.PUBLIC;
1035 // Add local var declaration
1037 ArrayList retval = new ArrayList ();
1038 retval.Add (new VariableDeclaration ((string) $2, (Expression) $7, lexer.Location));
1039 declare_local_variables ((Expression) $7, retval, lexer.Location);
1044 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
1045 (Parameters) current_local_parameters, null,
1046 (Expression) $7, lexer.Location);
1048 method.Block = end_block();
1055 : STRUCTURE identifier EOL
1056 opt_implement_clause
1059 string full_struct_name = MakeName ((string) $2);
1061 new_struct = new Struct (current_container, full_struct_name,
1062 (int) current_modifiers,
1063 (Attributes) current_attributes, lexer.Location);
1064 current_container = new_struct;
1065 current_container.Namespace = current_namespace;
1066 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
1068 opt_struct_member_declarations
1070 Struct new_struct = (Struct) current_container;
1073 new_struct.Bases = (ArrayList) $4;
1075 current_container = current_container.Parent;
1076 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
1082 opt_struct_member_declarations
1084 | struct_member_declarations
1087 struct_member_declarations
1088 : struct_member_declaration
1089 | struct_member_declarations struct_member_declaration
1092 struct_member_declaration
1094 struct_member_declarator
1096 struct_member_declarator
1098 //| constant_declaration
1099 | method_declaration
1100 | property_declaration
1102 | constructor_declaration
1106 * This is only included so we can flag error 575:
1107 * destructors only allowed on class types
1109 //| destructor_declaration
1113 : EVENT identifier AS type EOL
1115 VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
1117 Event e = new Event ((Expression) $4, var.identifier,
1118 null, current_modifiers, null, null,
1119 current_attributes, lexer.Location);
1121 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1124 // | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1126 // throw new NotSupportedException();
1131 : ENUM identifier opt_type_spec EOL
1132 opt_enum_member_declarations
1134 Location enum_location = lexer.Location;
1136 string full_name = MakeName ((string) $2);
1137 Mono.CSharp.Enum e = new Mono.CSharp.Enum (current_container, (Expression) $3, (int) current_modifiers, full_name,
1138 (Attributes) current_attributes, enum_location);
1140 foreach (VariableDeclaration ev in (ArrayList) $5) {
1141 Location loc = (Location) ev.Location;
1143 CheckDef (e.AddEnumMember (ev.identifier,
1144 (Expression) ev.expression_or_array_initializer,
1145 loc, ev.OptAttributes), ev.identifier, loc);
1148 e.Namespace = current_namespace;
1150 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1151 RootContext.Tree.RecordDecl (full_name, e);
1157 opt_enum_member_declarations
1158 : /* empty */ { $$ = new ArrayList (); }
1159 | enum_member_declarations { $$ = $1; }
1162 enum_member_declarations
1163 : enum_member_declaration
1165 ArrayList l = new ArrayList ();
1170 | enum_member_declarations enum_member_declaration
1172 ArrayList l = (ArrayList) $1;
1180 enum_member_declaration
1181 : opt_attributes identifier EOL
1183 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1185 | opt_attributes identifier
1187 $$ = lexer.Location;
1189 ASSIGN expression EOL
1191 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1195 interface_declaration
1196 : INTERFACE identifier EOL
1198 Interface new_interface;
1199 string full_interface_name = MakeName ((string) $2);
1201 new_interface = new Interface (current_container, full_interface_name, (int) current_modifiers,
1202 (Attributes) current_attributes, lexer.Location);
1203 if (current_interface != null) {
1204 Location l = lexer.Location;
1205 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1207 current_interface = new_interface;
1208 new_interface.Namespace = current_namespace;
1209 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1214 Interface new_interface = (Interface) current_interface;
1217 new_interface.Bases = (ArrayList) $5;
1219 current_interface = null;
1220 CheckDef (current_container.AddInterface (new_interface),
1221 new_interface.Name, new_interface.Location);
1228 : /* empty */ { $$ = null; }
1233 : INHERITS interface_type_list { $$ = $2; }
1239 ArrayList interfaces = new ArrayList ();
1241 interfaces.Add ($1);
1244 | interface_type_list COMMA interface_type
1246 ArrayList interfaces = (ArrayList) $1;
1247 interfaces.Add ($3);
1253 : opt_interface_member_declarations
1256 opt_interface_member_declarations
1258 | interface_member_declarations
1261 interface_member_declarations
1262 : interface_member_declaration
1263 | interface_member_declarations interface_member_declaration
1266 interface_member_declaration
1267 : interface_method_declaration
1269 InterfaceMethod m = (InterfaceMethod) $1;
1271 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1273 | interface_property_declaration
1275 InterfaceProperty p = (InterfaceProperty) $1;
1277 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1279 | interface_event_declaration
1281 InterfaceEvent e = (InterfaceEvent) $1;
1283 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1288 : /* empty */ { $$ = false; }
1289 | NEW { $$ = true; }
1292 interface_method_declaration
1294 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1296 $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
1297 (Parameters) $4, current_attributes, lexer.Location);
1299 | FUNCTION identifier
1300 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
1302 $$ = new InterfaceMethod (
1303 (Expression) $7, (string) $2, false, (Parameters) $4,
1304 current_attributes, lexer.Location);
1308 interface_property_declaration
1309 : PROPERTY identifier
1311 opt_formal_parameter_list
1312 CLOSE_PARENS opt_type_spec EOL
1314 // FIXME we MUST pass property parameters
1315 $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
1316 true, true, current_attributes,
1321 interface_event_declaration
1322 : opt_attributes opt_new EVENT type identifier EOL
1324 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1329 property_declaration
1330 : PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
1332 get_implicit_value_parameter_type = (Expression) $5;
1333 get_implicit_value_parameter_name = (string) $2;
1335 current_local_parameters = (Parameters) $3;
1336 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
1337 get_parameters = current_local_parameters.Copy (lexer.Location);
1338 set_parameters = current_local_parameters.Copy (lexer.Location);
1342 get_parameters = Parameters.EmptyReadOnlyParameters;
1343 set_parameters = new Parameters (null, null ,lexer.Location);
1345 lexer.PropertyParsing = true;
1347 $$ = lexer.Location;
1349 accessor_declarations
1352 lexer.PropertyParsing = false;
1355 Pair pair = (Pair) $9;
1356 Accessor get_block = (Accessor) pair.First;
1357 Accessor set_block = (Accessor) pair.Second;
1359 Location loc = lexer.Location;
1361 // Structure members are Public by default
1362 if ((current_container is Struct) && (current_modifiers == 0))
1363 current_modifiers = Modifiers.PUBLIC;
1365 prop = new Property ((Expression) $5, (string) $2, current_modifiers, get_block, set_block,
1366 current_attributes, loc, set_implicit_value_parameter_name,
1367 get_parameters, set_parameters, (Expression) $6);
1369 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1370 get_implicit_value_parameter_type = null;
1371 set_implicit_value_parameter_type = null;
1372 get_parameters = null;
1373 set_parameters = null;
1374 current_local_parameters = null;
1378 opt_property_parameters
1381 $$ = Parameters.EmptyReadOnlyParameters;
1383 | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1389 opt_implement_clause
1394 | IMPLEMENTS qualified_identifier
1396 $$ = DecomposeQI ((string)$2, lexer.Location);
1400 accessor_declarations
1401 : get_accessor_declaration opt_set_accessor_declaration
1403 $$ = new Pair ($1, $2);
1405 | set_accessor_declaration opt_get_accessor_declaration
1407 $$ = new Pair ($2, $1);
1411 opt_get_accessor_declaration
1412 : /* empty */ { $$ = null; }
1413 | get_accessor_declaration
1416 opt_set_accessor_declaration
1417 : /* empty */ { $$ = null; }
1418 | set_accessor_declaration
1421 get_accessor_declaration
1422 : opt_attributes GET EOL
1424 current_local_parameters = get_parameters;
1426 lexer.PropertyParsing = false;
1429 // Add local var declaration
1431 ArrayList retval = new ArrayList ();
1432 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
1433 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
1439 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1440 current_local_parameters = null;
1441 lexer.PropertyParsing = true;
1445 set_accessor_declaration
1446 : opt_attributes SET opt_set_parameter EOL
1448 Parameter implicit_value_parameter = new Parameter (
1449 set_implicit_value_parameter_type,
1450 set_implicit_value_parameter_name,
1451 Parameter.Modifier.NONE, null);
1453 current_local_parameters = set_parameters;
1454 current_local_parameters.AppendParameter (implicit_value_parameter);
1457 lexer.PropertyParsing = false;
1462 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
1463 current_local_parameters = null;
1464 lexer.PropertyParsing = true;
1471 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
1472 set_implicit_value_parameter_name = "Value";
1474 | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
1476 /* FIXME: possible syntax error which must be caught
1477 Set ( As <type>) is currently (and wrongly so) legal
1479 set_implicit_value_parameter_type = (Expression) $3;
1481 set_implicit_value_parameter_name = (string) $2;
1483 set_implicit_value_parameter_name = "Value";
1489 variable_declarators EOL
1491 int mod = (int) current_modifiers;
1494 VariableDeclaration.FixupTypes ((ArrayList) $2);
1495 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
1497 if (current_container is Module)
1498 mod = mod | Modifiers.STATIC;
1500 // Structure members are Public by default
1501 if ((current_container is Struct) && (mod == 0))
1502 mod = Modifiers.PUBLIC;
1504 foreach (VariableDeclaration var in (ArrayList) $2){
1505 Location l = var.Location;
1507 Field field = new Field (var.type, mod, var.identifier,
1508 var.expression_or_array_initializer,
1509 (Attributes) null, l);
1511 CheckDef (current_container.AddField (field), field.Name, l);
1516 withevents_declaration
1517 : WITHEVENTS variable_declarators EOL
1519 /* WithEvents Fields must be resolved into properties
1520 with a bit of magic behind the scenes */
1522 VariableDeclaration.FixupTypes ((ArrayList) $2);
1524 foreach (VariableDeclaration var in (ArrayList) $2) {
1525 // 1 - We create a private field
1526 Location l = var.Location;
1528 if ((current_modifiers & Modifiers.STATIC) > 0)
1529 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
1531 Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier,
1532 var.expression_or_array_initializer,
1533 (Attributes) null, l);
1535 CheckDef (current_container.AddField (field), field.Name, l);
1537 // 2 - Public property
1539 prop = BuildSimpleProperty (var.type, (string) var.identifier,
1540 field, (int) current_modifiers,
1541 (Attributes) current_attributes, l);
1543 CheckDef (current_container.AddProperty (prop), prop.Name, l);
1553 delegate_declaration
1555 identifier OPEN_PARENS
1556 opt_formal_parameter_list
1560 Location l = lexer.Location;
1561 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr,
1562 (int) current_modifiers,
1563 MakeName ((string) $3), (Parameters) $5,
1564 (Attributes) current_attributes, l);
1566 del.Namespace = current_namespace;
1567 CheckDef (current_container.AddDelegate (del), del.Name, l);
1570 identifier OPEN_PARENS
1571 opt_formal_parameter_list
1572 CLOSE_PARENS AS type
1574 Location l = lexer.Location;
1575 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
1577 (Expression) $8, (int) current_modifiers, MakeName ((string) $3),
1578 (Parameters) $5, (Attributes) current_attributes, l);
1580 del.Namespace = current_namespace;
1581 CheckDef (current_container.AddDelegate (del), del.Name, l);
1588 | HANDLES qualified_identifier
1590 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);
1596 | OPEN_PARENS CLOSE_PARENS
1599 static_constructor_declaration
1600 : SHARED SUB NEW opt_empty_parens EOL
1602 current_local_parameters = Parameters.EmptyReadOnlyParameters;
1604 oob_stack.Push (lexer.Location);
1606 Location l = (Location) oob_stack.Pop ();
1607 $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
1611 Constructor c = (Constructor) $1;
1612 c.Block = (Block) end_block();
1613 c.ModFlags = (int) current_modifiers;
1614 c.OptAttributes = current_attributes;
1616 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1617 current_local_parameters = null;
1621 constructor_declaration
1622 : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
1624 current_local_parameters = (Parameters) $4;
1626 oob_stack.Push (lexer.Location);
1628 Location l = (Location) oob_stack.Pop ();
1629 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
1633 Constructor c = (Constructor) $1;
1634 c.Block = (Block) end_block();
1635 c.ModFlags = (int) current_modifiers;
1636 c.OptAttributes = current_attributes;
1638 CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
1639 current_local_parameters = null;
1644 opt_formal_parameter_list
1647 $$ = Parameters.EmptyReadOnlyParameters;
1649 | formal_parameter_list
1652 //Parameter p = ((Parameters) $1).FixedParameters[0];
1656 formal_parameter_list
1659 ArrayList pars_list = (ArrayList) $1;
1661 Parameter [] pars = new Parameter [pars_list.Count];
1662 pars_list.CopyTo (pars);
1663 $$ = new Parameters (pars, null, lexer.Location);
1665 | fixed_parameters COMMA parameter_array
1667 ArrayList pars_list = (ArrayList) $1;
1669 Parameter [] pars = new Parameter [pars_list.Count];
1670 pars_list.CopyTo (pars);
1672 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
1676 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1683 ArrayList pars = new ArrayList ();
1688 | fixed_parameters COMMA fixed_parameter
1690 ArrayList pars = (ArrayList) $1;
1699 opt_parameter_modifier
1700 identifier opt_type_spec opt_variable_initializer
1702 Parameter.Modifier pm = (Parameter.Modifier)$2;
1703 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1705 if (opt_parm && ($5 == null))
1706 Report.Error (999, "Optional parameters must have a default value");
1709 if ((pm & Parameter.Modifier.REF) !=0)
1710 pm = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
1712 pm = Parameter.Modifier.NONE; //FIXME: should take into account BYREF
1714 $$ = new Parameter ((Expression) $4, (string) $3,
1715 pm, (Attributes) $1, (Expression) $5, opt_parm);
1720 : PARAM_ARRAY identifier opt_parens AS type
1722 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1723 // note ("type must be a single-dimension array type");
1729 | OPEN_PARENS CLOSE_PARENS
1732 opt_parameter_modifier
1733 : /* empty */ { $$ = Parameter.Modifier.VAL; }
1734 | parameter_modifiers { $$ = $1; }
1738 : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1739 | parameter_modifier { $$ = $1; }
1743 : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1744 | BYVAL { $$ = Parameter.Modifier.VAL; }
1745 | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; }
1750 | statement_list EOL
1755 | statement_list EOL statement
1759 declaration_statement
1761 if ($1 != null && (Block) $1 != current_block){
1762 current_block.AddStatement ((Statement) $1);
1763 current_block = (Block) $1;
1766 | embedded_statement
1768 Statement s = (Statement) $1;
1770 current_block.AddStatement ((Statement) $1);
1773 | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1775 AddHandler ((Expression) $2, (string) $5);
1777 | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1779 RaiseEvent ((string) $2, (ArrayList) $4);
1786 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1788 if (!current_block.AddLabel ((string) $1, labeled)){
1789 Location l = lexer.Location;
1790 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1792 current_block.AddStatement (labeled);
1798 : expression_statement
1799 | selection_statement
1800 | iteration_statement
1807 | continue_statement
1810 | */return_statement
1817 $$ = new Exit ((ExitType)$2, lexer.Location);
1822 : DO { $$ = ExitType.DO; }
1823 | FOR { $$ = ExitType.FOR; }
1824 | WHILE { $$ = ExitType.WHILE; }
1825 | SELECT { $$ = ExitType.SELECT; }
1826 | SUB { $$ = ExitType.SUB; }
1827 | FUNCTION { $$ = ExitType.FUNCTION; }
1828 | PROPERTY { $$ = ExitType.PROPERTY; }
1829 | TRY { $$ = ExitType.TRY; }
1832 : RETURN opt_expression
1834 $$ = new Return ((Expression) $2, lexer.Location);
1842 /*| foreach_statement*/
1855 ArrayList s = new ArrayList ();
1857 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
1864 // Now s contains the list of specific catch clauses
1865 // and g contains the general one.
1866 Block b = end_block();
1868 $$ = new Try ((Block) b, s, g, null, lexer.Location);
1875 tmp_block = end_block();
1885 ArrayList s = new ArrayList ();
1886 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
1888 if (catch_list != null){
1889 foreach (Catch cc in catch_list) {
1897 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
1910 tmp_catch_clauses = (ArrayList) $5;
1915 : /* empty */ { $$ = null; }
1922 ArrayList l = new ArrayList ();
1927 | catch_clauses catch_clause
1929 ArrayList l = (ArrayList) $1;
1937 : /* empty */ { $$ = null; }
1942 : CATCH opt_catch_args EOL
1944 Expression type = null;
1948 DictionaryEntry cc = (DictionaryEntry) $2;
1949 type = (Expression) cc.Key;
1950 id = (string) cc.Value;
1953 ArrayList one = new ArrayList ();
1954 Location loc = lexer.Location;
1956 one.Add (new VariableDeclaration (id, null, loc));
1960 current_block = new Block (current_block);
1961 Block b = declare_local_variables (type, one, loc);
1967 opt_statement_list {
1968 Expression type = null;
1970 Block b_catch = current_block;
1973 DictionaryEntry cc = (DictionaryEntry) $2;
1974 type = (Expression) cc.Key;
1975 id = (string) cc.Value;
1979 // FIXME: I can change this for an assignment.
1981 while (current_block != (Block) $1)
1982 current_block = current_block.Parent;
1986 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
1991 : /* empty */ { $$ = null; }
1996 : identifier AS type
1998 $$ = new DictionaryEntry ($3, $1);
2004 : DO opt_do_construct EOL
2007 oob_stack.Push (lexer.Location);
2010 LOOP opt_do_construct
2012 Expression t_before = (Expression) $2;
2013 Expression t_after = (Expression) $7;
2016 if ((t_before != null) && (t_after != null))
2017 Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
2019 if ((t_before == null) && (t_after == null))
2020 t = new BoolLiteral (true);
2022 t = (t_before != null) ? t_before : t_after;
2024 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
2026 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
2027 ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
2028 t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
2030 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
2035 : /* empty */ { $$ = null; }
2036 | while_or_until boolean_expression
2038 do_type = (DoOptions)$1;
2039 $$ = (Expression) $2;
2044 : WHILE { $$ = DoOptions.WHILE; }
2045 | UNTIL { $$ = DoOptions.UNTIL; }
2052 oob_stack.Push (lexer.Location);
2054 boolean_expression EOL
2058 Location l = (Location) oob_stack.Pop ();
2059 Block b = end_block();
2060 Expression e = (Expression) $3;
2061 $$ = new While ((Expression) e, (Statement) b, l);
2067 : FOR qualified_identifier ASSIGN expression TO expression opt_step EOL
2072 NEXT opt_next_identifier
2074 Block statement = end_block();
2075 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
2077 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
2078 Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual,
2079 for_var, (Expression) $6, lexer.Location);
2080 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
2081 for_var, (Expression) $7, lexer.Location), lexer.Location);
2083 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);
2084 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
2086 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);
2091 : /* empty */ { $$ = new IntLiteral ((Int32) 1); }
2092 | STEP expression { $$ = $2; }
2097 | qualified_identifier
2106 : if_statement_open if_statement_rest
2113 : IF boolean_expression THEN EOL
2115 oob_stack.Push (lexer.Location);
2117 tmp_expr = (Expression) $2;
2126 Location l = (Location) oob_stack.Pop ();
2128 $$ = new If ((Expression) tmp_expr, (Statement) end_block(), l);
2135 tmp_block = end_block();
2141 Location l = (Location) oob_stack.Pop ();
2143 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
2148 : SELECT opt_case expression EOL
2150 oob_stack.Push (lexer.Location);
2151 switch_stack.Push (current_block);
2156 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
2157 current_block = (Block) switch_stack.Pop ();
2162 : /* empty */ { $$ = null; }
2163 | case_sections { $$ = $1; }
2167 : case_sections case_section
2169 ArrayList sections = (ArrayList) $1;
2176 ArrayList sections = new ArrayList ();
2184 : CASE case_clauses EOL
2190 Block topmost = current_block;
2192 while (topmost.Implicit)
2193 topmost = topmost.Parent;
2195 // FIXME: This is a horrible hack which MUST go
2196 topmost.statements.Add (new Break (lexer.Location));
2197 $$ = new SwitchSection ((ArrayList) $2, topmost);
2200 /* FIXME: we should somehow flag an error
2201 (BC30321 'Case' cannot follow a 'Case Else'
2202 in the same 'Select' statement.)
2203 if Case Else is not the last of the Case clauses
2210 Block topmost = current_block;
2212 while (topmost.Implicit)
2213 topmost = topmost.Parent;
2215 // FIXME: This is a horrible hack which MUST go
2216 topmost.statements.Add (new Break (lexer.Location));
2218 ArrayList a = new ArrayList();
2219 a.Add (new SwitchLabel (null, lexer.Location));
2220 $$ = new SwitchSection ((ArrayList) a, topmost);
2227 ArrayList labels = new ArrayList ();
2232 | case_clauses COMMA case_clause
2234 ArrayList labels = (ArrayList) ($1);
2242 : opt_is comparison_operator expression
2245 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
2267 expression_statement
2268 : statement_expression
2274 statement_expression
2275 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2276 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2277 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2280 object_creation_expression
2281 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2283 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2288 : object_creation_expression
2289 /* | array_creation_expression */
2292 declaration_statement
2293 : local_variable_declaration
2296 DictionaryEntry de = (DictionaryEntry) $1;
2298 $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
2302 | local_constant_declaration
2305 DictionaryEntry de = (DictionaryEntry) $1;
2307 $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
2312 local_variable_declaration
2313 : DIM variable_declarators
2315 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);
2317 /*| DIM variable_declarators
2319 $$ = new DictionaryEntry (TypeManager.system_object_expr, $2);
2321 | DIM variable_declarators AS object_creation_expression
2324 $$ = new DictionaryEntry ($4, $2);
2332 local_constant_declaration
2333 : CONST constant_declarator
2336 $$ = new DictionaryEntry ($1, $2);
2343 : identifier ASSIGN constant_expression
2345 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
2349 variable_declarators
2350 : variable_declarator
2352 ArrayList decl = new ArrayList ();
2356 | variable_declarators COMMA variable_declarator
2358 ArrayList decls = (ArrayList) $1;
2365 : variable_identifier opt_type_decl opt_variable_initializer
2367 string varname = (string)$1;
2369 object varinit = $3;
2370 Expression vartype = (Expression) $2;
2373 Check for a declaration like Dim a(2) or Dim a(2,3)
2374 If this is the case, we must generate an ArrayCreationExpression
2375 and, in case, add the initializer after the array has been created.
2377 if (VariableDeclaration.IsArrayDecl (varname)) {
2378 if (VariableDeclaration.DimsSpecified(varname)) {
2379 varname = VariableDeclaration.StripDims (varname, ref dims);
2380 ArrayList a_dims = VariableDeclaration.ParseDimList(dims);
2381 varinit = new ArrayCreation (vartype, a_dims,"", (ArrayList) varinit, lexer.Location);
2383 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.GetRank (dims), lexer.Location);
2386 if (vartype is New) {
2387 if (varinit != null) {
2388 Report.Error (30205, lexer.Location, "End of statement expected");
2394 vartype = ((New)vartype).RequestedType;
2397 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
2402 : identifier opt_array_name_modifier
2406 $$ = (string)$$ + (string)$2;
2411 : /* empty */ { $$ = null; }
2412 | AS type { $$ = (Expression) $2; };
2420 | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS
2422 Report.Error (30638, "Array bounds cannot appear in type specifiers");
2427 New n = new New ((Expression)$3, null, lexer.Location);
2428 $$ = (Expression) n;
2430 | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2432 New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
2433 $$ = (Expression) n;
2437 opt_array_name_modifier
2438 : /* empty */ { $$ = null; }
2439 | array_type_modifier { $$ = $1; }
2443 : rank_specifiers { $$ = $1; }
2446 opt_variable_initializer
2447 : /* empty */ { $$ = null; }
2448 | ASSIGN variable_initializer { $$ = $2; }
2451 variable_initializer
2464 : OPEN_BRACE CLOSE_BRACE
2466 ArrayList list = new ArrayList ();
2469 | OPEN_BRACE variable_initializer_list CLOSE_BRACE
2471 $$ = (ArrayList) $2;
2475 variable_initializer_list
2476 : variable_initializer
2478 ArrayList list = new ArrayList ();
2482 | variable_initializer_list COMMA variable_initializer
2484 ArrayList list = (ArrayList) $1;
2491 * The following is from Rhys' grammar:
2492 * > Types in local variable declarations must be recognized as
2493 * > expressions to prevent reduce/reduce errors in the grammar.
2494 * > The expressions are converted into types during semantic analysis.
2497 : primary_expression opt_rank_specifier
2499 // FIXME: Do something smart here regarding the composition of the type.
2501 // Ok, the above "primary_expression" is there to get rid of
2502 // both reduce/reduce and shift/reduces in the grammar, it should
2503 // really just be "type_name". If you use type_name, a reduce/reduce
2504 // creeps up. If you use qualified_identifier (which is all we need
2505 // really) two shift/reduces appear.
2508 // So the super-trick is that primary_expression
2509 // can only be either a SimpleName or a MemberAccess.
2510 // The MemberAccess case arises when you have a fully qualified type-name like :
2512 // SimpleName is when you have
2515 Expression expr = (Expression) $1;
2516 if (!(expr is SimpleName || expr is MemberAccess)) {
2517 Error_ExpectingTypeName (lexer.Location, expr);
2521 // So we extract the string corresponding to the SimpleName
2524 if ((string) $2 == "")
2527 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2530 | builtin_types opt_rank_specifier
2532 if ((string) $2 == "")
2535 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2544 | rank_specifiers rank_specifier
2546 $$ = (string) $2 + (string) $1;
2551 : OPEN_PARENS opt_dim_separators CLOSE_PARENS
2553 $$ = "[" + (string) $2 + "]";
2588 | dim_separators COMMA
2590 $$ = (string) $1 + ",";
2595 : integer_literal { $$ = ((IntLiteral)$1).AsString(); }
2596 | dim_specifiers COMMA integer_literal { $$ = $1 + "," + ((IntLiteral)$3).AsString(); }
2606 | qualified_identifier
2608 string name = (string) $1;
2610 $$ = DecomposeQI (name, lexer.Location);
2612 | parenthesized_expression
2614 | invocation_expression
2625 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
2626 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
2627 | NOTHING { $$ = NullLiteral.Null; }
2631 : LITERAL_SINGLE { $$ = new FloatLiteral ((float) lexer.Value); }
2632 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
2633 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
2638 object v = lexer.Value;
2641 $$ = new IntLiteral ((Int32) v);
2643 $$ = new UIntLiteral ((UInt32) v);
2645 $$ = new LongLiteral ((Int64) v);
2646 else if (v is ulong)
2647 $$ = new ULongLiteral ((UInt64) v);
2649 Console.WriteLine ("OOPS. Unexpected result from scanner");
2655 : TRUE { $$ = new BoolLiteral (true); }
2656 | FALSE { $$ = new BoolLiteral (false); }
2659 parenthesized_expression
2660 : OPEN_PARENS expression CLOSE_PARENS
2665 : primary_expression DOT identifier
2667 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2669 | predefined_type DOT identifier
2671 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2679 invocation_expression
2680 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2683 Location l = lexer.Location;
2684 Report.Error (1, l, "THIS IS CRAZY");
2686 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2688 | MYBASE DOT identifier OPEN_PARENS opt_expression_list CLOSE_PARENS
2690 BaseAccess ba = new BaseAccess ((string) $3, lexer.Location);
2691 $$ = new Invocation ((Expression) ba, (ArrayList) $5, lexer.Location);
2693 | MYBASE DOT NEW OPEN_PARENS opt_expression_list CLOSE_PARENS
2695 BaseAccess ba = new BaseAccess ("New", lexer.Location);
2696 $$ = new Invocation ((Expression) ba, (ArrayList) $5, lexer.Location);
2704 The 'argument' rule returns an 'empty' argument
2705 of type NoArg (used for default arguments in invocations)
2706 if no arguments are actually passed.
2708 If there is only one argument and it is o type NoArg,
2709 we return a null (empty) list
2711 ArrayList args = (ArrayList) $1;
2712 if (args.Count == 1 &&
2713 ((Argument)args[0]).ArgType == Argument.AType.NoArg)
2723 ArrayList list = new ArrayList ();
2727 | argument_list COMMA argument
2729 ArrayList list = (ArrayList) $1;
2738 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2740 | BYREF variable_reference
2742 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2746 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
2751 : expression {/* note ("section 5.4"); */ $$ = $1; }
2755 : primary_expression OPEN_PARENS expression_list CLOSE_PARENS
2758 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2760 /* | primary_expression rank_specifiers
2762 // So the super-trick is that primary_expression
2763 // can only be either a SimpleName or a MemberAccess.
2764 // The MemberAccess case arises when you have a fully qualified type-name like :
2766 // SimpleName is when you have
2768 Expression expr = (Expression) $1;
2770 if (!(expr is SimpleName || expr is MemberAccess)) {
2771 Error_ExpectingTypeName (lexer.Location, expr);
2772 $$ = TypeManager.system_object_expr;
2775 // So we extract the string corresponding to the SimpleName
2778 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2784 : conditional_expression { $$ = $1; }
2785 /*| assignment_expression*/
2796 ArrayList list = new ArrayList ();
2800 | expression_list COMMA expression
2802 ArrayList list = (ArrayList) $1;
2809 : /*empty */ { $$ = null; }
2816 $$ = new This (current_block, lexer.Location);
2821 : primary_expression
2822 | NOT prefixed_unary_expression
2824 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2830 : cast_operator OPEN_PARENS expression CLOSE_PARENS
2832 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2834 | CTYPE OPEN_PARENS expression COMMA expression CLOSE_PARENS
2836 $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
2841 : CBOOL { $$ = TypeManager.system_boolean_expr; }
2842 | CBYTE { $$ = TypeManager.system_byte_expr; }
2843 | CCHAR { $$ = TypeManager.system_char_expr; }
2844 | CDATE { $$ = TypeManager.system_decimal_expr; } //FIXME
2845 | CDBL { $$ = TypeManager.system_double_expr; }
2846 | CDEC { $$ = TypeManager.system_decimal_expr; }
2847 | CINT { $$ = TypeManager.system_int32_expr; }
2848 | CLNG { $$ = TypeManager.system_int64_expr; }
2849 | COBJ { $$ = TypeManager.system_object_expr; }
2850 | CSHORT { $$ = TypeManager.system_int16_expr; }
2851 | CSNG { $$ = TypeManager.system_single_expr; }
2852 | CSTR { $$ = TypeManager.system_string_expr; }
2856 // The idea to split this out is from Rhys' grammar
2857 // to solve the problem with casts.
2859 prefixed_unary_expression
2861 | PLUS prefixed_unary_expression
2863 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2865 | MINUS prefixed_unary_expression
2867 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2869 | ADDRESSOF prefixed_unary_expression
2871 // FIXME: We should generate an error if AddressOf is NOT used
2872 // during delegate creation
2877 multiplicative_expression
2878 : prefixed_unary_expression
2879 | multiplicative_expression STAR prefixed_unary_expression
2881 $$ = new Binary (Binary.Operator.Multiply,
2882 (Expression) $1, (Expression) $3, lexer.Location);
2884 | multiplicative_expression DIV prefixed_unary_expression
2886 $$ = new Binary (Binary.Operator.Division,
2887 (Expression) $1, (Expression) $3, lexer.Location);
2889 | multiplicative_expression OP_MODULUS prefixed_unary_expression
2891 $$ = new Binary (Binary.Operator.Modulus,
2892 (Expression) $1, (Expression) $3, lexer.Location);
2897 : multiplicative_expression
2898 | additive_expression PLUS multiplicative_expression
2900 $$ = new Binary (Binary.Operator.Addition,
2901 (Expression) $1, (Expression) $3, lexer.Location);
2903 | additive_expression MINUS multiplicative_expression
2905 $$ = new Binary (Binary.Operator.Subtraction,
2906 (Expression) $1, (Expression) $3, lexer.Location);
2908 | additive_expression OP_CONCAT multiplicative_expression
2910 // FIXME: This should only work for String expressions
2911 // We probably need to use something from the runtime
2912 $$ = new Binary (Binary.Operator.Addition,
2913 (Expression) $1, (Expression) $3, lexer.Location);
2917 relational_expression
2918 : additive_expression
2919 | relational_expression OP_LT additive_expression
2921 $$ = new Binary (Binary.Operator.LessThan,
2922 (Expression) $1, (Expression) $3, lexer.Location);
2924 | relational_expression OP_GT additive_expression
2926 $$ = new Binary (Binary.Operator.GreaterThan,
2927 (Expression) $1, (Expression) $3, lexer.Location);
2929 | relational_expression OP_LE additive_expression
2931 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2932 (Expression) $1, (Expression) $3, lexer.Location);
2934 | relational_expression OP_GE additive_expression
2936 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2937 (Expression) $1, (Expression) $3, lexer.Location);
2939 | relational_expression IS type_name
2941 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2943 | relational_expression AS type_name
2945 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2950 : relational_expression
2951 | equality_expression ASSIGN relational_expression
2953 $$ = new Binary (Binary.Operator.Equality,
2954 (Expression) $1, (Expression) $3, lexer.Location);
2959 : equality_expression
2960 | and_expression OP_AND equality_expression
2962 $$ = new Binary (Binary.Operator.BitwiseAnd,
2963 (Expression) $1, (Expression) $3, lexer.Location);
2967 exclusive_or_expression
2969 | exclusive_or_expression OP_XOR and_expression
2971 $$ = new Binary (Binary.Operator.ExclusiveOr,
2972 (Expression) $1, (Expression) $3, lexer.Location);
2976 conditional_and_expression
2977 : exclusive_or_expression
2978 | conditional_and_expression OP_AND exclusive_or_expression
2980 $$ = new Binary (Binary.Operator.LogicalAnd,
2981 (Expression) $1, (Expression) $3, lexer.Location);
2985 conditional_or_expression
2986 : conditional_and_expression
2987 | conditional_or_expression OP_OR conditional_and_expression
2989 $$ = new Binary (Binary.Operator.LogicalOr,
2990 (Expression) $1, (Expression) $3, lexer.Location);
2994 conditional_expression
2995 : conditional_or_expression
2998 assignment_expression
2999 : prefixed_unary_expression ASSIGN expression
3001 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
3014 : type_name { /* class_type */
3016 This does interfaces, delegates, struct_types, class_types,
3017 parent classes, and more! 4.2
3019 $$ = DecomposeQI ((string) $1, lexer.Location);
3029 ArrayList types = new ArrayList ();
3034 | type_list COMMA type
3036 ArrayList types = (ArrayList) $1;
3044 : namespace_or_type_name
3047 namespace_or_type_name
3048 : qualified_identifier
3052 : type bracketed_rank_specifiers
3054 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3058 bracketed_rank_specifiers
3059 : bracketed_rank_specifier bracketed_opt_rank_specifier
3061 $$ = (string) $2 + (string) $1;
3065 bracketed_rank_specifier
3066 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
3068 $$ = "[" + (string) $2 + "]";
3072 bracketed_opt_rank_specifier
3077 | bracketed_rank_specifiers
3083 /* Built-in / Integral types */
3085 : OBJECT { $$ = TypeManager.system_object_expr; }
3086 | STRING { $$ = TypeManager.system_string_expr; }
3087 | BOOLEAN { $$ = TypeManager.system_boolean_expr; }
3088 | DECIMAL { $$ = TypeManager.system_decimal_expr; }
3089 | SINGLE { $$ = TypeManager.system_single_expr; }
3090 | DOUBLE { $$ = TypeManager.system_double_expr; }
3095 : /*SBYTE { $$ = TypeManager.system_sbyte_expr; }
3096 | BYTE { $$ = TypeManager.system_byte_expr; }
3097 | SHORT { $$ = TypeManager.system_int16_expr; }
3098 | USHORT { $$ = TypeManager.system_uint16_expr; }
3099 | */ INTEGER { $$ = TypeManager.system_int32_expr; }/*
3100 | UINT { $$ = TypeManager.system_uint32_expr; }
3101 | LONG { $$ = TypeManager.system_int64_expr; }
3102 | ULONG { $$ = TypeManager.system_uint64_expr; }
3103 | CHAR { $$ = TypeManager.system_char_expr; }
3104 | VOID { $$ = TypeManager.system_void_expr; }*/
3115 public Tokenizer Lexer {
3121 public static Expression DecomposeQI (string name, Location loc)
3125 if (name.IndexOf ('.') == -1){
3126 return new SimpleName (name, loc);
3128 int pos = name.LastIndexOf (".");
3129 string left = name.Substring (0, pos);
3130 string right = name.Substring (pos + 1);
3132 o = DecomposeQI (left, loc);
3134 return new MemberAccess (o, right, loc);
3138 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
3140 Block implicit_block;
3141 ArrayList inits = null;
3144 // We use the `Used' property to check whether statements
3145 // have been added to the current block. If so, we need
3146 // to create another block to contain the new declaration
3147 // otherwise, as an optimization, we use the same block to
3148 // add the declaration.
3150 // FIXME: A further optimization is to check if the statements
3151 // that were added were added as part of the initialization
3152 // below. In which case, no other statements have been executed
3153 // and we might be able to reduce the number of blocks for
3154 // situations like this:
3156 // int j = 1; int k = j + 1;
3159 VariableDeclaration.FixupTypes (variable_declarators);
3161 if (current_block.Used) {
3162 implicit_block = new Block (current_block, true, loc, Location.Null);
3163 implicit_block.AddChildVariableNames (current_block);
3165 implicit_block = current_block;
3167 foreach (VariableDeclaration decl in variable_declarators){
3168 Expression type = decl.type;
3169 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3170 if (decl.expression_or_array_initializer != null){
3172 inits = new ArrayList ();
3179 return implicit_block;
3181 foreach (VariableDeclaration decl in inits){
3184 Expression type = decl.type;
3186 if ((decl.expression_or_array_initializer is Expression) ||
3187 (decl.expression_or_array_initializer is New)) {
3188 expr = (Expression) decl.expression_or_array_initializer;
3190 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3192 expr = new ArrayCreation (type, "", init, decl.Location);
3195 LocalVariableReference var;
3196 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3198 assign = new Assign (var, expr, decl.Location);
3200 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3203 return implicit_block;
3207 Block declare_local_constant (Expression type, VariableDeclaration decl)
3209 Block implicit_block;
3211 if (current_block.Used)
3212 implicit_block = new Block (current_block, true);
3214 implicit_block = current_block;
3216 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3217 current_local_parameters, decl.Location))){
3220 return implicit_block;
3224 // A class used to pass around variable declarations and constants
3226 public class VariableDeclaration {
3227 public string identifier;
3228 public object expression_or_array_initializer;
3229 public Location Location;
3230 public Attributes OptAttributes;
3231 public Expression type;
3232 public ArrayList dims;
3234 public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
3236 this.identifier = id;
3237 this.expression_or_array_initializer = eoai;
3239 this.OptAttributes = opt_attrs;
3244 public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3248 public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
3252 public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this
3253 (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
3257 public static void FixupTypes (ArrayList vars)
3259 int varcount = vars.Count;
3260 VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
3262 if (last_var.type == null)
3263 last_var.type = TypeManager.system_object_expr;
3265 Expression cur_type = last_var.type;
3266 int n = varcount - 1;
3269 VariableDeclaration var = (VariableDeclaration) vars[n--];
3270 if (var.type == null)
3271 var.type = cur_type;
3273 cur_type = var.type;
3277 public static bool DimsSpecified (string varname)
3281 if (varname.IndexOf("[") >= 0) {
3282 char[] ds = {'1','2','3','4','5','6','7','8','9'};
3284 string dimpart = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3285 if (dimpart.IndexOfAny (ds) >= 0)
3291 public static string StripDims (string varname, ref string d)
3293 string res = varname;
3296 if (varname.IndexOf("[") >= 0) {
3297 dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
3298 res = varname.Substring(0, varname.IndexOf("["));
3304 public static string StripDims (string varname)
3308 return (StripDims(varname, ref dres));
3311 public static string GetRank (string dims)
3316 for (x = 0; x < dims.Length; x++) {
3317 if (dims[x] == '[' || dims[x] == ']' || dims[x] == ',')
3318 res = res + dims[x];
3323 public static ArrayList ParseDimList (string dims)
3325 ArrayList res = new ArrayList();
3326 string d = dims.Substring (1, dims.Length -2);
3327 Array a = d.Split (',');
3329 if (a.GetLength(0) > 32) {
3330 Report.Error (999, "Arrays cannot have more than 32 dimensions");
3333 foreach (string s in a)
3335 res.Add (new IntLiteral ((Int32) Convert.ToInt32(s)));
3337 res.Add (new IntLiteral ((Int32) 0));
3342 public static bool IsArrayDecl (string varname)
3344 return (varname.IndexOf("[") >= 0);
3347 public static void FixupArrayTypes (ArrayList vars)
3349 int varcount = vars.Count;
3352 foreach (VariableDeclaration var in vars) {
3353 if (var.identifier.EndsWith(",")) {
3354 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","),
3355 var.identifier.LastIndexOf(",")) + "]";
3356 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
3357 var.type = new ComposedCast (var.type, (string) dims, var.Location);
3363 public Property BuildSimpleProperty (Expression p_type, string name,
3364 Field p_fld, int mod_flags,
3365 Attributes attrs, Location loc)
3368 Block get_block, set_block;
3369 Accessor acc_set, acc_get;
3370 StatementExpression a_set;
3375 Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
3376 args = new Parameter [1];
3377 args [0] = implicit_value_parameter;
3379 Parameters set_params = new Parameters (args, null, loc);
3380 a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
3381 (Expression) new SimpleName("value", loc), loc), loc);
3383 set_block = new Block (current_block, set_params, loc, Location.Null);
3384 set_block.AddStatement ((Statement) a_set);
3385 acc_set = new Accessor (set_block, attrs);
3388 a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
3389 get_block = new Block (current_block, null, loc, Location.Null);
3390 get_block.AddStatement ((Statement) a_get);
3391 acc_get = new Accessor (get_block, attrs);
3393 p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
3400 current_block = new Block (current_block, current_local_parameters,
3401 lexer.Location, Location.Null);
3408 while (current_block.Implicit)
3409 current_block = current_block.Parent;
3411 res = current_block;
3413 current_block.SetEndLocation (lexer.Location);
3414 current_block = current_block.Parent;
3419 private void AddHandler (Expression evt_definition, string handler_name)
3421 AddHandler (current_block, evt_definition, handler_name);
3424 void CheckAttributeTarget (string a)
3428 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3432 Location l = lexer.Location;
3433 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3438 private void AddHandler (Block b, Expression evt_id, string handler_name)
3440 Location loc = lexer.Location;
3441 string evt_target = evt_id.ToString();
3442 evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
3443 Statement s = (Statement) new AddHandler (evt_id, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
3447 private void RaiseEvent (string evt_name, ArrayList args)
3449 Location loc = lexer.Location;
3451 Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
3452 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc));
3453 current_block.AddStatement (s);
3456 // FIXME: THIS DOES NOT WORK!!!
3457 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
3459 Location loc = lexer.Location;
3460 ArrayList neh_args = new ArrayList();
3461 neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
3463 ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
3465 CompoundAssign ca = new CompoundAssign (
3466 Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
3468 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc));
3473 // This method is used to get at the complete string representation of
3474 // a fully-qualified type name, hiding inside a MemberAccess ;-)
3475 // This is necessary because local_variable_type admits primary_expression
3476 // as the type of the variable. So we do some extra checking
3478 string GetQualifiedIdentifier (Expression expr)
3480 if (expr is SimpleName)
3481 return ((SimpleName)expr).Name;
3482 else if (expr is MemberAccess)
3483 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3485 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3489 private void RemoveHandler (Expression evt_definition, string handler_name)
3491 RemoveHandler (current_block, evt_definition, handler_name);
3496 void Error_ExpectingTypeName (Location l, Expression expr)
3498 if (expr is Invocation){
3499 Report.Error (1002, l, "; expected");
3501 Report.Error (-1, l, "Invalid Type definition");
3505 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
3509 public override int parse ()
3511 current_namespace = new Namespace (null, RootContext.RootNamespace);
3512 current_container = RootContext.Tree.Types;
3513 current_container.Namespace = current_namespace;
3514 oob_stack = new Stack ();
3515 switch_stack = new Stack ();
3517 UseExtendedSyntax = name.EndsWith(".mbs");
3518 OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
3519 OptionStrict = InitialOptionStrict || UseExtendedSyntax;
3520 OptionCompareBinary = InitialOptionCompareBinary;
3522 lexer = new Tokenizer (input, name, defines);
3523 StringBuilder value = new StringBuilder ();
3524 //yacc_verbose_flag=true;
3527 if (yacc_verbose_flag)
3528 yyparse (lexer, new yydebug.yyDebugSimple ());
3534 Console.WriteLine (lexer.location + " : Parsing error in " + lexer.ref_name);
3535 Report.Error (9999, lexer.Location, "");
3536 Console.WriteLine (e);
3539 return Report.Errors;