X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fcs-parser.jay;h=06a28d3720836dc77878610a274d24e38e913586;hb=60e8d68027b115d6b4c1df3e179bb0cd7b5ee171;hp=f1f0263b62a80c678327e9c38f193a4b128eaef3;hpb=53dac313a0191d3101c71ecc969d62d5884eb373;p=mono.git diff --git a/mcs/gmcs/cs-parser.jay b/mcs/gmcs/cs-parser.jay index f1f0263b62a..06a28d37208 100644 --- a/mcs/gmcs/cs-parser.jay +++ b/mcs/gmcs/cs-parser.jay @@ -91,14 +91,14 @@ namespace Mono.CSharp /// string tmpComment; string enumTypeComment; - - - + /// Current attribute target string current_attr_target; /// assembly and module attribute definition is enabled bool global_attrs_enabled = true; + bool has_get, has_set; + %} %token EOF @@ -350,7 +350,7 @@ using_alias_directive using_namespace_directive : USING namespace_name SEMICOLON { - current_namespace.Using ((string) $2, lexer.Location); + current_namespace.Using ((MemberName) $2, lexer.Location); } ; @@ -363,19 +363,13 @@ namespace_declaration : opt_attributes NAMESPACE namespace_or_type_name { if ($1 != null) { - Report.Error(1518, Lexer.Location, "Attributes cannot be applied to namespaces." - + " Expected class, delegate, enum, interface, or struct"); + Report.Error(1671, Lexer.Location, "A namespace declaration cannot have modifiers or attributes"); } MemberName name = (MemberName) $3; if (name.TypeArguments != null) syntax_error (lexer.Location, "namespace name expected"); - else if ((current_namespace.Parent != null) && (name.Left != null)) { - Report.Error (134, lexer.Location, - "Cannot use qualified namespace names in nested " + - "namespace declarations"); - } current_namespace = new NamespaceEntry ( current_namespace, file, name.GetName (), lexer.Location); @@ -403,7 +397,7 @@ namespace_name if (name.TypeArguments != null) syntax_error (lexer.Location, "namespace name expected"); - $$ = name.GetName (); + $$ = name; } ; @@ -416,8 +410,6 @@ namespace_body opt_using_directives opt_namespace_member_declarations CLOSE_BRACE - { - } ; opt_using_directives @@ -438,25 +430,13 @@ namespace_member_declarations namespace_member_declaration : type_declaration { - string name = ""; - int mod_flags; - - if ($1 is Class){ - Class c = (Class) $1; - mod_flags = c.ModFlags; - name = c.Name; - } else if ($1 is Struct){ - Struct s = (Struct) $1; - mod_flags = s.ModFlags; - name = s.Name; - } else - break; + if ($1 != null) { + DeclSpace ds = (DeclSpace)$1; - if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){ - Report.Error ( - 1527, lexer.Location, - "Namespace elements cant be explicitly " + - "declared private or protected in `" + name + "'"); + if ((ds.ModFlags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){ + Report.Error (1527, lexer.Location, + "Namespace elements cannot be explicitly declared as private, protected or protected internal"); + } } current_namespace.DeclarationFound = true; } @@ -624,19 +604,23 @@ attribute } opt_attribute_arguments { + Location loc = (Location) $2; MemberName mname = (MemberName) $1; if (mname.IsGeneric) { Report.Error (404, lexer.Location, "'<' unexpected: attributes cannot be generic"); } - string name = mname.GetName (); + MemberName left = mname.Left; + string identifier = mname.Name; + + Expression left_expr = left == null ? null : left.GetTypeExpression (loc); + if (current_attr_target == "assembly" || current_attr_target == "module") - $$ = new GlobalAttribute (current_container, current_attr_target, - name, (ArrayList) $3, (Location) $2); + $$ = new GlobalAttribute (current_class, current_attr_target, + left_expr, identifier, (ArrayList) $3, loc); else - $$ = new Attribute (current_attr_target, name, (ArrayList) $3, - (Location) $2); + $$ = new Attribute (current_attr_target, left_expr, identifier, (ArrayList) $3, loc); } ; @@ -770,43 +754,44 @@ struct_declaration : opt_attributes opt_modifiers opt_partial - STRUCT member_name + STRUCT + { + lexer.ConstraintsParsing = true; + } + member_name { - MemberName name = MakeName ((MemberName) $5); + MemberName name = MakeName ((MemberName) $6); bool partial = (bool) $3; if (partial) { ClassPart part = PartialContainer.CreatePart ( - current_namespace, current_container, name, (int) $2, + current_namespace, current_class, name, (int) $2, (Attributes) $1, Kind.Struct, lexer.Location); current_container = part.PartialContainer; current_class = part; } else { current_class = new Struct ( - current_namespace, current_container, name, (int) $2, + current_namespace, current_class, name, (int) $2, (Attributes) $1, lexer.Location); + current_container.AddClassOrStruct (current_class); current_container = current_class; - RootContext.Tree.RecordDecl (name.GetName (true), current_class); + RootContext.Tree.RecordDecl (name, current_class); } - - lexer.ConstraintsParsing = true; } opt_class_base opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; - if ($7 != null) - current_class.Bases = (ArrayList) $7; + if ($8 != null) + current_class.Bases = (ArrayList) $8; - current_class.SetParameterInfo ((ArrayList) $8); + current_class.SetParameterInfo ((ArrayList) $9); if (RootContext.Documentation != null) current_class.DocComment = Lexer.consume_doc_comment (); - - current_class.Register (); } struct_body { @@ -815,10 +800,7 @@ struct_declaration } opt_semicolon { - $$ = current_class; - - current_container = current_container.Parent; - current_class = current_container; + $$ = pop_current_class (); } | opt_attributes opt_modifiers opt_partial STRUCT error { CheckIdentifierToken (yyToken); @@ -933,11 +915,9 @@ field_declaration int mod = (int) $2; foreach (VariableDeclaration var in (ArrayList) $4){ - Location l = var.Location; - Field field = new Field (current_class, type, mod, var.identifier, var.expression_or_array_initializer, - (Attributes) $1, l); + (Attributes) $1, var.Location); if (RootContext.Documentation != null) { field.DocComment = Lexer.consume_doc_comment (); @@ -946,6 +926,27 @@ field_declaration current_container.AddField (field); } } + | opt_attributes + opt_modifiers + FIXED + type + fixed_variable_declarators + SEMICOLON + { + Expression type = (Expression) $4; + int mod = (int) $2; + + foreach (VariableDeclaration var in (ArrayList) $5) { + FixedField field = new FixedField (current_class, type, mod, var.identifier, + (Expression)var.expression_or_array_initializer, (Attributes) $1, var.Location); + + if (RootContext.Documentation != null) { + field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + current_container.AddField (field); + } + } | opt_attributes opt_modifiers VOID @@ -955,11 +956,34 @@ field_declaration } ; +fixed_variable_declarators + : fixed_variable_declarator + { + ArrayList decl = new ArrayList (2); + decl.Add ($1); + $$ = decl; + } + | fixed_variable_declarators COMMA fixed_variable_declarator + { + ArrayList decls = (ArrayList) $1; + decls.Add ($3); + $$ = $1; + } + ; + +fixed_variable_declarator + : IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET + { + $$ = new VariableDeclaration ((string) $1, $3, lexer.Location); + } + ; + variable_declarators : variable_declarator { ArrayList decl = new ArrayList (4); - decl.Add ($1); + if ($1 != null) + decl.Add ($1); $$ = decl; } | variable_declarators COMMA variable_declarator @@ -979,6 +1003,12 @@ variable_declarator { $$ = new VariableDeclaration ((string) $1, null, lexer.Location); } + | IDENTIFIER OPEN_BRACKET opt_expression CLOSE_BRACKET + { + Report.Error (650, lexer.Location, "Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. " + + "To declare a fixed size buffer field, use the fixed keyword before the field type"); + $$ = null; + } ; variable_initializer @@ -1038,25 +1068,6 @@ method_declaration } ; -opt_error_modifier - : /* empty */ - | modifiers - { - int m = (int) $1; - int i = 1; - - while (m != 0){ - if ((i & m) != 0){ - Report.Error ( - 1585, lexer.Location, "Member modifier `" + - Modifiers.Name (i) + "' must precede member type and name"); - } - m &= ~i; - i = i << 1; - } - } - ; - method_header : opt_attributes opt_modifiers @@ -1173,7 +1184,7 @@ formal_parameter_list Parameter [] pars = new Parameter [pars_list.Count]; pars_list.CopyTo (pars); - $$ = new Parameters (pars, null, lexer.Location); + $$ = new Parameters (pars, null); } | fixed_parameters COMMA parameter_array { @@ -1182,7 +1193,7 @@ formal_parameter_list Parameter [] pars = new Parameter [pars_list.Count]; pars_list.CopyTo (pars); - $$ = new Parameters (pars, (Parameter) $3, lexer.Location); + $$ = new Parameters (pars, (Parameter) $3); } | fixed_parameters COMMA ARGLIST { @@ -1191,15 +1202,25 @@ formal_parameter_list Parameter [] pars = new Parameter [pars_list.Count]; pars_list.CopyTo (pars); - $$ = new Parameters (pars, true, lexer.Location); + $$ = new Parameters (pars, true); + } + | parameter_array COMMA fixed_parameters + { + Report.Error (231, lexer.Location, "A params parameter must be the last parameter in a formal parameter list"); + $$ = null; + } + | ARGLIST COMMA fixed_parameters + { + Report.Error (257, lexer.Location, "An __arglist parameter must be the last parameter in a formal parameter list"); + $$ = null; } | parameter_array { - $$ = new Parameters (null, (Parameter) $1, lexer.Location); + $$ = new Parameters (null, (Parameter) $1); } | ARGLIST { - $$ = new Parameters (null, true, lexer.Location); + $$ = new Parameters (null, true); } ; @@ -1226,7 +1247,15 @@ fixed_parameter type IDENTIFIER { - $$ = new Parameter ((Expression) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1); + $$ = new Parameter ((Expression) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1, lexer.Location); + } + | opt_attributes + opt_parameter_modifier + type + IDENTIFIER OPEN_BRACKET CLOSE_BRACKET + { + Report.Error (1552, lexer.Location, "Array type specifier, [], must appear before parameter name"); + $$ = null; } | opt_attributes opt_parameter_modifier @@ -1267,7 +1296,7 @@ parameter_modifier parameter_array : opt_attributes PARAMS type IDENTIFIER { - $$ = new Parameter ((Expression) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1); + $$ = new Parameter ((Expression) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1, lexer.Location); note ("type must be a single-dimension array type"); } | opt_attributes PARAMS parameter_modifier type IDENTIFIER @@ -1303,9 +1332,13 @@ property_declaration accessor_declarations { lexer.PropertyParsing = false; + has_get = has_set = false; } CLOSE_BRACE { + if ($8 == null) + break; + Property prop; Pair pair = (Pair) $8; Accessor get_block = (Accessor) pair.First; @@ -1317,7 +1350,7 @@ property_declaration if (name.TypeArguments != null) syntax_error (lexer.Location, "a property can't have type arguments"); - prop = new Property (current_container, (Expression) $3, (int) $2, false, + prop = new Property (current_class, (Expression) $3, (int) $2, false, name, (Attributes) $1, get_block, set_block, loc); if (SimpleIteratorContainer.Simple.Yields) prop.SetYields (); @@ -1333,26 +1366,33 @@ property_declaration ; accessor_declarations - : get_accessor_declaration opt_set_accessor_declaration - { - $$ = new Pair ($1, $2); - } - | set_accessor_declaration opt_get_accessor_declaration + : get_accessor_declaration + { + $$ = new Pair ($1, null); + } + | get_accessor_declaration accessor_declarations + { + Pair pair = (Pair) $2; + pair.First = $1; + $$ = pair; + } + | set_accessor_declaration + { + $$ = new Pair (null, $1); + } + | set_accessor_declaration accessor_declarations + { + Pair pair = (Pair) $2; + pair.Second = $1; + $$ = pair; + } + | error { - $$ = new Pair ($2, $1); + Report.Error (1014, lexer.Location, "A get or set accessor expected"); + $$ = null; } ; -opt_get_accessor_declaration - : /* empty */ { $$ = null; } - | get_accessor_declaration - ; - -opt_set_accessor_declaration - : /* empty */ { $$ = null; } - | set_accessor_declaration - ; - get_accessor_declaration : opt_attributes opt_modifiers GET { @@ -1366,7 +1406,12 @@ get_accessor_declaration } accessor_body { + if (has_get) { + Report.Error (1007, lexer.Location, "Property accessor already defined"); + break; + } $$ = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, lexer.Location); + has_get = true; current_local_parameters = null; lexer.PropertyParsing = true; @@ -1382,12 +1427,12 @@ set_accessor_declaration Parameter [] args; Parameter implicit_value_parameter = new Parameter ( implicit_value_parameter_type, "value", - Parameter.Modifier.NONE, null); + Parameter.Modifier.NONE, null, lexer.Location); if (parsing_indexer == false) { args = new Parameter [1]; args [0] = implicit_value_parameter; - current_local_parameters = new Parameters (args, null, lexer.Location); + current_local_parameters = new Parameters (args, null); } else { Parameter [] fpars = indexer_parameters.FixedParameters; @@ -1400,14 +1445,19 @@ set_accessor_declaration } else args = null; current_local_parameters = new Parameters ( - args, indexer_parameters.ArrayParameter, lexer.Location); + args, indexer_parameters.ArrayParameter); } lexer.PropertyParsing = false; } accessor_body { + if (has_set) { + Report.Error (1007, lexer.Location, "Property accessor already defined"); + break; + } $$ = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, lexer.Location); + has_set = true; current_local_parameters = null; lexer.PropertyParsing = true; @@ -1426,45 +1476,46 @@ interface_declaration : opt_attributes opt_modifiers opt_partial - INTERFACE member_name + INTERFACE { - MemberName name = MakeName ((MemberName) $5); + lexer.ConstraintsParsing = true; + } + member_name + { + MemberName name = MakeName ((MemberName) $6); bool partial = (bool) $3; if (partial) { ClassPart part = PartialContainer.CreatePart ( - current_namespace, current_container, name, (int) $2, + current_namespace, current_class, name, (int) $2, (Attributes) $1, Kind.Interface, lexer.Location); current_container = part.PartialContainer; current_class = part; } else { current_class = new Interface ( - current_namespace, current_container, name, (int) $2, + current_namespace, current_class, name, (int) $2, (Attributes) $1, lexer.Location); + current_container.AddInterface (current_class); current_container = current_class; - RootContext.Tree.RecordDecl (name.GetName (true), current_class); + RootContext.Tree.RecordDecl (name, current_class); } - - lexer.ConstraintsParsing = true; } opt_class_base opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; - if ($7 != null) - current_class.Bases = (ArrayList) $7; + if ($8 != null) + current_class.Bases = (ArrayList) $8; - current_class.SetParameterInfo ((ArrayList) $8); + current_class.SetParameterInfo ((ArrayList) $9); if (RootContext.Documentation != null) { current_class.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } - - current_class.Register (); } interface_body { @@ -1473,10 +1524,7 @@ interface_declaration } opt_semicolon { - $$ = current_class; - - current_container = current_container.Parent; - current_class = current_container; + $$ = pop_current_class (); } | opt_attributes opt_modifiers opt_partial INTERFACE error { CheckIdentifierToken (yyToken); @@ -1502,8 +1550,15 @@ interface_member_declarations interface_member_declaration : interface_method_declaration { + if ($1 == null) + break; + Method m = (Method) $1; + if (m.IsExplicitImpl) + Report.Error (541, lexer.Location, + "Explicit interface declaration can only be declared in a class or struct"); + current_container.AddMethod (m); if (RootContext.Documentation != null) @@ -1511,8 +1566,15 @@ interface_member_declaration } | interface_property_declaration { + if ($1 == null) + break; + Property p = (Property) $1; + if (p.IsExplicitImpl) + Report.Error (541, lexer.Location, + "Explicit interface declaration can only be declared in a class or struct"); + current_container.AddProperty (p); if (RootContext.Documentation != null) @@ -1522,6 +1584,11 @@ interface_member_declaration { if ($1 != null){ Event e = (Event) $1; + + if (e.IsExplicitImpl) + Report.Error (541, lexer.Location, + "Explicit interface declaration can only be declared in a class or struct"); + current_container.AddEvent (e); } @@ -1530,13 +1597,44 @@ interface_member_declaration } | interface_indexer_declaration { + if ($1 == null) + break; + Indexer i = (Indexer) $1; + if (i.IsExplicitImpl) + Report.Error (541, lexer.Location, + "Explicit interface declaration can only be declared in a class or struct"); + current_container.AddIndexer (i); if (RootContext.Documentation != null) Lexer.doc_state = XmlCommentState.Allowed; } + | delegate_declaration + { + Report.Error (524, lexer.Location, "Interfaces can not declare delegates"); + } + | class_declaration + { + Report.Error (524, lexer.Location, "Interfaces can not declare classes"); + } + | struct_declaration + { + Report.Error (524, lexer.Location, "Interfaces can not declare structures"); + } + | enum_declaration + { + Report.Error (524, lexer.Location, "Interfaces can not declare enumerations"); + } + | interface_declaration + { + Report.Error (524, lexer.Location, "Interfaces can not declare interfaces"); + } + | constant_declaration + { + Report.Error (525, lexer.Location, "Interfaces cannot contain constants"); + } ; opt_new @@ -1607,6 +1705,19 @@ interface_method_declaration if (RootContext.Documentation != null) ((Method) $$).DocComment = Lexer.consume_doc_comment (); } + | opt_attributes opt_new type namespace_or_type_name + OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + { + lexer.ConstraintsParsing = true; + } + opt_type_parameter_constraints_clauses + OPEN_BRACE opt_statement_list CLOSE_BRACE + { + lexer.ConstraintsParsing = false; + Report.Error (531, lexer.Location, "'{0}': interface members cannot have a definition", $4); + $$ = null; + } + ; interface_property_declaration @@ -1619,6 +1730,14 @@ interface_property_declaration { lexer.PropertyParsing = false; } CLOSE_BRACE { + if ($3 == TypeManager.system_void_expr) { + Report.Error (547, lexer.Location, "'{0}': property cannot have void type", $4); + break; + } + + if ($7 == null) + break; + InterfaceAccessorInfo pinfo = (InterfaceAccessorInfo) $7; $$ = new Property (current_class, (Expression) $3, (int) $2, true, @@ -1638,12 +1757,21 @@ interface_property_declaration interface_accessors : opt_attributes opt_modifiers GET SEMICOLON { $$ = new InterfaceAccessorInfo (true, false, (Attributes) $1, null, (int) $2, 0, lexer.Location, lexer.Location); } + | opt_attributes opt_modifiers GET OPEN_BRACE + { + Report.Error (531, lexer.Location, "'{0}': interface members cannot have a definition", ".get"); + $$ = null; + } | opt_attributes opt_modifiers SET SEMICOLON { $$ = new InterfaceAccessorInfo (false, true, null, (Attributes) $1, 0, (int) $2, lexer.Location, lexer.Location); } | opt_attributes opt_modifiers GET SEMICOLON opt_attributes opt_modifiers SET SEMICOLON { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $1, (Attributes) $5, (int) $2, (int) $6, lexer.Location, lexer.Location); } | opt_attributes opt_modifiers SET SEMICOLON opt_attributes opt_modifiers GET SEMICOLON { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $5, (Attributes) $1, (int) $6, (int) $2, lexer.Location, lexer.Location); } + | + { + Report.Error (548, lexer.Location, "'{0}' : property or indexer must have at least one accessor", ""); + } ; interface_event_declaration @@ -1663,8 +1791,16 @@ interface_event_declaration Report.Error (68, lexer.Location, "Event declarations on interfaces can not be initialized."); $$ = null; } - | opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE event_accessor_declarations CLOSE_BRACE { - Report.Error (69, lexer.Location, "Event accessors not valid on interfaces"); + | opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE + { + lexer.EventParsing = true; + } + event_accessor_declarations + { + lexer.EventParsing = false; + } + CLOSE_BRACE { + Report.Error (69, lexer.Location, "Event in interface cannot have add or remove accessors"); $$ = null; } ; @@ -1678,6 +1814,9 @@ interface_indexer_declaration { lexer.PropertyParsing = false; } CLOSE_BRACE { + if ($10 == null) + break; + InterfaceAccessorInfo info = (InterfaceAccessorInfo) $10; $$ = new Indexer (current_class, (Expression) $3, @@ -1696,17 +1835,20 @@ operator_declaration } operator_body { + if ($3 == null) + break; + OperatorDeclaration decl = (OperatorDeclaration) $3; Parameter [] param_list = new Parameter [decl.arg2type != null ? 2 : 1]; - param_list[0] = new Parameter (decl.arg1type, decl.arg1name, Parameter.Modifier.NONE, null); + param_list[0] = new Parameter (decl.arg1type, decl.arg1name, Parameter.Modifier.NONE, null, decl.location); if (decl.arg2type != null) - param_list[1] = new Parameter (decl.arg2type, decl.arg2name, Parameter.Modifier.NONE, null); + param_list[1] = new Parameter (decl.arg2type, decl.arg2name, Parameter.Modifier.NONE, null, decl.location); Operator op = new Operator ( current_class, decl.optype, decl.ret_type, (int) $2, - new Parameters (param_list, null, decl.location), + new Parameters (param_list, null), (ToplevelBlock) $5, (Attributes) $1, decl.location); if (RootContext.Documentation != null) { @@ -1745,9 +1887,9 @@ operator_declarator Parameter [] pars = new Parameter [1]; Expression type = (Expression) $5; - pars [0] = new Parameter (type, (string) $6, Parameter.Modifier.NONE, null); + pars [0] = new Parameter (type, (string) $6, Parameter.Modifier.NONE, null, lexer.Location); - current_local_parameters = new Parameters (pars, null, lexer.Location); + current_local_parameters = new Parameters (pars, null); if (RootContext.Documentation != null) { tmpComment = Lexer.consume_doc_comment (); @@ -1770,10 +1912,10 @@ operator_declarator Expression typeL = (Expression) $5; Expression typeR = (Expression) $8; - pars [0] = new Parameter (typeL, (string) $6, Parameter.Modifier.NONE, null); - pars [1] = new Parameter (typeR, (string) $9, Parameter.Modifier.NONE, null); + pars [0] = new Parameter (typeL, (string) $6, Parameter.Modifier.NONE, null, lexer.Location); + pars [1] = new Parameter (typeR, (string) $9, Parameter.Modifier.NONE, null, lexer.Location); - current_local_parameters = new Parameters (pars, null, lexer.Location); + current_local_parameters = new Parameters (pars, null); if (RootContext.Documentation != null) { tmpComment = Lexer.consume_doc_comment (); @@ -1785,6 +1927,22 @@ operator_declarator typeR, (string) $9, lexer.Location); } | conversion_operator_declarator + | type OPERATOR overloadable_operator + OPEN_PARENS + type IDENTIFIER COMMA + type IDENTIFIER COMMA + type IDENTIFIER + CLOSE_PARENS + { + Report.Error (1534, lexer.Location, "Overloaded binary operator '{0}' takes two parameters", $3); + $$ = null; + } + | type OPERATOR overloadable_operator + OPEN_PARENS CLOSE_PARENS + { + Report.Error (1535, lexer.Location, "Overloaded unary operator '{0}' takes one parameter", $3); + $$ = null; + } ; overloadable_operator @@ -1820,9 +1978,9 @@ conversion_operator_declarator { Parameter [] pars = new Parameter [1]; - pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null); + pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null, lexer.Location); - current_local_parameters = new Parameters (pars, null, lexer.Location); + current_local_parameters = new Parameters (pars, null); if (RootContext.Documentation != null) { tmpComment = Lexer.consume_doc_comment (); @@ -1836,9 +1994,9 @@ conversion_operator_declarator { Parameter [] pars = new Parameter [1]; - pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null); + pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null, lexer.Location); - current_local_parameters = new Parameters (pars, null, lexer.Location); + current_local_parameters = new Parameters (pars, null); if (RootContext.Documentation != null) { tmpComment = Lexer.consume_doc_comment (); @@ -1918,17 +2076,14 @@ constructor_declarator Lexer.doc_state = XmlCommentState.Allowed; } } - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS _mark_ { - oob_stack.Push (lexer.Location); - current_local_parameters = (Parameters) $4; } opt_constructor_initializer { - Location l = (Location) oob_stack.Pop (); $$ = new Constructor (current_class, (string) $1, 0, (Parameters) $4, - (ConstructorInitializer) $7, l); + (ConstructorInitializer) $8, (Location) $6); } ; @@ -1945,11 +2100,11 @@ opt_constructor_initializer constructor_initializer : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS { - $$ = new ConstructorBaseInitializer ((ArrayList) $4, current_local_parameters, lexer.Location); + $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location); } | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS { - $$ = new ConstructorThisInitializer ((ArrayList) $4, current_local_parameters, lexer.Location); + $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location); } | COLON error { Report.Error (1018, lexer.Location, "Keyword this or base expected"); @@ -1973,7 +2128,7 @@ destructor_declaration } IDENTIFIER OPEN_PARENS CLOSE_PARENS block { - if ((string) $5 != current_container.Basename){ + if ((string) $5 != current_container.MemberName.Name){ Report.Error (574, lexer.Location, "Name of destructor must match name of class"); } else if (current_container.Kind != Kind.Class){ Report.Error (575, lexer.Location, "Destructors are only allowed in class types"); @@ -1996,7 +2151,7 @@ destructor_declaration Method d = new Destructor ( current_class, TypeManager.system_void_expr, m, "Finalize", - new Parameters (null, null, l), (Attributes) $1, l); + new Parameters (null, null), (Attributes) $1, l); if (RootContext.Documentation != null) d.DocComment = ConsumeStoredComment (); @@ -2031,11 +2186,10 @@ event_declaration | opt_attributes opt_modifiers EVENT type namespace_or_type_name - OPEN_BRACE + OPEN_BRACE _mark_ { implicit_value_parameter_type = (Expression) $4; lexer.EventParsing = true; - oob_stack.Push (lexer.Location); } event_accessor_declarations { @@ -2043,13 +2197,13 @@ event_declaration } CLOSE_BRACE { - Location loc = (Location) oob_stack.Pop (); + Location loc = (Location) $7; - if ($8 == null){ + if ($9 == null){ Report.Error (65, lexer.Location, "Event must have both add and remove accesors"); $$ = null; } else { - Pair pair = (Pair) $8; + Pair pair = (Pair) $9; MemberName name = (MemberName) $5; @@ -2107,11 +2261,11 @@ add_accessor_declaration Parameter [] args = new Parameter [1]; Parameter implicit_value_parameter = new Parameter ( implicit_value_parameter_type, "value", - Parameter.Modifier.NONE, null); + Parameter.Modifier.NONE, null, lexer.Location); args [0] = implicit_value_parameter; - current_local_parameters = new Parameters (args, null, lexer.Location); + current_local_parameters = new Parameters (args, null); lexer.EventParsing = false; } block @@ -2123,6 +2277,10 @@ add_accessor_declaration Report.Error (73, lexer.Location, "Add or remove accessor must have a body"); $$ = null; } + | opt_attributes modifiers ADD { + Report.Error (1609, lexer.Location, "Modifiers cannot be placed on event accessor declarations"); + $$ = null; + } ; remove_accessor_declaration @@ -2131,11 +2289,11 @@ remove_accessor_declaration Parameter [] args = new Parameter [1]; Parameter implicit_value_parameter = new Parameter ( implicit_value_parameter_type, "value", - Parameter.Modifier.NONE, null); + Parameter.Modifier.NONE, null, lexer.Location); args [0] = implicit_value_parameter; - current_local_parameters = new Parameters (args, null, lexer.Location); + current_local_parameters = new Parameters (args, null); lexer.EventParsing = false; } block @@ -2147,11 +2305,15 @@ remove_accessor_declaration Report.Error (73, lexer.Location, "Add or remove accessor must have a body"); $$ = null; } + | opt_attributes modifiers REMOVE { + Report.Error (1609, lexer.Location, "Modifiers cannot be placed on event accessor declarations"); + $$ = null; + } ; indexer_declaration : opt_attributes opt_modifiers indexer_declarator - OPEN_BRACE + OPEN_BRACE _mark_ { IndexerDeclaration decl = (IndexerDeclaration) $3; @@ -2161,21 +2323,24 @@ indexer_declaration parsing_indexer = true; indexer_parameters = decl.param_list; - oob_stack.Push (lexer.Location); } accessor_declarations { lexer.PropertyParsing = false; + has_get = has_set = false; parsing_indexer = false; } CLOSE_BRACE { + if ($7 == null) + break; + // The signature is computed from the signature of the indexer. Look // at section 3.6 on the spec - Location loc = (Location) oob_stack.Pop (); + Location loc = (Location) $5; Indexer indexer; IndexerDeclaration decl = (IndexerDeclaration) $3; - Pair pair = (Pair) $6; + Pair pair = (Pair) $7; Accessor get_block = (Accessor) pair.First; Accessor set_block = (Accessor) pair.Second; @@ -2229,8 +2394,6 @@ indexer_declarator } MemberName name = (MemberName) $2; - if (name.TypeArguments != null) - syntax_error (lexer.Location, "an indexer can't have type arguments"); $$ = new IndexerDeclaration ((Expression) $1, name, pars); @@ -2244,6 +2407,7 @@ indexer_declarator enum_declaration : opt_attributes opt_modifiers + opt_partial ENUM IDENTIFIER opt_enum_base { if (RootContext.Documentation != null) @@ -2251,26 +2415,33 @@ enum_declaration } enum_body opt_semicolon - { + { + bool partial = (bool) $3; + + if (partial) { + Report.Error (267, lexer.Location, "The partial modifier can only appear before a 'class', 'struct', or 'interface'"); + break; // assumes that the parser put us in a switch + } + Location enum_location = lexer.Location; - MemberName full_name = MakeName (new MemberName ((string) $4)); - Enum e = new Enum (current_namespace, current_container, (Expression) $5, (int) $2, - full_name, (Attributes) $1, enum_location); + MemberName name = MakeName (new MemberName ((string) $5)); + Enum e = new Enum (current_namespace, current_class, (Expression) $6, (int) $2, + name, (Attributes) $1, enum_location); if (RootContext.Documentation != null) e.DocComment = enumTypeComment; - foreach (VariableDeclaration ev in (ArrayList) $7) { + foreach (VariableDeclaration ev in (ArrayList) $8) { e.AddEnumMember (ev.identifier, (Expression) ev.expression_or_array_initializer, ev.Location, ev.OptAttributes, ev.DocComment); } - string name = full_name.GetName (); current_container.AddEnum (e); RootContext.Tree.RecordDecl (name, e); + $$ = e; } ; @@ -2355,13 +2526,17 @@ enum_member_declaration delegate_declaration : opt_attributes opt_modifiers - DELEGATE type member_name + DELEGATE + { + lexer.ConstraintsParsing = true; + } + type member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { Location l = lexer.Location; - MemberName name = MakeName ((MemberName) $5); - Delegate del = new Delegate (current_namespace, current_container, (Expression) $4, - (int) $2, name, (Parameters) $7, (Attributes) $1, l); + MemberName name = MakeName ((MemberName) $6); + Delegate del = new Delegate (current_namespace, current_class, (Expression) $5, + (int) $2, name, (Parameters) $8, (Attributes) $1, l); if (RootContext.Documentation != null) { del.DocComment = Lexer.consume_doc_comment (); @@ -2369,11 +2544,9 @@ delegate_declaration } current_container.AddDelegate (del); - RootContext.Tree.RecordDecl (name.GetName (true), del); + RootContext.Tree.RecordDecl (name, del); current_delegate = del; - - lexer.ConstraintsParsing = true; } opt_type_parameter_constraints_clauses { @@ -2381,43 +2554,23 @@ delegate_declaration } SEMICOLON { - current_delegate.SetParameterInfo ((ArrayList) $9); + current_delegate.SetParameterInfo ((ArrayList) $10); + $$ = current_delegate; current_delegate = null; } - | opt_attributes - opt_modifiers - DELEGATE VOID member_name - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS - { - Location l = lexer.Location; - MemberName name = MakeName ((MemberName) $5); - Delegate del = new Delegate ( - current_namespace, current_container, - TypeManager.system_void_expr, (int) $2, name, - (Parameters) $7, (Attributes) $1, l); - - if (RootContext.Documentation != null) { - del.DocComment = Lexer.consume_doc_comment (); - Lexer.doc_state = XmlCommentState.Allowed; - } - - current_container.AddDelegate (del); - RootContext.Tree.RecordDecl (name.GetName (true), del); - - current_delegate = del; + ; - lexer.ConstraintsParsing = true; - } - opt_type_parameter_constraints_clauses +opt_nullable + : /* empty */ { - lexer.ConstraintsParsing = false; + lexer.CheckNullable (false); + $$ = false; } - SEMICOLON + | INTERR { - current_delegate.SetParameterInfo ((ArrayList) $9); - - current_delegate = null; + lexer.CheckNullable (true); + $$ = true; } ; @@ -2466,16 +2619,22 @@ type_arguments * gets rid of a shift/reduce couple */ type - : namespace_or_type_name + : namespace_or_type_name opt_nullable { $$ = ((MemberName) $1).GetTypeExpression (lexer.Location); + + if ((bool) $2) + $$ = new ComposedCast ((Expression) $$, "?", lexer.Location); + } + | builtin_types opt_nullable + { + if ((bool) $2) + $$ = new ComposedCast ((Expression) $1, "?", lexer.Location); } - | builtin_types | array_type - | pointer_type + | pointer_type ; - pointer_type : type STAR { @@ -2493,7 +2652,11 @@ pointer_type ; non_expression_type - : builtin_types + : builtin_types opt_nullable + { + if ((bool) $2) + $$ = new ComposedCast ((Expression) $1, "?", lexer.Location); + } | non_expression_type rank_specifier { $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location); @@ -2566,9 +2729,13 @@ integral_type ; array_type - : type rank_specifiers + : type rank_specifiers opt_nullable { - $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location); + string rank_specifiers = (string) $2; + if ((bool) $3) + rank_specifiers += "?"; + + $$ = new ComposedCast ((Expression) $1, rank_specifiers, lexer.Location); } ; @@ -2580,8 +2747,7 @@ primary_expression { // 7.5.1: Literals } - - | member_name + | member_name { $$ = ((MemberName) $1).GetTypeExpression (lexer.Location); } @@ -2706,6 +2872,18 @@ invocation_expression { $$ = new InvocationOrCast ((Expression) $1, (Expression) $3, lexer.Location); } + | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS non_simple_argument CLOSE_PARENS + { + ArrayList args = new ArrayList (1); + args.Add ($4); + $$ = new Invocation ((Expression) $1, args, lexer.Location); + } + | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS argument_list COMMA argument CLOSE_PARENS + { + ArrayList args = ((ArrayList) $4); + args.Add ($6); + $$ = new Invocation ((Expression) $1, args, lexer.Location); + } ; opt_argument_list @@ -2736,7 +2914,14 @@ argument { $$ = new Argument ((Expression) $1, Argument.AType.Expression); } - | REF variable_reference + | non_simple_argument + { + $$ = $1; + } + ; + +non_simple_argument + : REF variable_reference { $$ = new Argument ((Expression) $2, Argument.AType.Ref); } @@ -2891,6 +3076,31 @@ opt_rank_specifier } ; +opt_rank_specifier_or_nullable + : /* empty */ + { + $$ = ""; + } + | INTERR + { + $$ = "?"; + } + | opt_nullable rank_specifiers + { + if ((bool) $1) + $$ = "?" + $2; + else + $$ = $2; + } + | opt_nullable rank_specifiers INTERR + { + if ((bool) $1) + $$ = "?" + $2 + "?"; + else + $$ = $2 + "?"; + } + ; + rank_specifiers : rank_specifier opt_rank_specifier { @@ -3027,24 +3237,26 @@ pointer_member_access ; anonymous_method_expression - : DELEGATE opt_anonymous_method_signature { + : DELEGATE opt_anonymous_method_signature _mark_ + { oob_stack.Push (current_local_parameters); current_local_parameters = (Parameters)$2; // Force the next block to be created as a ToplevelBlock oob_stack.Push (current_block); oob_stack.Push (top_current_block); - oob_stack.Push (lexer.Location); current_block = null; - } block { - Location loc = (Location) oob_stack.Pop (); + } + block + { + Location loc = (Location) $3; top_current_block = (Block) oob_stack.Pop (); current_block = (Block) oob_stack.Pop (); - if (RootContext.Version == LanguageVersion.ISO_1){ + if (RootContext.Version == LanguageVersion.ISO_1){ Report.FeatureIsNotStandardized (lexer.Location, "anonymous methods"); $$ = null; } else { - ToplevelBlock anon_block = (ToplevelBlock) $4; + ToplevelBlock anon_block = (ToplevelBlock) $5; anon_block.Parent = current_block; $$ = new AnonymousMethod ((Parameters) $2, (ToplevelBlock) top_current_block, @@ -3068,7 +3280,7 @@ anonymous_method_signature ArrayList par_list = (ArrayList) $2; Parameter [] pars = new Parameter [par_list.Count]; par_list.CopyTo (pars); - $$ = new Parameters (pars, null, lexer.Location); + $$ = new Parameters (pars, null); } } ; @@ -3095,10 +3307,10 @@ anonymous_method_parameter_list anonymous_method_parameter : opt_parameter_modifier type IDENTIFIER { - $$ = new Parameter ((Expression) $2, (string) $3, (Parameter.Modifier) $1, null); + $$ = new Parameter ((Expression) $2, (string) $3, (Parameter.Modifier) $1, null, lexer.Location); } | PARAMS type IDENTIFIER { - Report.Error (-221, lexer.Location, "params modifier not allowed in anonymous method declaration"); + Report.Error (1670, lexer.Location, "params modifier not allowed in anonymous method declaration"); $$ = null; } ; @@ -3239,6 +3451,28 @@ shift_expression } ; +opt_error + : /* empty */ + { + $$ = false; + } + | error + { + lexer.PutbackNullable (); + $$ = true; + } + ; + +nullable_type_or_conditional + : type opt_error + { + if (((bool) $2) && ($1 is ComposedCast)) + $$ = ((ComposedCast) $1).RemoveNullable (); + else + $$ = $1; + } + ; + relational_expression : shift_expression | relational_expression OP_LT shift_expression @@ -3261,13 +3495,19 @@ relational_expression $$ = new Binary (Binary.Operator.GreaterThanOrEqual, (Expression) $1, (Expression) $3, lexer.Location); } - | relational_expression IS type + | relational_expression IS + { + yyErrorFlag = 3; + } nullable_type_or_conditional { - $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location); + $$ = new Is ((Expression) $1, (Expression) $4, lexer.Location); } - | relational_expression AS type + | relational_expression AS + { + yyErrorFlag = 3; + } nullable_type_or_conditional { - $$ = new As ((Expression) $1, (Expression) $3, lexer.Location); + $$ = new As ((Expression) $1, (Expression) $4, lexer.Location); } ; @@ -3336,6 +3576,16 @@ conditional_expression { $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location); } + | conditional_or_expression INTERR INTERR expression + { + $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $4, lexer.Location); + } + // We'll be resolved into a `parenthesized_expression_0' later on. + | conditional_or_expression INTERR CLOSE_PARENS + { + $$ = new ComposedCast ((Expression) $1, "?", lexer.Location); + lexer.PutbackCloseParens (); + } ; assignment_expression @@ -3435,15 +3685,19 @@ class_declaration : opt_attributes opt_modifiers opt_partial - CLASS member_name + CLASS + { + lexer.ConstraintsParsing = true; + } + member_name { - MemberName name = MakeName ((MemberName) $5); + MemberName name = MakeName ((MemberName) $6); bool partial = (bool) $3; int mod_flags = (int) $2; if (partial) { ClassPart part = PartialContainer.CreatePart ( - current_namespace, current_container, name, mod_flags, + current_namespace, current_class, name, mod_flags, (Attributes) $1, Kind.Class, lexer.Location); current_container = part.PartialContainer; @@ -3451,42 +3705,39 @@ class_declaration } else { if ((mod_flags & Modifiers.STATIC) != 0) { current_class = new StaticClass ( - current_namespace, current_container, name, + current_namespace, current_class, name, mod_flags, (Attributes) $1, lexer.Location); } else { current_class = new Class ( - current_namespace, current_container, name, + current_namespace, current_class, name, mod_flags, (Attributes) $1, lexer.Location); } + current_container.AddClassOrStruct (current_class); current_container = current_class; - RootContext.Tree.RecordDecl (name.GetName (true), current_class); + RootContext.Tree.RecordDecl (name, current_class); } - - lexer.ConstraintsParsing = true; } opt_class_base opt_type_parameter_constraints_clauses { lexer.ConstraintsParsing = false; - if ($7 != null) { + if ($8 != null) { if (current_class.Name == "System.Object") { Report.Error (537, current_class.Location, "The class System.Object cannot have a base " + "class or implement an interface."); } - current_class.Bases = (ArrayList) $7; + current_class.Bases = (ArrayList) $8; } - current_class.SetParameterInfo ((ArrayList) $8); + current_class.SetParameterInfo ((ArrayList) $9); if (RootContext.Documentation != null) { current_class.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } - - current_class.Register (); } class_body { @@ -3495,10 +3746,7 @@ class_declaration } opt_semicolon { - $$ = current_class; - - current_container = current_container.Parent; - current_class = current_container; + $$ = pop_current_class (); } ; @@ -3628,8 +3876,7 @@ block current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location); top_current_block = current_block; } else { - current_block = new Block (current_block, current_local_parameters, - lexer.Location, Location.Null); + current_block = new Block (current_block, lexer.Location, Location.Null); } } opt_statement_list CLOSE_BRACE @@ -3744,7 +3991,7 @@ declaration_statement * > The expressions are converted into types during semantic analysis. */ local_variable_type - : primary_expression opt_rank_specifier + : primary_expression opt_rank_specifier_or_nullable { // FIXME: Do something smart here regarding the composition of the type. @@ -3778,7 +4025,7 @@ local_variable_type $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location); } } - | builtin_types opt_rank_specifier + | builtin_types opt_rank_specifier_or_nullable { if ((string) $2 == "") $$ = $1; @@ -3822,7 +4069,7 @@ local_variable_declaration else $$ = null; } - | local_variable_pointer_type opt_rank_specifier variable_declarators + | local_variable_pointer_type opt_rank_specifier_or_nullable variable_declarators { if ($1 != null){ Expression t; @@ -3883,52 +4130,37 @@ selection_statement ; if_statement - : if_statement_open if_statement_rest - { - $$ = $2; - } - ; - -if_statement_open - : IF OPEN_PARENS - { - oob_stack.Push (lexer.Location); - } - ; - -if_statement_rest - : boolean_expression CLOSE_PARENS + : IF OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS embedded_statement { - Location l = (Location) oob_stack.Pop (); + Location l = (Location) $3; - $$ = new If ((Expression) $1, (Statement) $3, l); + $$ = new If ((Expression) $4, (Statement) $6, l); if (RootContext.WarningLevel >= 4){ - if ($3 == EmptyStatement.Value) + if ($6 == EmptyStatement.Value) Report.Warning (642, lexer.Location, "Possible mistaken empty statement"); } } - | boolean_expression CLOSE_PARENS + | IF OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement { - Location l = (Location) oob_stack.Pop (); + Location l = (Location) $3; - $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l); + $$ = new If ((Expression) $4, (Statement) $6, (Statement) $8, l); } ; switch_statement - : SWITCH OPEN_PARENS + : SWITCH OPEN_PARENS _mark_ { - oob_stack.Push (lexer.Location); switch_stack.Push (current_block); } expression CLOSE_PARENS switch_block { - $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ()); + $$ = new Switch ((Expression) $5, (ArrayList) $7, (Location) $3); current_block = (Block) switch_stack.Pop (); } ; @@ -4017,13 +4249,9 @@ iteration_statement ; while_statement - : WHILE OPEN_PARENS - { - oob_stack.Push (lexer.Location); - } - boolean_expression CLOSE_PARENS embedded_statement + : WHILE OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS embedded_statement { - Location l = (Location) oob_stack.Pop (); + Location l = (Location) $3; $$ = new While ((Expression) $4, (Statement) $6, l); if (RootContext.WarningLevel >= 4){ @@ -4035,12 +4263,9 @@ while_statement do_statement : DO embedded_statement - WHILE OPEN_PARENS { - oob_stack.Push (lexer.Location); - } - boolean_expression CLOSE_PARENS SEMICOLON + WHILE OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS SEMICOLON { - Location l = (Location) oob_stack.Pop (); + Location l = (Location) $5; $$ = new Do ((Statement) $2, (Expression) $6, l); } @@ -4048,7 +4273,7 @@ do_statement for_statement : FOR OPEN_PARENS - opt_for_initializer SEMICOLON + opt_for_initializer SEMICOLON _mark_ { Block assign_block = new Block (current_block); current_block = assign_block; @@ -4063,8 +4288,7 @@ for_statement LocalInfo vi; - vi = current_block.AddVariable ( - type, decl.identifier, current_local_parameters, decl.Location); + vi = current_block.AddVariable (type, decl.identifier, decl.Location); if (vi == null) continue; @@ -4089,20 +4313,23 @@ for_statement } } - $3 = null; - } - oob_stack.Push (lexer.Location); + // Note: the $$ below refers to the value of this code block, not of the LHS non-terminal. + // This can be referred to as $6 below. + $$ = null; + } else { + $$ = $3; + } } opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement { - Location l = (Location) oob_stack.Pop (); + Location l = (Location) $5; - For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l); + For f = new For ((Statement) $6, (Expression) $7, (Statement) $9, (Statement) $11, l); if (RootContext.WarningLevel >= 4){ - if ($10 == EmptyStatement.Value) + if ($11 == EmptyStatement.Value) Report.Warning (642, lexer.Location, "Possible mistaken empty statement"); } @@ -4157,46 +4384,47 @@ statement_expression_list ; foreach_statement - : FOREACH OPEN_PARENS type IDENTIFIER IN - { - oob_stack.Push (lexer.Location); - } + : FOREACH OPEN_PARENS type IN expression CLOSE_PARENS + { + Report.Error (230, lexer.Location, "Type and identifier are both required in a foreach statement"); + $$ = null; + } + | FOREACH OPEN_PARENS type IDENTIFIER IN _mark_ expression CLOSE_PARENS { - oob_stack.Push (current_block); - Block foreach_block = new Block (current_block); - LocalVariableReference v = null; + current_block = foreach_block; + Location l = lexer.Location; LocalInfo vi; - vi = foreach_block.AddVariable ((Expression) $3, (string) $4, current_local_parameters, l); + vi = foreach_block.AddVariable ((Expression) $3, (string) $4, l); if (vi != null) { - vi.ReadOnly = true; + vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Foreach); // Get a writable reference to this read-only variable. - v = new LocalVariableReference (foreach_block, (string) $4, l, vi, false); + // + // Note that the $$ here refers to the value of _this_ code block, + // not the value of the LHS non-terminal. This can be referred to as $9 below. + $$ = new LocalVariableReference (foreach_block, (string) $4, l, vi, false); + } else { + $$ = null; } - current_block = foreach_block; - - oob_stack.Push (v); - oob_stack.Push (current_block); } embedded_statement { - Block foreach_block = (Block) oob_stack.Pop (); - LocalVariableReference v = (LocalVariableReference) oob_stack.Pop (); - Block prev_block = (Block) oob_stack.Pop (); - Location l = (Location) oob_stack.Pop (); - - current_block = prev_block; + LocalVariableReference v = (LocalVariableReference) $9; + Location l = (Location) $6; if (v != null) { Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l); - foreach_block.AddStatement (f); + current_block.AddStatement (f); } - $$ = foreach_block; + while (current_block.Implicit) + current_block = current_block.Parent; + $$ = current_block; + current_block = current_block.Parent; } ; @@ -4226,7 +4454,7 @@ continue_statement goto_statement : GOTO IDENTIFIER SEMICOLON { - $$ = new Goto (current_block, (string) $2, lexer.Location); + $$ = new Goto ((string) $2, lexer.Location); } | GOTO CASE constant_expression SEMICOLON { @@ -4272,6 +4500,11 @@ yield_statement $$ = new Yield ((Expression) $3, lexer.Location); } } + | IDENTIFIER RETURN SEMICOLON + { + Report.Error (1627, lexer.Location, "Expression expected after yield return"); + $$ = null; + } | IDENTIFIER BREAK SEMICOLON { string s = (string) $1; @@ -4387,7 +4620,6 @@ catch_clause one.Add (new VariableDeclaration (id, null, loc)); - $1 = current_block; current_block = new Block (current_block); Block b = declare_local_variables (type, one, loc); current_block = b; @@ -4402,17 +4634,14 @@ catch_clause type = (Expression) cc.Key; id = (string) cc.Value; - if ($1 != null){ - // - // FIXME: I can change this for an assignment. - // - while (current_block != (Block) $1) + if (id != null){ + while (current_block.Implicit) current_block = current_block.Parent; + current_block = current_block.Parent; } } - - $$ = new Catch (type, id , (Block) $4, ((Block) $4).loc); + $$ = new Catch (type, id, (Block) $4, ((Block) $4).loc); } ; @@ -4447,7 +4676,7 @@ unsafe_statement { if (!RootContext.Unsafe){ Report.Error (227, lexer.Location, - "Unsafe code can only be used if --unsafe is used"); + "Unsafe code can only be used if -unsafe is used"); } } block { $$ = new Unsafe ((Block) $3); @@ -4457,7 +4686,7 @@ unsafe_statement fixed_statement : FIXED OPEN_PARENS type fixed_pointer_declarators - CLOSE_PARENS + CLOSE_PARENS _mark_ { ArrayList list = (ArrayList) $4; Expression type = (Expression) $3; @@ -4471,26 +4700,24 @@ fixed_statement Pair p = (Pair) list [i]; LocalInfo v; - v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l); + v = current_block.AddVariable (type, (string) p.First, l); if (v == null) continue; - v.ReadOnly = true; + v.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed); v.Pinned = true; p.First = v; list [i] = p; } - - oob_stack.Push (l); } embedded_statement { - Location l = (Location) oob_stack.Pop (); + Location l = (Location) $6; - Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l); + Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $8, l); if (RootContext.WarningLevel >= 4){ - if ($7 == EmptyStatement.Value) + if ($8 == EmptyStatement.Value) Report.Warning (642, lexer.Location, "Possible mistaken empty statement"); } @@ -4542,13 +4769,11 @@ lock_statement ; using_statement - : USING OPEN_PARENS resource_acquisition CLOSE_PARENS + : USING OPEN_PARENS resource_acquisition CLOSE_PARENS _mark_ { Block assign_block = new Block (current_block); current_block = assign_block; - oob_stack.Push (lexer.Location); - if ($3 is DictionaryEntry){ DictionaryEntry de = (DictionaryEntry) $3; Location l = lexer.Location; @@ -4560,12 +4785,10 @@ using_statement foreach (VariableDeclaration decl in var_declarators){ - LocalInfo vi = current_block.AddVariable ( - type, decl.identifier, - current_local_parameters, decl.Location); + LocalInfo vi = current_block.AddVariable (type, decl.identifier, decl.Location); if (vi == null) continue; - vi.ReadOnly = true; + vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Using); Expression expr; if (decl.expression_or_array_initializer is Expression){ @@ -4592,12 +4815,17 @@ using_statement // Assign a = new Assign (var, expr, decl.Location); // assign_block.AddStatement (new StatementExpression (a, lexer.Location)); } - $3 = new DictionaryEntry (type, vars); + + // Note: the $$ here refers to the value of this code block and not of the LHS non-terminal. + // It can be referred to as $6 below. + $$ = new DictionaryEntry (type, vars); + } else { + $$ = $3; } } embedded_statement { - Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ()); + Using u = new Using ($6, (Statement) $7, (Location) $5); current_block.AddStatement (u); while (current_block.Implicit) current_block = current_block.Parent; @@ -4611,6 +4839,11 @@ resource_acquisition | expression ; +// Utility rule to save location information +_mark_ + : /* empty */ + { $$ = lexer.Location; } + %% // @@ -4729,6 +4962,23 @@ void Error_ExpectingTypeName (Location l, Expression expr) } } +TypeContainer pop_current_class () +{ + TypeContainer retval = current_class; + + current_class = current_class.Parent; + current_container = current_container.Parent; + + if (current_class != current_container) { + if (!(current_class is ClassPart) || + ((ClassPart) current_class).PartialContainer != current_container) + throw new InternalErrorException (); + } else if (current_container is ClassPart) + current_container = ((ClassPart) current_class).PartialContainer; + + return retval; +} + // // Given the @class_name name, it creates a fully qualified name // based on the containing declaration space @@ -4736,11 +4986,11 @@ void Error_ExpectingTypeName (Location l, Expression expr) MemberName MakeName (MemberName class_name) { - string ns = current_namespace.FullName; + Namespace ns = current_namespace.NS; if (current_container.Name == ""){ - if (ns != "") - return new MemberName (new MemberName (ns), class_name); + if (ns.Name != "") + return new MemberName (ns.MemberName, class_name); else return class_name; } else { @@ -4768,11 +5018,14 @@ Block declare_local_variables (Expression type, ArrayList variable_declarators, // // int j = 1; int k = j + 1; // - implicit_block = current_block; + if (current_block.Used) + implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null); + else + implicit_block = current_block; foreach (VariableDeclaration decl in variable_declarators){ - if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) { + if (implicit_block.AddVariable (type, decl.identifier, decl.Location) != null) { if (decl.expression_or_array_initializer != null){ if (inits == null) inits = new ArrayList (4); @@ -4818,8 +5071,7 @@ Block declare_local_constants (Expression type, ArrayList declarators) implicit_block = current_block; foreach (VariableDeclaration decl in declarators){ - implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer, - current_local_parameters, decl.Location); + implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer, decl.Location); } return implicit_block; @@ -4898,11 +5150,6 @@ void syntax_error (Location l, string msg) Report.Error (1003, l, "Syntax error, " + msg); } -void output (string s) -{ - Console.WriteLine (s); -} - void note (string s) { // Used to put annotations @@ -4922,6 +5169,8 @@ public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList def this.name = file.Name; this.file = file; current_container = RootContext.Tree.Types; + // TODO: Make RootContext.Tree.Types a PartialContainer. + current_class = current_container; current_container.NamespaceEntry = current_namespace; oob_stack = new Stack (); switch_stack = new Stack (); @@ -4937,7 +5186,7 @@ public void parse () else yyparse (lexer); Tokenizer tokenizer = lexer as Tokenizer; - tokenizer.cleanup (); + tokenizer.cleanup (); } catch (Exception e){ // // Removed for production use, use parser verbose to get the output. @@ -4947,6 +5196,8 @@ public void parse () if (yacc_verbose_flag > 0) Console.WriteLine (e); } + + RootContext.Tree.Types.NamespaceEntry = null; } void CheckToken (int error, int yyToken, string msg)