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 bool UseExtendedSyntax; // for ".mbs" files
124 public override string[] extensions()
126 string [] list = { ".vb", ".mbs" };
133 %token NONE /* This token is never returned by our lexer */
134 %token ERROR // This is used not by the parser, but by the tokenizer.
138 *These are the MonoBASIC keywords
178 %token DESCRIPTION // MonoBASIC extension
227 %token NOTINHERITABLE
228 %token NOTOVERRIDABLE
238 %token PARAMETER // MonoBASIC extension
265 %token SUMMARY // MonoBASIC extension
283 /* MonoBASIC single character operators/punctuation. */
284 %token OPEN_BRACKET "["
285 %token CLOSE_BRACKET "]"
286 %token OPEN_PARENS "("
287 %token CLOSE_PARENS ")"
305 /* MonoBASIC multi-character operators. */
310 %token OP_AND //"and"
312 %token OP_XOR //"xor"
313 %token OP_MODULUS //"mod"
314 %token OP_MULT_ASSIGN "*="
315 %token OP_DIV_ASSIGN "/="
316 %token OP_IDIV_ASSIGN "\\="
317 %token OP_ADD_ASSIGN "+="
318 %token OP_SUB_ASSIGN "-="
319 %token OP_CONCAT_ASSIGN "&="
320 %token OP_EXP_ASSIGN "^="
323 %token LITERAL_INTEGER "int literal"
324 %token LITERAL_SINGLE "float literal"
325 %token LITERAL_DOUBLE "double literal"
326 %token LITERAL_DECIMAL "decimal literal"
327 %token LITERAL_CHARACTER "character literal"
328 %token LITERAL_STRING "string literal"
332 /* Add precedence rules to solve dangling else s/r conflict */
341 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
343 %left STAR DIV PERCENT
344 %right BITWISE_NOT CARRET UMINUS
345 %nonassoc OP_INC OP_DEC
347 %left OPEN_BRACKET OPEN_BRACE
351 %start compilation_unit
355 : opt_imports_directives
371 | declarations declaration
375 : namespace_declaration
382 Class c = (Class) $1;
383 mod_flags = c.ModFlags;
385 } else if ($1 is Struct){
386 Struct s = (Struct) $1;
387 mod_flags = s.ModFlags;
389 } else if ($1 is Module){
390 Module m = (Module) $1;
391 mod_flags = m.ModFlags;
396 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
398 1527, lexer.Location,
399 "Namespace elements cannot be explicitly " +
400 "declared private or protected in '" + name + "'");
407 | qualified_identifier DOT IDENTIFIER
409 $$ = (($1).ToString ()) + "." + ($3.ToString ());
412 opt_imports_directives
419 | imports_directives imports_directive
423 : /* imports_alias_directive
424 | */ imports_namespace_directive
427 imports_namespace_directive
428 : IMPORTS qualified_identifier EOL
430 current_namespace.Using ((string) $2, lexer.Location);
436 | OP_LT attribute_list OP_GT
441 | attribute_list COMMA attribute
448 namespace_declaration
449 : NAMESPACE qualified_identifier EOL
451 current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$2);
453 opt_imports_directives
457 current_namespace = current_namespace.Parent;
465 current_attributes = (Attributes) $1;
466 current_modifiers = (int) $2;
468 type_spec_declaration
471 type_spec_declaration
474 // | struct_declaration
475 // | interface_declaration
476 // | enum_declaration
477 | delegate_declaration
481 : CLASS IDENTIFIER EOL opt_class_base
486 name = MakeName ((string) $2);
488 new_class = new Class (current_container, name, current_modifiers,
489 (Attributes) current_attributes, lexer.Location);
491 current_container = new_class;
492 current_container.Namespace = current_namespace;
493 RootContext.Tree.RecordDecl (name, new_class);
495 opt_class_member_declarations
498 Class new_class = (Class) current_container;
499 new_class.Bases = (ArrayList) $4;
501 current_container = current_container.Parent;
502 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
509 : /* empty */ { $$ = null; }
510 | class_base { $$ = $1; }
514 : INHERITS type_list EOL { $$ = $2; }
518 : /* empty */ { $$ = (int) 0; current_modifiers = 0; }
519 | modifiers { $$ = $1; current_modifiers = (int) $1; }
529 if ((m1 & m2) != 0) {
530 Location l = lexer.Location;
531 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
533 $$ = (int) (m1 | m2);
538 : PUBLIC { $$ = Modifiers.PUBLIC; }
539 | PROTECTED { $$ = Modifiers.PROTECTED; }
540 | PRIVATE { $$ = Modifiers.PRIVATE; }
541 | STATIC { $$ = Modifiers.STATIC; }
542 /* FIXME: FRIEND and PROTECTED FRIEND are missing */
546 : MODULE IDENTIFIER EOL
550 // FIXME : Check for valid module modifiers
551 name = MakeName((string) $2);
552 new_module = new Module(current_container,
555 (Attributes) current_attributes,
557 current_container = new_module;
558 current_container.Namespace = current_namespace;
559 RootContext.Tree.RecordDecl(name, new_module);
561 opt_class_member_declarations
564 Module new_module = (Module)current_container;
566 current_container = current_container.Parent;
567 CheckDef (current_container.AddClass(new_module), new_module.Name, new_module.Location);
573 opt_class_member_declarations
575 | class_member_declarations
578 class_member_declarations
579 : class_member_declaration
580 | class_member_declarations class_member_declaration
583 class_member_declaration
588 current_attributes = (Attributes) $1;
589 current_modifiers = (int) $2;
591 class_member_declarator
597 class_member_declarator
599 constructor_declaration
602 Method method = (Method) $1;
603 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
606 | property_declaration
607 // | event_declaration
608 | withevents_declaration /* This is a field but must be treated specially, see below */
619 : SUB IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler EOL
622 current_local_parameters = (Parameters) $4;
625 opt_local_declarations
627 /* This is WEIRD: declaring a method (sub) in a module as static will
628 trigger a syntax error, but the same methods MUST be static in order
629 to be properly called
631 if (current_container is Module) {
632 if (current_modifiers == Modifiers.STATIC) {
633 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
637 current_modifiers = Modifiers.STATIC;
644 Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
645 (Parameters) current_local_parameters, null, lexer.Location);
647 method.Block = (Block) end_block();
650 if ($6 != null) { /* we have an event handler to take care of */
651 // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
652 string evt_def = ((MemberAccess)$6).ToString();
653 int pos = evt_def.LastIndexOf (".");
654 string evt_target = ((string) $2).Substring (0, pos);
656 foreach (Property p in current_container.Properties) {
657 if (p.Name == evt_target) {
659 // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
660 AddHandler (p.Set.Block, (Expression)$6, (string) $2);
671 : FUNCTION IDENTIFIER
672 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type EOL
675 current_local_parameters = (Parameters) $4;
678 opt_local_declarations
680 /* This is WEIRD: declaring a method (sub) in a module as static will
681 trigger a syntax error, but the same methods MUST be static in order
682 to be properly called
684 if (current_container is Module) {
685 if (current_modifiers == Modifiers.STATIC) {
686 Report.Error (30810, lexer.Location, "Methods cannot be declared 'Static'");
690 current_modifiers = Modifiers.STATIC;
693 // Add local var declaration
695 ArrayList retval = new ArrayList ();
696 retval.Add (new VariableDeclaration ((string) $2, null, lexer.Location));
697 declare_local_variables ((Expression) $7, retval, lexer.Location);
702 Method method = new Method ((Expression) $7, (int) current_modifiers, (string) $2,
703 (Parameters) current_local_parameters, null, lexer.Location);
705 method.Block = end_block();
712 : PROPERTY IDENTIFIER opt_property_parameters AS type EOL
714 get_implicit_value_parameter_type = (Expression) $5;
715 get_implicit_value_parameter_name = (string) $2;
717 current_local_parameters = (Parameters) $3;
718 if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
719 get_parameters = current_local_parameters.Copy (lexer.Location);
720 set_parameters = current_local_parameters.Copy (lexer.Location);
724 get_parameters = Parameters.EmptyReadOnlyParameters;
725 set_parameters = new Parameters (null, null ,lexer.Location);
727 lexer.PropertyParsing = true;
731 accessor_declarations
734 lexer.PropertyParsing = false;
737 Pair pair = (Pair) $8;
738 Accessor get_block = (Accessor) pair.First;
739 Accessor set_block = (Accessor) pair.Second;
740 Location loc = lexer.Location;
742 prop = new Property ((Expression) $5, (string) $2, current_modifiers, get_block, set_block,
743 current_attributes, loc, set_implicit_value_parameter_name,
744 get_parameters, set_parameters);
746 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
747 get_implicit_value_parameter_type = null;
748 set_implicit_value_parameter_type = null;
749 get_parameters = null;
750 set_parameters = null;
751 current_local_parameters = null;
755 opt_property_parameters
758 $$ = Parameters.EmptyReadOnlyParameters; ;
760 | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
766 accessor_declarations
767 : get_accessor_declaration opt_set_accessor_declaration
769 $$ = new Pair ($1, $2);
771 | set_accessor_declaration opt_get_accessor_declaration
773 $$ = new Pair ($2, $1);
777 opt_get_accessor_declaration
778 : /* empty */ { $$ = null; }
779 | get_accessor_declaration
782 opt_set_accessor_declaration
783 : /* empty */ { $$ = null; }
784 | set_accessor_declaration
787 get_accessor_declaration
788 : opt_attributes GET EOL
790 current_local_parameters = get_parameters;
792 lexer.PropertyParsing = false;
795 // Add local var declaration
797 ArrayList retval = new ArrayList ();
798 retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, null, lexer.Location));
799 declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
805 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
806 current_local_parameters = null;
807 lexer.PropertyParsing = true;
811 set_accessor_declaration
812 : opt_attributes SET opt_set_parameter EOL
815 Parameter implicit_value_parameter = new Parameter (
816 set_implicit_value_parameter_type,
817 set_implicit_value_parameter_name,
818 Parameter.Modifier.NONE, null);
820 current_local_parameters = set_parameters;
821 current_local_parameters.AppendParameter (implicit_value_parameter);
824 lexer.PropertyParsing = false;
829 $$ = new Accessor ((Block) end_block(), (Attributes) $1);
830 current_local_parameters = null;
831 lexer.PropertyParsing = true;
838 set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
839 set_implicit_value_parameter_name = "Value";
841 | OPEN_PARENS opt_identifier opt_type_spec CLOSE_PARENS
843 /* FIXME: possible syntax error which must be caught
844 Set ( As <type>) is currently (and wrongly so) legal
846 set_implicit_value_parameter_type = (Expression) $3;
848 set_implicit_value_parameter_name = (string) $2;
850 set_implicit_value_parameter_name = "Value";
856 variable_declarators EOL
858 int mod = (int) current_modifiers;
861 VariableDeclaration.FixupTypes ((ArrayList) $2);
862 VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
864 if (current_container is Module)
865 mod = mod | Modifiers.STATIC;
867 foreach (VariableDeclaration var in (ArrayList) $2){
868 Location l = var.Location;
870 Field field = new Field (var.type, mod, var.identifier,
871 var.expression_or_array_initializer,
872 (Attributes) null, l);
874 CheckDef (current_container.AddField (field), field.Name, l);
879 withevents_declaration
880 : WITHEVENTS variable_declarators EOL
882 /* WithEvents Fields must be resolved into properties
883 with a bit of magic behind the scenes */
885 VariableDeclaration.FixupTypes ((ArrayList) $2);
887 foreach (VariableDeclaration var in (ArrayList) $2) {
888 // 1 - We create a private field
889 Location l = var.Location;
891 if ((current_modifiers & Modifiers.STATIC) > 0)
892 Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
894 Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier,
895 var.expression_or_array_initializer,
896 (Attributes) null, l);
898 CheckDef (current_container.AddField (field), field.Name, l);
900 // 2 - Public property
902 prop = BuildSimpleProperty (var.type, (string) var.identifier,
903 field, (int) current_modifiers,
904 (Attributes) current_attributes, l);
906 CheckDef (current_container.AddProperty (prop), prop.Name, l);
918 IDENTIFIER OPEN_PARENS
919 opt_formal_parameter_list
923 Location l = lexer.Location;
924 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (current_container, TypeManager.system_void_expr,
925 (int) current_modifiers,
926 MakeName ((string) $3), (Parameters) $5,
927 (Attributes) current_attributes, l);
929 del.Namespace = current_namespace;
930 CheckDef (current_container.AddDelegate (del), del.Name, l);
933 IDENTIFIER OPEN_PARENS
934 opt_formal_parameter_list
937 Location l = lexer.Location;
938 Mono.CSharp.Delegate del = new Mono.CSharp.Delegate (
940 (Expression) $8, (int) current_modifiers, MakeName ((string) $3),
941 (Parameters) $5, (Attributes) current_attributes, l);
943 del.Namespace = current_namespace;
944 CheckDef (current_container.AddDelegate (del), del.Name, l);
951 | HANDLES qualified_identifier
953 $$ = (Expression) DecomposeQI ((string)$2, lexer.Location);
957 constructor_declaration
958 : constructor_declarator
959 opt_local_declarations
962 Constructor c = (Constructor) $1;
963 c.Block = (Block) end_block();
964 c.ModFlags = (int) current_modifiers;
965 c.OptAttributes = (Attributes) null;
967 CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
968 current_local_parameters = null;
973 constructor_declarator
974 : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
976 current_local_parameters = (Parameters) $4;
978 oob_stack.Push (lexer.Location);
980 Location l = (Location) oob_stack.Pop ();
981 $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
986 opt_formal_parameter_list
989 $$ = Parameters.EmptyReadOnlyParameters;
991 | formal_parameter_list
994 //Parameter p = ((Parameters) $1).FixedParameters[0];
998 formal_parameter_list
1001 ArrayList pars_list = (ArrayList) $1;
1003 Parameter [] pars = new Parameter [pars_list.Count];
1004 pars_list.CopyTo (pars);
1005 $$ = new Parameters (pars, null, lexer.Location);
1007 | fixed_parameters COMMA parameter_array
1009 ArrayList pars_list = (ArrayList) $1;
1011 Parameter [] pars = new Parameter [pars_list.Count];
1012 pars_list.CopyTo (pars);
1014 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
1018 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
1025 ArrayList pars = new ArrayList ();
1030 | fixed_parameters COMMA fixed_parameter
1032 ArrayList pars = (ArrayList) $1;
1041 opt_parameter_modifier
1042 IDENTIFIER opt_type_spec opt_variable_initializer
1044 Parameter.Modifier pm = (Parameter.Modifier)$2;
1045 bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
1047 if (opt_parm && ($5 == null))
1048 Report.Error (999, "Optional parameters must have a default value");
1051 pm = Parameter.Modifier.NONE; //FIXME: should take into account BYREF
1053 $$ = new Parameter ((Expression) $4, (string) $3,
1054 pm, (Attributes) $1, (Expression) $5, opt_parm);
1059 : PARAM_ARRAY IDENTIFIER opt_parens AS type
1061 $$ = new Parameter ((Expression) $5, (string) $2, Parameter.Modifier.PARAMS, null);
1062 // note ("type must be a single-dimension array type");
1068 | OPEN_PARENS CLOSE_PARENS
1072 : /* empty */ { $$ = (Expression) TypeManager.system_object_expr; }
1073 | AS type { $$ = (Expression) $2; };
1076 opt_parameter_modifier
1077 : /* empty */ { $$ = Parameter.Modifier.VAL; }
1078 | parameter_modifiers { $$ = $1; }
1082 : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
1083 | parameter_modifier { $$ = $1; }
1087 : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1088 | BYVAL { $$ = Parameter.Modifier.VAL; }
1089 | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; }
1092 opt_actual_parameters
1094 | qualified_identifier
1100 | statement_list EOL
1105 | statement_list EOL statement
1108 statement : embedded_statement
1110 Statement s = (Statement) $1;
1112 current_block.AddStatement ((Statement) $1);
1114 | labeled_statement EOL
1115 | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
1117 AddHandler ((Expression) $2, (string) $5);
1125 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
1127 if (!current_block.AddLabel ((string) $1, labeled)){
1128 Location l = lexer.Location;
1129 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
1131 current_block.AddStatement (labeled);
1137 : expression_statement
1138 | selection_statement
1139 | iteration_statement
1146 | continue_statement
1149 | */return_statement
1156 $$ = new Exit ((ExitType)$2, lexer.Location);
1161 : DO { $$ = ExitType.DO; }
1162 | FOR { $$ = ExitType.FOR; }
1163 | WHILE { $$ = ExitType.WHILE; }
1164 | SELECT { $$ = ExitType.SELECT; }
1165 | SUB { $$ = ExitType.SUB; }
1166 | FUNCTION { $$ = ExitType.FUNCTION; }
1167 | PROPERTY { $$ = ExitType.PROPERTY; }
1168 | TRY { $$ = ExitType.TRY; }
1171 : RETURN opt_expression
1173 $$ = new Return ((Expression) $2, lexer.Location);
1181 /*| foreach_statement*/
1194 ArrayList s = new ArrayList ();
1196 foreach (Catch cc in (ArrayList) tmp_catch_clauses) {
1203 // Now s contains the list of specific catch clauses
1204 // and g contains the general one.
1205 Block b = end_block();
1207 $$ = new Try ((Block) b, s, g, null, lexer.Location);
1214 tmp_block = end_block();
1224 ArrayList s = new ArrayList ();
1225 ArrayList catch_list = (ArrayList) tmp_catch_clauses;
1227 if (catch_list != null){
1228 foreach (Catch cc in catch_list) {
1236 $$ = new Try ((Block) tmp_block, s, g, (Block) end_block(), lexer.Location);
1243 { Console.WriteLine ("try_header");
1249 tmp_catch_clauses = (ArrayList) $5;
1254 : /* empty */ { $$ = null; }
1261 ArrayList l = new ArrayList ();
1266 | catch_clauses catch_clause
1268 ArrayList l = (ArrayList) $1;
1276 : /* empty */ { $$ = null; }
1281 : CATCH opt_catch_args EOL
1283 Expression type = null;
1287 DictionaryEntry cc = (DictionaryEntry) $2;
1288 type = (Expression) cc.Key;
1289 id = (string) cc.Value;
1292 ArrayList one = new ArrayList ();
1293 Location loc = lexer.Location;
1295 one.Add (new VariableDeclaration (id, null, loc));
1299 current_block = new Block (current_block);
1300 Block b = declare_local_variables (type, one, loc);
1306 opt_statement_list {
1307 Expression type = null;
1309 Block b_catch = current_block;
1312 DictionaryEntry cc = (DictionaryEntry) $2;
1313 type = (Expression) cc.Key;
1314 id = (string) cc.Value;
1318 // FIXME: I can change this for an assignment.
1320 while (current_block != (Block) $1)
1321 current_block = current_block.Parent;
1325 $$ = new Catch (type, id , (Block)b_catch, lexer.Location);
1330 : /* empty */ { $$ = null; }
1335 : IDENTIFIER AS type
1337 $$ = new DictionaryEntry ($3, $1);
1343 : DO opt_do_construct EOL
1346 oob_stack.Push (lexer.Location);
1349 LOOP opt_do_construct
1351 Expression t_before = (Expression) $2;
1352 Expression t_after = (Expression) $7;
1355 if ((t_before != null) && (t_after != null))
1356 Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
1358 if ((t_before == null) && (t_after == null))
1359 t = new BoolLiteral (true);
1361 t = (t_before != null) ? t_before : t_after;
1363 DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
1365 if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
1366 ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
1367 t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
1369 $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
1374 : /* empty */ { $$ = null; }
1375 | while_or_until boolean_expression
1377 do_type = (DoOptions)$1;
1378 $$ = (Expression) $2;
1383 : WHILE { $$ = DoOptions.WHILE; }
1384 | UNTIL { $$ = DoOptions.UNTIL; }
1391 oob_stack.Push (lexer.Location);
1393 boolean_expression EOL
1397 Location l = (Location) oob_stack.Pop ();
1398 Block b = end_block();
1399 Expression e = (Expression) $3;
1400 $$ = new While ((Expression) e, (Statement) b, l);
1406 : FOR qualified_identifier ASSIGN expression TO expression opt_step EOL
1411 NEXT opt_next_identifier
1413 Block statement = end_block();
1414 Expression for_var = (Expression) DecomposeQI ((string)$2, lexer.Location);;
1416 Expression assign_expr = new Assign (for_var, (Expression) $4, lexer.Location);
1417 Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual,
1418 for_var, (Expression) $6, lexer.Location);
1419 Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
1420 for_var, (Expression) $7, lexer.Location), lexer.Location);
1422 Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, lexer.Location);
1423 Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, lexer.Location);
1425 $$ = new For (assign_stmt, test_expr, step_stmt, statement, lexer.Location);
1430 : /* empty */ { $$ = new IntLiteral ((Int32) 1); }
1431 | STEP expression { $$ = $2; }
1436 | qualified_identifier
1445 : if_statement_open if_statement_rest
1452 : IF boolean_expression THEN EOL
1454 oob_stack.Push (lexer.Location);
1456 tmp_expr = (Expression) $2;
1465 Location l = (Location) oob_stack.Pop ();
1467 $$ = new If ((Expression) tmp_expr, (Statement) end_block(), l);
1474 tmp_block = end_block();
1480 Location l = (Location) oob_stack.Pop ();
1482 $$ = new If ((Expression) tmp_expr, (Statement) tmp_block, (Statement) end_block(), l);
1487 : SELECT opt_case expression EOL
1489 oob_stack.Push (lexer.Location);
1490 switch_stack.Push (current_block);
1495 $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
1496 current_block = (Block) switch_stack.Pop ();
1501 : /* empty */ { $$ = null; }
1502 | case_sections { $$ = $1; }
1506 : case_sections case_section
1508 ArrayList sections = (ArrayList) $1;
1515 ArrayList sections = new ArrayList ();
1523 : CASE case_clauses EOL
1529 Block topmost = current_block;
1531 while (topmost.Implicit)
1532 topmost = topmost.Parent;
1534 // FIXME: This is a horrible hack which MUST go
1535 topmost.statements.Add (new Break (lexer.Location));
1536 $$ = new SwitchSection ((ArrayList) $2, topmost);
1539 /* FIXME: we should somehow flag an error
1540 (BC30321 'Case' cannot follow a 'Case Else'
1541 in the same 'Select' statement.)
1542 if Case Else is not the last of the Case clauses
1549 Block topmost = current_block;
1551 while (topmost.Implicit)
1552 topmost = topmost.Parent;
1554 // FIXME: This is a horrible hack which MUST go
1555 topmost.statements.Add (new Break (lexer.Location));
1557 ArrayList a = new ArrayList();
1558 a.Add (new SwitchLabel (null, lexer.Location));
1559 $$ = new SwitchSection ((ArrayList) a, topmost);
1566 ArrayList labels = new ArrayList ();
1571 | case_clauses COMMA case_clause
1573 ArrayList labels = (ArrayList) ($1);
1581 : opt_is comparison_operator expression
1584 $$ = new SwitchLabel ((Expression) $1, lexer.Location);
1607 expression_statement
1608 : statement_expression
1614 statement_expression
1615 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
1616 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
1617 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
1620 object_creation_expression
1621 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
1623 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
1628 : object_creation_expression
1629 /* | array_creation_expression */
1632 assignment_expression
1633 : prefixed_unary_expression ASSIGN expression
1635 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
1639 opt_local_declarations
1641 | local_declarations
1642 { if ($1 != null && (Block) $1 != current_block){
1643 current_block.AddStatement ((Statement) $1);
1644 current_block = (Block) $1;
1650 : local_declaration EOL
1651 | local_declaration EOL local_declarations
1655 : local_variable_declaration
1658 DictionaryEntry de = (DictionaryEntry) $1;
1660 $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
1664 | local_constant_declaration
1667 DictionaryEntry de = (DictionaryEntry) $1;
1669 $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
1674 local_variable_declaration
1675 : DIM variable_declarators
1677 $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);
1679 | DIM variable_declarators
1681 $$ = new DictionaryEntry (TypeManager.system_object_expr, $2);
1683 /*| DIM variable_declarators AS object_creation_expression
1686 $$ = new DictionaryEntry ($4, $2);
1694 local_constant_declaration
1695 : CONST constant_declarator
1698 $$ = new DictionaryEntry ($1, $2);
1705 : IDENTIFIER ASSIGN constant_expression
1707 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
1711 variable_declarators
1712 : variable_declarator
1714 ArrayList decl = new ArrayList ();
1718 | variable_declarators COMMA variable_declarator
1720 ArrayList decls = (ArrayList) $1;
1727 : variable_identifier opt_type_decl opt_variable_initializer
1729 string varname = (string)$1;
1731 Expression vartype = (Expression) $2;
1732 Expression varinit = (Expression) $3;
1734 Check for a declaration like Dim a(2) or Dim a(2,3)
1735 If this is the case, we must generate an ArrayCreationExpression
1736 and, in case, add the initializer after the array has been created.
1738 if (VariableDeclaration.IsArrayDecl (varname)) {
1739 if (VariableDeclaration.HasDimBounds(varname)) {
1740 varname = VariableDeclaration.StripDims (varname, ref dims);
1741 ArrayList a_dims = VariableDeclaration.ParseDims(dims);
1742 varinit = new ArrayCreation (vartype, a_dims,"", null, lexer.Location);
1744 vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.GetRank (dims), lexer.Location);
1747 $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
1752 : IDENTIFIER opt_array_name_modifier
1756 $$ = (string)$$ + (string)$2;
1765 | AS type opt_argument_list /* FIXME must handle argument list*/
1769 | AS NEW type opt_argument_list /* FIXME must handle NEW clause + argument list */
1775 opt_array_name_modifier
1776 : /* empty */ { $$ = null; }
1777 | array_type_modifier { $$ = $1; }
1778 | array_initialization_modifier
1782 : rank_specifiers { $$ = $1; }
1801 | dim_separators COMMA
1803 $$ = (string) $1 + ",";
1807 opt_variable_initializer
1808 : /* empty */ { $$ = null; }
1809 | ASSIGN variable_initializer { $$ = $2; }
1812 array_initialization_modifier
1813 : /* empty */ { $$ = null; }
1816 variable_initializer
1821 /*| array_initializer
1829 * The following is from Rhys' grammar:
1830 * > Types in local variable declarations must be recognized as
1831 * > expressions to prevent reduce/reduce errors in the grammar.
1832 * > The expressions are converted into types during semantic analysis.
1835 : primary_expression opt_rank_specifier
1837 // FIXME: Do something smart here regarding the composition of the type.
1839 // Ok, the above "primary_expression" is there to get rid of
1840 // both reduce/reduce and shift/reduces in the grammar, it should
1841 // really just be "type_name". If you use type_name, a reduce/reduce
1842 // creeps up. If you use qualified_identifier (which is all we need
1843 // really) two shift/reduces appear.
1846 // So the super-trick is that primary_expression
1847 // can only be either a SimpleName or a MemberAccess.
1848 // The MemberAccess case arises when you have a fully qualified type-name like :
1850 // SimpleName is when you have
1853 Expression expr = (Expression) $1;
1854 if (!(expr is SimpleName || expr is MemberAccess)) {
1855 Error_ExpectingTypeName (lexer.Location, expr);
1859 // So we extract the string corresponding to the SimpleName
1862 if ((string) $2 == "")
1865 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1868 | builtin_types opt_rank_specifier
1870 if ((string) $2 == "")
1873 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1882 | rank_specifiers rank_specifier
1884 $$ = (string) $2 + (string) $1;
1889 : OPEN_PARENS opt_dim_separators CLOSE_PARENS
1891 $$ = "[" + (string) $2 + "]";
1926 | dim_separators COMMA
1928 $$ = (string) $1 + ",";
1933 : integer_literal { $$ = ((IntLiteral)$1).AsString(); }
1934 | dim_specifiers COMMA integer_literal { $$ = $1 + "," + ((IntLiteral)$3).AsString(); }
1944 | qualified_identifier
1946 string name = (string) $1;
1949 $$ = DecomposeQI (name, lexer.Location);
1951 | parenthesized_expression
1953 | invocation_expression
1964 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
1965 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
1966 | NOTHING { $$ = NullLiteral.Null; }
1970 : LITERAL_SINGLE { $$ = new FloatLiteral ((float) lexer.Value); }
1971 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
1972 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1977 object v = lexer.Value;
1980 $$ = new IntLiteral ((Int32) v);
1982 $$ = new UIntLiteral ((UInt32) v);
1984 $$ = new LongLiteral ((Int64) v);
1985 else if (v is ulong)
1986 $$ = new ULongLiteral ((UInt64) v);
1988 Console.WriteLine ("OOPS. Unexpected result from scanner");
1994 : TRUE { $$ = new BoolLiteral (true); }
1995 | FALSE { $$ = new BoolLiteral (false); }
1998 parenthesized_expression
1999 : OPEN_PARENS expression CLOSE_PARENS
2004 : primary_expression DOT IDENTIFIER
2006 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2008 | predefined_type DOT IDENTIFIER
2010 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2018 invocation_expression
2019 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2022 Location l = lexer.Location;
2023 Report.Error (1, l, "THIS IS CRAZY");
2025 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2030 : /* empty */ { $$ = null; }
2037 ArrayList list = new ArrayList ();
2041 | argument_list COMMA argument
2043 ArrayList list = (ArrayList) $1;
2052 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2054 | BYREF variable_reference
2056 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2060 $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
2065 : expression {/* note ("section 5.4"); */ $$ = $1; }
2069 : primary_expression OPEN_PARENS expression_list CLOSE_PARENS
2071 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2073 /*| primary_expression rank_specifiers
2075 // So the super-trick is that primary_expression
2076 // can only be either a SimpleName or a MemberAccess.
2077 // The MemberAccess case arises when you have a fully qualified type-name like :
2079 // SimpleName is when you have
2081 Expression expr = (Expression) $1;
2083 if (!(expr is SimpleName || expr is MemberAccess)) {
2084 Error_ExpectingTypeName (lexer.Location, expr);
2085 $$ = TypeManager.system_object_expr;
2088 // So we extract the string corresponding to the SimpleName
2091 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2104 ArrayList list = new ArrayList ();
2108 | expression_list COMMA expression
2110 ArrayList list = (ArrayList) $1;
2119 $$ = new This (current_block, lexer.Location);
2124 : MYBASE DOT IDENTIFIER
2126 $$ = new BaseAccess ((string) $3, lexer.Location);
2128 | MYBASE OPEN_BRACKET expression_list CLOSE_BRACKET
2130 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
2134 post_increment_expression
2135 : primary_expression OP_INC
2137 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2138 (Expression) $1, lexer.Location);
2143 : primary_expression
2144 | NOT prefixed_unary_expression
2146 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2151 // The idea to split this out is from Rhys' grammar
2152 // to solve the problem with casts.
2154 prefixed_unary_expression
2156 | PLUS prefixed_unary_expression
2158 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2160 | MINUS prefixed_unary_expression
2162 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2164 | ADDRESSOF prefixed_unary_expression
2166 // FIXME: We should generate an error if AddressOf is NOT used
2167 // during delegate creation
2172 multiplicative_expression
2173 : prefixed_unary_expression
2174 | multiplicative_expression STAR prefixed_unary_expression
2176 $$ = new Binary (Binary.Operator.Multiply,
2177 (Expression) $1, (Expression) $3, lexer.Location);
2179 | multiplicative_expression DIV prefixed_unary_expression
2181 $$ = new Binary (Binary.Operator.Division,
2182 (Expression) $1, (Expression) $3, lexer.Location);
2184 | multiplicative_expression OP_MODULUS prefixed_unary_expression
2186 $$ = new Binary (Binary.Operator.Modulus,
2187 (Expression) $1, (Expression) $3, lexer.Location);
2192 : multiplicative_expression
2193 | additive_expression PLUS multiplicative_expression
2195 $$ = new Binary (Binary.Operator.Addition,
2196 (Expression) $1, (Expression) $3, lexer.Location);
2198 | additive_expression MINUS multiplicative_expression
2200 $$ = new Binary (Binary.Operator.Subtraction,
2201 (Expression) $1, (Expression) $3, lexer.Location);
2205 relational_expression
2206 : additive_expression
2207 | relational_expression OP_LT additive_expression
2209 $$ = new Binary (Binary.Operator.LessThan,
2210 (Expression) $1, (Expression) $3, lexer.Location);
2212 | relational_expression OP_GT additive_expression
2214 $$ = new Binary (Binary.Operator.GreaterThan,
2215 (Expression) $1, (Expression) $3, lexer.Location);
2217 | relational_expression OP_LE additive_expression
2219 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2220 (Expression) $1, (Expression) $3, lexer.Location);
2222 | relational_expression OP_GE additive_expression
2224 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2225 (Expression) $1, (Expression) $3, lexer.Location);
2227 | relational_expression IS type
2229 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2231 | relational_expression AS type
2233 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2238 : relational_expression
2239 | equality_expression OP_EQ relational_expression
2241 $$ = new Binary (Binary.Operator.Equality,
2242 (Expression) $1, (Expression) $3, lexer.Location);
2244 | equality_expression OP_NE relational_expression
2246 $$ = new Binary (Binary.Operator.Inequality,
2247 (Expression) $1, (Expression) $3, lexer.Location);
2252 : equality_expression
2253 | and_expression OP_AND equality_expression
2255 $$ = new Binary (Binary.Operator.BitwiseAnd,
2256 (Expression) $1, (Expression) $3, lexer.Location);
2260 exclusive_or_expression
2262 | exclusive_or_expression OP_XOR and_expression
2264 $$ = new Binary (Binary.Operator.ExclusiveOr,
2265 (Expression) $1, (Expression) $3, lexer.Location);
2269 conditional_and_expression
2270 : exclusive_or_expression
2271 | conditional_and_expression OP_AND exclusive_or_expression
2273 $$ = new Binary (Binary.Operator.LogicalAnd,
2274 (Expression) $1, (Expression) $3, lexer.Location);
2278 conditional_or_expression
2279 : conditional_and_expression
2280 | conditional_or_expression OP_OR conditional_and_expression
2282 $$ = new Binary (Binary.Operator.LogicalOr,
2283 (Expression) $1, (Expression) $3, lexer.Location);
2287 conditional_expression
2288 : conditional_or_expression
2291 assignment_expression
2292 : prefixed_unary_expression ASSIGN expression
2294 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2299 : conditional_expression
2300 | assignment_expression
2312 : type_name { /* class_type */
2314 This does interfaces, delegates, struct_types, class_types,
2315 parent classes, and more! 4.2
2317 $$ = DecomposeQI ((string) $1, lexer.Location);
2327 ArrayList types = new ArrayList ();
2332 | type_list COMMA type
2334 ArrayList types = (ArrayList) $1;
2342 : namespace_or_type_name
2345 namespace_or_type_name
2346 : qualified_identifier
2350 : type rank_specifiers
2352 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2357 : rank_specifier opt_rank_specifier
2359 $$ = (string) $2 + (string) $1;
2364 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2366 $$ = "[" + (string) $2 + "]";
2386 | dim_separators COMMA
2388 $$ = (string) $1 + ",";
2391 /* Built-in / Integral types */
2393 : OBJECT { $$ = TypeManager.system_object_expr; }
2394 | STRING { $$ = TypeManager.system_string_expr; }
2395 | BOOLEAN { $$ = TypeManager.system_boolean_expr; }
2396 | DECIMAL { $$ = TypeManager.system_decimal_expr; }
2397 | SINGLE { $$ = TypeManager.system_single_expr; }
2398 | DOUBLE { $$ = TypeManager.system_double_expr; }
2403 : /*SBYTE { $$ = TypeManager.system_sbyte_expr; }
2404 | BYTE { $$ = TypeManager.system_byte_expr; }
2405 | SHORT { $$ = TypeManager.system_int16_expr; }
2406 | USHORT { $$ = TypeManager.system_uint16_expr; }
2407 | */ INTEGER { $$ = TypeManager.system_int32_expr; }/*
2408 | UINT { $$ = TypeManager.system_uint32_expr; }
2409 | LONG { $$ = TypeManager.system_int64_expr; }
2410 | ULONG { $$ = TypeManager.system_uint64_expr; }
2411 | CHAR { $$ = TypeManager.system_char_expr; }
2412 | VOID { $$ = TypeManager.system_void_expr; }*/
2420 public Tokenizer Lexer {
2426 Expression DecomposeQI (string name, Location loc)
2430 if (name.IndexOf ('.') == -1){
2431 return new SimpleName (name, loc);
2433 int pos = name.LastIndexOf (".");
2434 string left = name.Substring (0, pos);
2435 string right = name.Substring (pos + 1);
2437 o = DecomposeQI (left, loc);
2439 return new MemberAccess (o, right, loc);
2443 Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc)
2445 Block implicit_block;
2446 ArrayList inits = null;
2449 // We use the `Used' property to check whether statements
2450 // have been added to the current block. If so, we need
2451 // to create another block to contain the new declaration
2452 // otherwise, as an optimization, we use the same block to
2453 // add the declaration.
2455 // FIXME: A further optimization is to check if the statements
2456 // that were added were added as part of the initialization
2457 // below. In which case, no other statements have been executed
2458 // and we might be able to reduce the number of blocks for
2459 // situations like this:
2461 // int j = 1; int k = j + 1;
2464 VariableDeclaration.FixupTypes (variable_declarators);
2466 if (current_block.Used) {
2467 implicit_block = new Block (current_block, true, loc, Location.Null);
2468 implicit_block.AddChildVariableNames (current_block);
2470 implicit_block = current_block;
2472 foreach (VariableDeclaration decl in variable_declarators){
2473 Expression type = decl.type;
2474 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
2475 if (decl.expression_or_array_initializer != null){
2477 inits = new ArrayList ();
2484 return implicit_block;
2486 foreach (VariableDeclaration decl in inits){
2489 Expression type = decl.type;
2491 if (decl.expression_or_array_initializer is Expression){
2492 expr = (Expression) decl.expression_or_array_initializer;
2495 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
2497 expr = new ArrayCreation (type, "", init, decl.Location);
2500 LocalVariableReference var;
2501 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
2503 assign = new Assign (var, expr, decl.Location);
2505 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
2508 return implicit_block;
2512 Block declare_local_constant (Expression type, VariableDeclaration decl)
2514 Block implicit_block;
2516 if (current_block.Used)
2517 implicit_block = new Block (current_block, true);
2519 implicit_block = current_block;
2521 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
2522 current_local_parameters, decl.Location))){
2525 return implicit_block;
2529 // A class used to pass around variable declarations and constants
2531 public class VariableDeclaration {
2532 public string identifier;
2533 public object expression_or_array_initializer;
2534 public Location Location;
2535 public Attributes OptAttributes;
2536 public Expression type;
2537 public ArrayList dims;
2539 public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this
2540 (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
2544 public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
2546 this.identifier = id;
2547 this.expression_or_array_initializer = eoai;
2549 this.OptAttributes = opt_attrs;
2554 public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
2558 public static void FixupTypes (ArrayList vars)
2560 int varcount = vars.Count;
2561 VariableDeclaration lf = (VariableDeclaration) vars[varcount - 1];
2563 if (lf.type == null)
2564 lf.type = TypeManager.system_object_expr;
2566 Expression cur_type = lf.type;
2567 int n = varcount - 1;
2570 VariableDeclaration var = (VariableDeclaration) vars[n--];
2571 if (var.type == null)
2572 var.type = cur_type;
2574 cur_type = var.type;
2578 public static bool HasDimBounds (string varname)
2582 if (varname.IndexOf("[") >= 0) {
2583 char[] ds = {'1','2','3','4','5','6','7','8','9'};
2585 string dimpart = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
2586 if (dimpart.IndexOfAny (ds) >= 0)
2592 public static string StripDims (string varname, ref string d)
2594 string res = varname;
2597 if (varname.IndexOf("[") >= 0) {
2598 dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
2599 res = varname.Substring(0, varname.IndexOf("["));
2605 public static string GetRank (string dims)
2610 for (x = 0; x < dims.Length; x++) {
2611 if (dims[x] == '[' || dims[x] == ']' || dims[x] == ',')
2612 res = res + dims[x];
2617 public static ArrayList ParseDims (string dims)
2619 ArrayList res = new ArrayList();
2620 string d = dims.Substring (1, dims.Length -2);
2621 Array a = d.Split (',');
2623 if (a.GetLength(0) > 32) {
2624 Report.Error (999, "Arrays cannot have more than 32 dimensions");
2627 foreach (string s in a)
2628 res.Add (new IntLiteral ((Int32) Convert.ToInt32(s)));
2633 public static bool IsArrayDecl (string varname)
2635 return (varname.IndexOf("[") >= 0);
2638 public static void FixupArrayTypes (ArrayList vars)
2640 int varcount = vars.Count;
2643 foreach (VariableDeclaration var in vars) {
2644 if (var.identifier.EndsWith(",")) {
2645 dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","),
2646 var.identifier.LastIndexOf(",")) + "]";
2647 var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
2648 var.type = new ComposedCast (var.type, (string) dims, var.Location);
2654 public Property BuildSimpleProperty (Expression p_type, string name,
2655 Field p_fld, int mod_flags,
2656 Attributes attrs, Location loc)
2659 Block get_block, set_block;
2660 Accessor acc_set, acc_get;
2661 StatementExpression a_set;
2666 Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
2667 args = new Parameter [1];
2668 args [0] = implicit_value_parameter;
2670 Parameters set_params = new Parameters (args, null, loc);
2671 a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
2672 (Expression) new SimpleName("value", loc), loc), loc);
2674 set_block = new Block (current_block, set_params, loc, Location.Null);
2675 set_block.AddStatement ((Statement) a_set);
2676 acc_set = new Accessor (set_block, attrs);
2679 a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
2680 get_block = new Block (current_block, null, loc, Location.Null);
2681 get_block.AddStatement ((Statement) a_get);
2682 acc_get = new Accessor (get_block, attrs);
2684 p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
2691 current_block = new Block (current_block, current_local_parameters,
2692 lexer.Location, Location.Null);
2699 while (current_block.Implicit)
2700 current_block = current_block.Parent;
2702 res = current_block;
2704 current_block.SetEndLocation (lexer.Location);
2705 current_block = current_block.Parent;
2710 private void AddHandler (Expression evt_definition, string handler_name)
2712 AddHandler (current_block, evt_definition, handler_name);
2715 private void AddHandler (Block b, Expression evt_definition, string handler_name)
2717 Location loc = lexer.Location;
2718 ArrayList neh_args = new ArrayList();
2719 neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
2721 ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
2723 CompoundAssign ca = new CompoundAssign (
2724 Binary.Operator.Addition, evt_definition, (Expression) se, loc);
2726 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc));
2730 // FIXME: THIS DOES NOT WORK!!!
2731 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
2733 Location loc = lexer.Location;
2734 ArrayList neh_args = new ArrayList();
2735 neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
2737 ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
2739 CompoundAssign ca = new CompoundAssign (
2740 Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
2742 Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc));
2747 // This method is used to get at the complete string representation of
2748 // a fully-qualified type name, hiding inside a MemberAccess ;-)
2749 // This is necessary because local_variable_type admits primary_expression
2750 // as the type of the variable. So we do some extra checking
2752 string GetQualifiedIdentifier (Expression expr)
2754 if (expr is SimpleName)
2755 return ((SimpleName)expr).Name;
2756 else if (expr is MemberAccess)
2757 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
2759 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
2763 private void RemoveHandler (Expression evt_definition, string handler_name)
2765 RemoveHandler (current_block, evt_definition, handler_name);
2770 void Error_ExpectingTypeName (Location l, Expression expr)
2772 if (expr is Invocation){
2773 Report.Error (1002, l, "; expected");
2775 Report.Error (-1, l, "Invalid Type definition");
2779 static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
2783 public override int parse ()
2785 current_namespace = new Namespace (null, "");
2786 current_container = RootContext.Tree.Types;
2787 current_container.Namespace = current_namespace;
2788 oob_stack = new Stack ();
2789 switch_stack = new Stack ();
2791 UseExtendedSyntax = name.EndsWith(".mbs");
2793 lexer = new Tokenizer (input, name, defines);
2794 StringBuilder value = new StringBuilder ();
2795 //yacc_verbose_flag=true;
2798 if (yacc_verbose_flag)
2799 yyparse (lexer, new yydebug.yyDebugSimple ());
2805 Console.WriteLine (lexer.location + " : Parsing error in " + lexer.ref_name);
2806 Report.Error (9999, lexer.Location, "");
2807 Console.WriteLine (e);
2810 return Report.Errors;