X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fcs-parser.jay;h=807588e532597d94b4b928874de9a3464e7ec311;hb=7d956e0d400f0b42f824d0ea2c1f13fe65360a22;hp=397f9642b5731019c34619aa87089872fc76a103;hpb=3f71f2eb719e3d134895a520c9027799ff9ebb63;p=mono.git diff --git a/mcs/gmcs/cs-parser.jay b/mcs/gmcs/cs-parser.jay index 397f9642b57..807588e5325 100644 --- a/mcs/gmcs/cs-parser.jay +++ b/mcs/gmcs/cs-parser.jay @@ -33,9 +33,9 @@ namespace Mono.CSharp public class CSharpParser { NamespaceEntry current_namespace; TypeContainer current_container; - TypeContainer current_class; + DeclSpace current_class; - IIteratorContainer iterator_container; + IAnonymousHost anonymous_host; /// /// Current block is used to add statements as we find @@ -45,6 +45,9 @@ namespace Mono.CSharp Delegate current_delegate; + GenericMethod current_generic_method; + AnonymousMethodExpression current_anonymous_method; + /// /// This is used by the unary_expression code to resolve /// a name against a parameter. @@ -63,12 +66,15 @@ namespace Mono.CSharp /// Hack to help create non-typed array initializer /// public static Expression current_array_type; + Expression pushed_current_array_type; /// /// Used to determine if we are parsing the get/set pair /// of an indexer or a property /// - bool parsing_indexer; + bool parsing_indexer; + + bool parsing_anonymous_method; /// /// An out-of-band stack. @@ -400,11 +406,15 @@ namespace_declaration syntax_error (lexer.Location, "namespace name expected"); current_namespace = new NamespaceEntry ( - current_namespace, file, name.GetName (), name.Location); + current_namespace, file, name.GetName ()); + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; } namespace_body opt_semicolon { current_namespace = current_namespace.Parent; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; } ; @@ -783,16 +793,9 @@ struct_declaration member_name { MemberName name = MakeName ((MemberName) $6); - current_class = new Struct ( + push_current_class (new Struct ( current_namespace, current_class, name, (int) $2, - (Attributes) $1); - - if ($3 != null) { - current_container = current_container.AddPartial (current_class); - } else { - current_container.AddClassOrStruct (current_class); - current_container = current_class; - } + (Attributes) $1), false, $3); } opt_class_base opt_type_parameter_constraints_clauses @@ -800,7 +803,7 @@ struct_declaration lexer.ConstraintsParsing = false; if ($8 != null) - current_class.Bases = (ArrayList) $8; + current_container.AddBasesForPart (current_class, (ArrayList) $8); current_class.SetParameterInfo ((ArrayList) $9); @@ -1051,6 +1054,10 @@ variable_initializer { $$ = new StackAlloc ((Expression) $2, (Expression) $4, (Location) $1); } + | ARGLIST + { + $$ = new ArglistAccess ((Location) $1); + } | STACKALLOC type { Report.Error (1575, (Location) $1, "A stackalloc expression requires [] after type"); @@ -1060,7 +1067,7 @@ variable_initializer method_declaration : method_header { - iterator_container = (IIteratorContainer) $1; + anonymous_host = (IAnonymousHost) $1; if (RootContext.Documentation != null) Lexer.doc_state = XmlCommentState.NotAllowed; } @@ -1070,8 +1077,9 @@ method_declaration method.Block = (ToplevelBlock) $3; current_container.AddMethod (method); + anonymous_host = null; + current_generic_method = null; current_local_parameters = null; - iterator_container = null; if (RootContext.Documentation != null) Lexer.doc_state = XmlCommentState.Allowed; @@ -1128,7 +1136,9 @@ method_header method = new Method (current_class, generic, (Expression) $3, (int) $2, false, name, (Parameters) $6, (Attributes) $1); + anonymous_host = method; current_local_parameters = (Parameters) $6; + current_generic_method = generic; if (RootContext.Documentation != null) method.DocComment = Lexer.consume_doc_comment (); @@ -1164,7 +1174,9 @@ method_header method = new Method (current_class, generic, TypeManager.system_void_expr, (int) $2, false, name, (Parameters) $6, (Attributes) $1); + anonymous_host = method; current_local_parameters = (Parameters) $6; + current_generic_method = generic; if (RootContext.Documentation != null) method.DocComment = Lexer.consume_doc_comment (); @@ -1238,11 +1250,22 @@ formal_parameter_list Report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list"); $$ = null; } + | fixed_parameters COMMA parameter_array COMMA error + { + if ($3 != null) + Report.Error (231, ((Parameter) $3).Location, "A params parameter must be the last parameter in a formal parameter list"); + $$ = null; + } | ARGLIST COMMA error { Report.Error (257, (Location) $1, "An __arglist parameter must be the last parameter in a formal parameter list"); $$ = null; } + | fixed_parameters COMMA ARGLIST COMMA error + { + Report.Error (257, (Location) $3, "An __arglist parameter must be the last parameter in a formal parameter list"); + $$ = null; + } | parameter_array { $$ = new Parameters (new Parameter[] { (Parameter) $1 } ); @@ -1429,7 +1452,7 @@ get_accessor_declaration current_local_parameters = indexer_parameters; lexer.PropertyParsing = false; - iterator_container = SimpleIteratorContainer.GetSimple (); + anonymous_host = SimpleAnonymousHost.GetSimple (); } accessor_body { @@ -1442,10 +1465,8 @@ get_accessor_declaration current_local_parameters = null; lexer.PropertyParsing = true; - if (SimpleIteratorContainer.Simple.Yields) - accessor.SetYields (); - - iterator_container = null; + SimpleAnonymousHost.Simple.Propagate (accessor); + anonymous_host = null; if (RootContext.Documentation != null) if (Lexer.doc_state == XmlCommentState.Error) @@ -1484,7 +1505,7 @@ set_accessor_declaration lexer.PropertyParsing = false; - iterator_container = SimpleIteratorContainer.GetSimple (); + anonymous_host = SimpleAnonymousHost.GetSimple (); } accessor_body { @@ -1497,10 +1518,8 @@ set_accessor_declaration current_local_parameters = null; lexer.PropertyParsing = true; - if (SimpleIteratorContainer.Simple.Yields) - accessor.SetYields (); - - iterator_container = null; + SimpleAnonymousHost.Simple.Propagate (accessor); + anonymous_host = null; if (RootContext.Documentation != null && Lexer.doc_state == XmlCommentState.Error) @@ -1527,16 +1546,9 @@ interface_declaration { MemberName name = MakeName ((MemberName) $6); - current_class = new Interface ( + push_current_class (new Interface ( current_namespace, current_class, name, (int) $2, - (Attributes) $1); - - if ($3 != null) { - current_container = current_container.AddPartial (current_class); - } else { - current_container.AddInterface (current_class); - current_container = current_class; - } + (Attributes) $1), true, $3); } opt_class_base opt_type_parameter_constraints_clauses @@ -1544,7 +1556,7 @@ interface_declaration lexer.ConstraintsParsing = false; if ($8 != null) - current_class.Bases = (ArrayList) $8; + current_container.AddBasesForPart (current_class, (ArrayList) $8); current_class.SetParameterInfo ((ArrayList) $9); @@ -1925,7 +1937,7 @@ interface_indexer_declaration operator_declaration : opt_attributes opt_modifiers operator_declarator { - iterator_container = SimpleIteratorContainer.GetSimple (); + anonymous_host = SimpleAnonymousHost.GetSimple (); } operator_body { @@ -1950,14 +1962,13 @@ operator_declaration Lexer.doc_state = XmlCommentState.Allowed; } - if (SimpleIteratorContainer.Simple.Yields) - op.SetYields (); + SimpleAnonymousHost.Simple.Propagate (op); + anonymous_host = null; // Note again, checking is done in semantic analysis current_container.AddOperator (op); current_local_parameters = null; - iterator_container = null; } ; @@ -2146,11 +2157,6 @@ constructor_declaration "`{0}': static constructor cannot have an explicit `this' or `base' constructor call", c.GetSignatureForError ()); } - - if (!c.Parameters.Empty){ - Report.Error (132, c.Location, - "`{0}': The static constructor must be parameterless", c.GetSignatureForError ()); - } } else { c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location); } @@ -2184,6 +2190,8 @@ constructor_declarator LocatedToken lt = (LocatedToken) $1; $$ = new Constructor (current_class, lt.Value, 0, (Parameters) $4, (ConstructorInitializer) $7, lt.Location); + + anonymous_host = (IAnonymousHost) $$; } ; @@ -2422,7 +2430,7 @@ indexer_declaration parsing_indexer = true; indexer_parameters = decl.param_list; - iterator_container = SimpleIteratorContainer.GetSimple (); + anonymous_host = SimpleAnonymousHost.GetSimple (); } accessor_declarations { @@ -2543,7 +2551,6 @@ enum_declaration } current_container.AddEnum (e); - RootContext.Tree.RecordDecl (current_namespace.NS, name, e); $$ = e; } @@ -2638,8 +2645,14 @@ delegate_declaration OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { MemberName name = MakeName ((MemberName) $6); + Parameters p = (Parameters) $8; + if (p.HasArglist) { + // TODO: wrong location + Report.Error (1669, name.Location, "__arglist is not valid in this context"); + } + Delegate del = new Delegate (current_namespace, current_class, (Expression) $5, - (int) $2, name, (Parameters) $8, (Attributes) $1); + (int) $2, name, p, (Attributes) $1); if (RootContext.Documentation != null) { del.DocComment = Lexer.consume_doc_comment (); @@ -2647,8 +2660,6 @@ delegate_declaration } current_container.AddDelegate (del); - RootContext.Tree.RecordDecl (current_namespace.NS, name, del); - current_delegate = del; } opt_type_parameter_constraints_clauses @@ -2953,9 +2964,9 @@ parenthesized_expression_0 : OPEN_PARENS expression CLOSE_PARENS { $$ = $2; - lexer.Deambiguate_CloseParens (); + lexer.Deambiguate_CloseParens ($$); // After this, the next token returned is one of - // CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST, CLOSE_PARENS_OPEN_PARENS + // CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST (CLOSE_PARENS), CLOSE_PARENS_OPEN_PARENS // or CLOSE_PARENS_MINUS. } | OPEN_PARENS expression error { CheckToken (1026, yyToken, "Expecting ')'", lexer.Location); } @@ -2965,7 +2976,11 @@ parenthesized_expression : parenthesized_expression_0 CLOSE_PARENS_NO_CAST { $$ = $1; - } + } + | parenthesized_expression_0 CLOSE_PARENS + { + $$ = $1; + } | parenthesized_expression_0 CLOSE_PARENS_MINUS { // If a parenthesized expression is followed by a minus, we need to wrap @@ -2979,14 +2994,13 @@ member_access : primary_expression DOT IDENTIFIER opt_type_argument_list { LocatedToken lt = (LocatedToken) $3; - $$ = new MemberAccess ((Expression) $1, lt.Value, - (TypeArguments) $4, lt.Location); + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); } | predefined_type DOT IDENTIFIER opt_type_argument_list { LocatedToken lt = (LocatedToken) $3; - $$ = new MemberAccess ((Expression) $1, lt.Value, - (TypeArguments) $4, lt.Location); + // TODO: Location is wrong as some predefined types doesn't hold a location + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); } ; @@ -3317,34 +3331,21 @@ variable_initializer_list } ; -void_pointer_expression - : void_pointer_expression STAR - { - $$ = new ComposedCast ((Expression) $1, "*", lexer.Location); - } - | VOID STAR - { - $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);; - } - ; - typeof_expression - : TYPEOF OPEN_PARENS VOID CLOSE_PARENS - { - $$ = new TypeOfVoid ((Location) $1); + : TYPEOF + { + pushed_current_array_type = current_array_type; + lexer.TypeOfParsing = true; } - | TYPEOF OPEN_PARENS void_pointer_expression CLOSE_PARENS + OPEN_PARENS type CLOSE_PARENS { - $$ = new TypeOf ((Expression) $3, (Location) $1); - } - | TYPEOF OPEN_PARENS - { - lexer.TypeOfParsing = true; - } - type CLOSE_PARENS - { - lexer.TypeOfParsing = false; - $$ = new TypeOf ((Expression) $4, lexer.Location); + lexer.TypeOfParsing = false; + Expression type = (Expression)$4; + if (type == TypeManager.system_void_expr) + $$ = new TypeOfVoid ((Location) $1); + else + $$ = new TypeOf (type, (Location) $1); + current_array_type = pushed_current_array_type; } ; @@ -3375,26 +3376,37 @@ pointer_member_access LocatedToken lt = (LocatedToken) $3; deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lt.Location); - $$ = new MemberAccess (deref, lt.Value, lt.Location); + $$ = new MemberAccess (deref, lt.Value); } ; anonymous_method_expression : DELEGATE opt_anonymous_method_signature { + if (oob_stack == null) + oob_stack = new Stack (6); + + oob_stack.Push (current_anonymous_method); 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); - current_block = null; - } + + Location loc = (Location) $1; + current_anonymous_method = new AnonymousMethodExpression ( + current_anonymous_method, current_generic_method, current_container, + (Parameters) $2, (ToplevelBlock) top_current_block, loc); + + parsing_anonymous_method = true; + } block { Location loc = (Location) $1; top_current_block = (Block) oob_stack.Pop (); current_block = (Block) oob_stack.Pop (); + if (RootContext.Version == LanguageVersion.ISO_1){ Report.FeatureIsNotStandardized (loc, "anonymous methods"); $$ = null; @@ -3402,11 +3414,17 @@ anonymous_method_expression ToplevelBlock anon_block = (ToplevelBlock) $4; anon_block.Parent = current_block; - $$ = new AnonymousMethod (current_container, (Parameters) $2, (ToplevelBlock) top_current_block, - anon_block, loc); - } - current_local_parameters = (Parameters) oob_stack.Pop (); + + current_anonymous_method.Block = anon_block; + if ((anonymous_host != null) && (current_anonymous_method.Parent == null)) + anonymous_host.AddAnonymousMethod (current_anonymous_method); + + $$ = current_anonymous_method; } + + current_local_parameters = (Parameters) oob_stack.Pop (); + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + } ; opt_anonymous_method_signature @@ -3484,6 +3502,10 @@ cast_list { $$ = new Cast ((Expression) $1, (Expression) $3); } + | parenthesized_expression_0 CLOSE_PARENS_NO_CAST default_value_expression + { + $$ = new Cast ((Expression) $1, (Expression) $3); + } | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression { $$ = new Cast ((Expression) $1, (Expression) $3); @@ -3819,16 +3841,9 @@ class_declaration MemberName name = MakeName ((MemberName) $6); int mod_flags = (int) $2; - current_class = new Class ( + push_current_class (new Class ( current_namespace, current_class, name, - mod_flags, (Attributes) $1); - - if ($3 != null) { - current_container = current_container.AddPartial (current_class); - } else { - current_container.AddClassOrStruct (current_class); - current_container = current_class; - } + mod_flags, (Attributes) $1), false, $3); } opt_class_base opt_type_parameter_constraints_clauses @@ -3841,7 +3856,7 @@ class_declaration "The class System.Object cannot have a base " + "class or implement an interface."); } - current_class.Bases = (ArrayList) $8; + current_container.AddBasesForPart (current_class, (ArrayList) $8); } current_class.SetParameterInfo ((ArrayList) $9); @@ -3929,8 +3944,16 @@ type_parameter_constraints_clauses } | type_parameter_constraints_clauses type_parameter_constraints_clause { ArrayList constraints = (ArrayList) $1; + Constraints new_constraint = (Constraints)$2; + + foreach (Constraints c in constraints) { + if (new_constraint.TypeParameter == c.TypeParameter) { + Report.Error (409, new_constraint.Location, "A constraint clause has already been specified for type parameter `{0}'", + new_constraint.TypeParameter); + } + } - constraints.Add ($2); + constraints.Add (new_constraint); $$ = constraints; } ; @@ -3985,8 +4008,18 @@ type_parameter_constraint block : OPEN_BRACE { - if (current_block == null){ - current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, (Location) $1); + if (parsing_anonymous_method) { + top_current_block = new ToplevelBlock ( + current_block, current_local_parameters, current_generic_method, + (Location) $1); + if (current_block != null) + current_block.AddAnonymousChild ((ToplevelBlock) top_current_block); + current_block = top_current_block; + parsing_anonymous_method = false; + } else if (current_block == null) { + current_block = new ToplevelBlock ( + (ToplevelBlock) top_current_block, current_local_parameters, + current_generic_method, (Location) $1); top_current_block = current_block; } else { current_block = new Block (current_block, (Location) $1, Location.Null); @@ -4072,7 +4105,7 @@ labeled_statement LocatedToken lt = (LocatedToken) $1; LabeledStatement labeled = new LabeledStatement (lt.Value, lt.Location); - if (current_block.AddLabel (lt.Value, labeled, lt.Location)) + if (current_block.AddLabel (labeled)) current_block.AddStatement (labeled); } statement @@ -4277,6 +4310,8 @@ if_statement switch_statement : SWITCH OPEN_PARENS { + if (switch_stack == null) + switch_stack = new Stack (2); switch_stack.Push (current_block); } expression CLOSE_PARENS @@ -4299,7 +4334,8 @@ switch_block opt_switch_sections : /* empty */ { - Report.Error (1522, lexer.Location, "Empty switch block"); + Report.Warning (1522, 1, lexer.Location, "Empty switch block"); + $$ = new ArrayList (); } | switch_sections ; @@ -4600,11 +4636,11 @@ yield_statement Report.FeatureIsNotStandardized (lt.Location, "yield statement"); $$ = null; } - if (iterator_container == null){ + if (anonymous_host == null){ Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property"); $$ = null; } else { - iterator_container.SetYields (); + anonymous_host.SetYields (); $$ = new Yield ((Expression) $3, lt.Location); } } @@ -4625,11 +4661,11 @@ yield_statement Report.FeatureIsNotStandardized (lt.Location, "yield statement"); $$ = null; } - if (iterator_container == null){ + if (anonymous_host == null){ Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property"); $$ = null; } else { - iterator_container.SetYields (); + anonymous_host.SetYields (); $$ = new YieldBreak (lt.Location); } } @@ -4990,22 +5026,41 @@ public class IndexerDeclaration { } // -// We use this when we do not have an object in advance that is an IIteratorContainer +// We use this when we do not have an object in advance that is an IAnonymousHost // -public class SimpleIteratorContainer : IIteratorContainer { - public bool Yields; +public class SimpleAnonymousHost : IAnonymousHost { + public static readonly SimpleAnonymousHost Simple = new SimpleAnonymousHost (); - public static SimpleIteratorContainer Simple = new SimpleIteratorContainer (); + bool yields; + ArrayList anonymous_methods; - // - // Reset and return - // - public static SimpleIteratorContainer GetSimple () { - Simple.Yields = false; + public static SimpleAnonymousHost GetSimple () { + Simple.yields = false; + Simple.anonymous_methods = null; return Simple; } - public void SetYields () { Yields = true; } + public void SetYields () + { + yields = true; + } + + public void AddAnonymousMethod (AnonymousMethodExpression anonymous) + { + if (anonymous_methods == null) + anonymous_methods = new ArrayList (); + anonymous_methods.Add (anonymous); + } + + public void Propagate (IAnonymousHost real_host) + { + if (yields) + real_host.SetYields (); + if (anonymous_methods != null) { + foreach (AnonymousMethodExpression ame in anonymous_methods) + real_host.AddAnonymousMethod (ame); + } + } } // @@ -5041,11 +5096,20 @@ void Error_ExpectingTypeName (Expression expr) } } -TypeContainer pop_current_class () +void push_current_class (TypeContainer tc, bool is_interface, object partial_token) +{ + if (partial_token != null) + current_container = current_container.AddPartial (tc, is_interface); + else + current_container = current_container.AddTypeContainer (tc, is_interface); + current_class = tc; +} + +DeclSpace pop_current_class () { - TypeContainer retval = current_class; + DeclSpace retval = current_class; - current_class = (TypeContainer) current_class.Parent; + current_class = current_class.Parent; current_container = current_class.PartialContainer; return retval; @@ -5060,8 +5124,8 @@ MakeName (MemberName class_name) { Namespace ns = current_namespace.NS; - if (current_container.Name == ""){ - if (ns.Name != "") + if (current_container.Name.Length == 0){ + if (ns.Name.Length != 0) return new MemberName (ns.MemberName, class_name); else return class_name; @@ -5225,15 +5289,11 @@ public Tokenizer Lexer { public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines) { - current_namespace = new NamespaceEntry (null, file, null, Location.Null); 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 (); + current_namespace = new NamespaceEntry (null, file, null); + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes lexer = new Tokenizer (reader, file, defines); } @@ -5259,10 +5319,11 @@ public void parse () Console.WriteLine (e); } - RootContext.Tree.Types.NamespaceEntry = null; + if (RootContext.ToplevelTypes.NamespaceEntry != null) + throw new InternalErrorException ("who set it?"); } -void CheckToken (int error, int yyToken, string msg, Location loc) +static void CheckToken (int error, int yyToken, string msg, Location loc) { if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) Report.Error (error, loc, "{0}: `{1}' is a keyword", msg, yyNames [yyToken].ToLower ());