X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fcs-parser.jay;h=902690017e992da6e112221bbd8078cc1d7751c8;hb=7a345a73f5cdd9f89fb6103d0b52b745a8f1dd45;hp=d0ac204bd7f6d10681d8c1d9118e40ddefa5de0e;hpb=a34746ac4eba1f9ec6741a99b73577ea64f17157;p=mono.git diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index d0ac204bd7f..902690017e9 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -139,6 +139,7 @@ namespace Mono.CSharp // LocationsBag lbag; List> mod_locations; + Stack location_stack; %} %token EOF @@ -521,7 +522,7 @@ namespace_declaration if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } - opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon + opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon_error { if ($11 != null) lbag.AddLocation (current_container, GetLocation ($2), GetLocation ($5), GetLocation ($10), GetLocation ($11)); @@ -541,6 +542,16 @@ namespace_declaration } ; +opt_semicolon_error + : /* empty */ + | SEMICOLON + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + namespace_name : IDENTIFIER { @@ -665,6 +676,7 @@ attribute_sections attribute_section : OPEN_BRACKET { + PushLocation (GetLocation ($1)); lexer.parsing_attribute_section = true; } attribute_section_cont @@ -689,13 +701,43 @@ attribute_section_cont $$ = new List (0); else $$ = $4; - + + lbag.InsertLocation ($$, 0, PopLocation ()); + if ($5 != null) { + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($5), GetLocation ($6)); + } else { + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($6)); + } + current_attr_target = null; lexer.parsing_attribute_section = false; } | attribute_list opt_comma CLOSE_BRACKET { $$ = $1; + + lbag.InsertLocation ($$, 0, PopLocation ()); + if ($2 != null) { + lbag.AddLocation ($$, GetLocation($2), GetLocation ($3)); + } else { + lbag.AddLocation ($$, GetLocation($3)); + } + } + | IDENTIFIER error + { + Error_SyntaxError (yyToken); + + var lt = (Tokenizer.LocatedToken) $1; + var tne = new SimpleName (lt.Value, null, lt.Location); + + $$ = new List () { + new Attribute (null, tne, null, GetLocation ($1), false) + }; + } + | error + { + $$ = CheckAttributeTarget (GetTokenName (yyToken), GetLocation ($1)); + $$ = null; } ; @@ -707,16 +749,6 @@ attribute_target } | EVENT { $$ = "event"; } | RETURN { $$ = "return"; } - | error - { - if (yyToken == Token.IDENTIFIER) { - Error_SyntaxError (yyToken); - $$ = null; - } else { - string name = GetTokenName (yyToken); - $$ = CheckAttributeTarget (name, GetLocation ($1)); - } - } ; attribute_list @@ -727,7 +759,10 @@ attribute_list | attribute_list COMMA attribute { var attrs = (List) $1; - attrs.Add ((Attribute) $3); + if (attrs != null) { + attrs.Add ((Attribute) $3); + lbag.AppendTo (attrs, GetLocation ($2)); + } $$ = attrs; } @@ -809,6 +844,11 @@ positional_or_named_argument $$ = new Argument ((Expression) $1); } | named_argument + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } ; named_attribute_argument @@ -880,13 +920,14 @@ class_member_declaration | destructor_declaration | type_declaration | attributes_without_members + | incomplete_member | error { report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", GetSymbolName (yyToken)); $$ = null; lexer.parsing_generic_declaration = false; - } + } ; struct_declaration @@ -895,10 +936,10 @@ struct_declaration opt_partial STRUCT { - lexer.ConstraintsParsing = true; } type_declaration_name { + lexer.ConstraintsParsing = true; push_current_container (new Struct (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3); } opt_class_base @@ -1463,7 +1504,7 @@ fixed_parameter : opt_attributes opt_parameter_modifier parameter_type - IDENTIFIER + identifier_inside_body { var lt = (Tokenizer.LocatedToken) $4; $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); @@ -1471,7 +1512,7 @@ fixed_parameter | opt_attributes opt_parameter_modifier parameter_type - IDENTIFIER OPEN_BRACKET CLOSE_BRACKET + identifier_inside_body OPEN_BRACKET CLOSE_BRACKET { var lt = (Tokenizer.LocatedToken) $4; report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); @@ -1495,7 +1536,7 @@ fixed_parameter | opt_attributes opt_parameter_modifier parameter_type - IDENTIFIER + identifier_inside_body ASSIGN { ++lexer.parsing_block; @@ -1865,10 +1906,10 @@ interface_declaration opt_partial INTERFACE { - lexer.ConstraintsParsing = true; } type_declaration_name { + lexer.ConstraintsParsing = true; push_current_container (new Interface (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3); lbag.AddMember (current_container, mod_locations, GetLocation ($4)); } @@ -2079,7 +2120,11 @@ conversion_operator_declarator Location loc = GetLocation ($2); current_local_parameters = (ParametersCompiled)$6; - + + if (current_local_parameters.Count != 1) { + report.Error (1535, loc, "Overloaded unary operator `implicit' takes one parameter"); + } + if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; @@ -2098,7 +2143,11 @@ conversion_operator_declarator Location loc = GetLocation ($2); current_local_parameters = (ParametersCompiled)$6; - + + if (current_local_parameters.Count != 1) { + report.Error (1535, loc, "Overloaded unary operator `explicit' takes one parameter"); + } + if (doc_support) { tmpComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.NotAllowed; @@ -2497,6 +2546,23 @@ attributes_without_members lexer.putback ('}'); } ; + +// For full ast try to recover incomplete ambiguous member +// declaration in form on class X { public int } +incomplete_member + : opt_attributes opt_modifiers member_type CLOSE_BRACE + { + report.Error (1519, lexer.Location, "Unexpected symbol `}' in class, struct, or interface member declaration"); + + lexer.putback ('}'); + + lexer.parsing_generic_declaration = false; + FullNamedExpression type = (FullNamedExpression) $3; + current_field = new Field (current_type, type, (Modifiers) $2, MemberName.Null, (Attributes) $1); + current_type.AddField (current_field); + $$ = current_field; + } + ; enum_declaration : opt_attributes @@ -3081,35 +3147,35 @@ close_parens parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS { - $$ = new ParenthesizedExpression ((Expression) $2); + $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } | OPEN_PARENS expression COMPLETE_COMPLETION { - $$ = new ParenthesizedExpression ((Expression) $2); + $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); } ; member_access - : primary_expression DOT IDENTIFIER opt_type_argument_list + : primary_expression DOT identifier_inside_body opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } - | builtin_types DOT IDENTIFIER opt_type_argument_list + | builtin_types DOT identifier_inside_body opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } - | BASE DOT IDENTIFIER opt_type_argument_list + | BASE DOT identifier_inside_body opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } - | qualified_alias_member IDENTIFIER opt_type_argument_list + | qualified_alias_member identifier_inside_body opt_type_argument_list { var lt1 = (Tokenizer.LocatedToken) $1; var lt2 = (Tokenizer.LocatedToken) $2; @@ -3153,7 +3219,7 @@ invocation_expression $$ = new Invocation ((Expression) $1, null); lbag.AddLocation ($$, GetLocation ($2)); - } + } ; opt_object_or_collection_initializer @@ -3165,12 +3231,11 @@ object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion { if ($2 == null) { - $$ = CollectionOrObjectInitializers.Empty; - // TODO: lbag + $$ = new CollectionOrObjectInitializers (GetLocation ($1)); } else { $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); - lbag.AddLocation ($$, GetLocation ($3)); } + lbag.AddLocation ($$, GetLocation ($3)); } | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE { @@ -3213,6 +3278,12 @@ member_initializer $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } + | AWAIT ASSIGN initializer_value + { + var lt = (Tokenizer.LocatedToken) Error_AwaitAsIdentifier ($1); + $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } | GENERATE_COMPLETION { $$ = new CompletionElementInitializer (null, GetLocation ($1)); @@ -3235,7 +3306,7 @@ member_initializer { report.Error (1920, GetLocation ($1), "An element initializer cannot be empty"); $$ = null; - } + } ; initializer_value @@ -3351,22 +3422,18 @@ element_access ; expression_list - : expression + : expression_or_error { var list = new List (4); list.Add ((Expression) $1); $$ = list; } - | expression_list COMMA expression + | expression_list COMMA expression_or_error { var list = (List) $1; list.Add ((Expression) $3); $$ = list; } - | expression_list error { - Error_SyntaxError (yyToken); - $$ = $1; - } ; expression_list_arguments @@ -3540,13 +3607,13 @@ anonymous_type_parameters ; anonymous_type_parameter - : IDENTIFIER ASSIGN variable_initializer + : identifier_inside_body ASSIGN variable_initializer { var lt = (Tokenizer.LocatedToken)$1; $$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location); lbag.AddLocation ($$, GetLocation ($2)); } - | IDENTIFIER + | identifier_inside_body { var lt = (Tokenizer.LocatedToken)$1; $$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), @@ -4270,6 +4337,14 @@ conditional_expression $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); lbag.AddLocation ($$, GetLocation ($4)); } + | null_coalescing_expression INTERR expression COLON CLOSE_BRACE + { + Error_SyntaxError (Token.CLOSE_BRACE); + + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + lexer.putback ('}'); + } ; assignment_expression @@ -4369,6 +4444,11 @@ lambda_parameter var lt = (Tokenizer.LocatedToken) $1; $$ = new ImplicitLambdaParameter (lt.Value, lt.Location); } + | AWAIT + { + var lt = (Tokenizer.LocatedToken) Error_AwaitAsIdentifier ($1); + $$ = new ImplicitLambdaParameter (lt.Value, lt.Location); + } ; opt_lambda_parameter_list @@ -4395,6 +4475,8 @@ lambda_expression_body { // Handles only cases like foo = x.FirstOrDefault (l => ); // where we must restore current_variable + Block b = end_block (Location.Null); + b.IsCompilerGenerated = true; Error_SyntaxError (yyToken); $$ = null; @@ -4422,6 +4504,17 @@ lambda_expression $$ = end_anonymous ((ParametersBlock) $4); lbag.AddLocation ($$, GetLocation ($2)); } + | AWAIT ARROW + { + var lt = (Tokenizer.LocatedToken) Error_AwaitAsIdentifier ($1); + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), false, lt.Location); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $4); + lbag.AddLocation ($$, GetLocation ($2)); + } | ASYNC identifier_inside_body ARROW { var lt = (Tokenizer.LocatedToken) $2; @@ -4516,10 +4609,11 @@ class_declaration opt_partial CLASS { - lexer.ConstraintsParsing = true; } type_declaration_name { + lexer.ConstraintsParsing = true; + Class c = new Class (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1); if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (c.Location, "static classes"); @@ -5096,10 +5190,7 @@ identifier_inside_body : IDENTIFIER | AWAIT { - if (async_block) { - report.Error (4003, GetLocation ($1), "`await' cannot be used as an identifier within an async method or lambda expression"); - $$ = new Tokenizer.LocatedToken ("await", GetLocation ($1)); - } + $$ = Error_AwaitAsIdentifier ($1); } ; @@ -5115,7 +5206,10 @@ block_variable_declaration { $$ = current_variable; current_variable = null; - lbag.AddLocation ($$, GetLocation ($6)); + if ($4 != null) + lbag.AddLocation ($$, PopLocation (), GetLocation ($6)); + else + lbag.AddLocation ($$, GetLocation ($6)); } | CONST variable_type identifier_inside_body { @@ -5137,7 +5231,8 @@ opt_local_variable_initializer | ASSIGN block_variable_initializer { current_variable.Initializer = (Expression) $2; - // TODO: lbag + PushLocation (GetLocation ($1)); + $$ = current_variable; } | error { @@ -5268,8 +5363,9 @@ statement_expression { ExpressionStatement s = $1 as ExpressionStatement; if (s == null) { - Expression.Error_InvalidExpressionStatement (report, GetLocation ($1)); - $$ = new StatementErrorExpression ($1 as Expression); + var expr = $1 as Expression; + expr.Error_InvalidExpressionStatement (report); + $$ = new StatementErrorExpression (expr); } else { $$ = new StatementExpression (s); } @@ -5334,7 +5430,7 @@ switch_statement } opt_switch_sections CLOSE_BRACE { - $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, (List) $7, GetLocation ($1)); + $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, GetLocation ($1)); end_block (GetLocation ($8)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); } @@ -5342,7 +5438,7 @@ switch_statement { Error_SyntaxError (yyToken); - $$ = new Switch ((Expression) $3, null, null, GetLocation ($1)); + $$ = new Switch ((Expression) $3, null, GetLocation ($1)); lbag.AddStatement ($$, GetLocation ($2)); } ; @@ -5351,58 +5447,33 @@ opt_switch_sections : /* empty */ { report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); - $$ = new List (); } | switch_sections ; switch_sections : switch_section - { - var sections = new List (4); - - sections.Add ((SwitchSection) $1); - $$ = sections; - } | switch_sections switch_section - { - var sections = (List) $1; - - sections.Add ((SwitchSection) $2); - $$ = sections; - } | error { Error_SyntaxError (yyToken); - $$ = new List (); } ; switch_section - : switch_labels - { - current_block = current_block.CreateSwitchBlock (lexer.Location); - } - statement_list - { - $$ = new SwitchSection ((List) $1, current_block); - } + : switch_labels statement_list ; switch_labels : switch_label { - var labels = new List (2); - - labels.Add ((SwitchLabel) $1); - $$ = labels; + var label = (SwitchLabel) $1; + label.SectionStart = true; + current_block.AddStatement (label); } | switch_labels switch_label { - var labels = (List) ($1); - labels.Add ((SwitchLabel) $2); - - $$ = labels; + current_block.AddStatement ((Statement) $2); } ; @@ -5568,6 +5639,9 @@ for_initializer opt_local_variable_initializer opt_variable_declarators { $$ = current_variable; + if ($4 != null) + lbag.AddLocation (current_variable, PopLocation ()); + current_variable = null; } | statement_expression_list @@ -5783,7 +5857,7 @@ yield_statement FeatureIsNotAvailable (lt.Location, "iterators"); } - current_block.Explicit.RegisterIteratorYield (); + current_block.ParametersBlock.TopBlock.IsIterator = true; $$ = new YieldBreak (lt.Location); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); } @@ -6222,15 +6296,29 @@ select_or_group_clause current_block = new Linq.QueryBlock (current_block, lexer.Location); } - BY expression_or_error + by_expression { - $$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1)); - lbag.AddLocation ($$, GetLocation ($5)); + var obj = (object[]) $5; + + $$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)obj[0], GetLocation ($1)); + lbag.AddLocation ($$, (Location) obj[1]); current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } ; + +by_expression + : BY expression_or_error + { + $$ = new object[] { $2, GetLocation ($1) }; + } + | error + { + Error_SyntaxError (yyToken); + $$ = new object[2] { null, Location.Null }; + } + ; query_body_clauses : query_body_clause @@ -6743,7 +6831,7 @@ void Error_ExpectingTypeName (Expression expr) if (expr is Invocation){ report.Error (1002, expr.Location, "Expecting `;'"); } else { - Expression.Error_InvalidExpressionStatement (report, expr.Location); + expr.Error_InvalidExpressionStatement (report); } } @@ -6784,6 +6872,16 @@ void Error_MissingInitializer (Location loc) report.Error (210, loc, "You must provide an initializer in a fixed or using statement declaration"); } +object Error_AwaitAsIdentifier (object token) +{ + if (async_block) { + report.Error (4003, GetLocation (token), "`await' cannot be used as an identifier within an async method or lambda expression"); + return new Tokenizer.LocatedToken ("await", GetLocation (token)); + } + + return token; +} + void push_current_container (TypeDefinition tc, object partial_token) { if (module.Evaluator != null){ @@ -6826,6 +6924,23 @@ void StoreModifierLocation (object token, Location loc) mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); } +[System.Diagnostics.Conditional ("FULL_AST")] +void PushLocation (Location loc) +{ + if (location_stack == null) + location_stack = new Stack (); + + location_stack.Push (loc); +} + +Location PopLocation () +{ + if (location_stack == null) + return Location.Null; + + return location_stack.Pop (); +} + string CheckAttributeTarget (string a, Location l) { switch (a) { @@ -6913,7 +7028,8 @@ public void parse () } if (e is yyParser.yyException) { - report.Error (-25, lexer.Location, "Parsing error"); + if (report.Errors == 0) + report.Error (-25, lexer.Location, "Parsing error"); } else { // Used by compiler-tester to test internal errors if (yacc_verbose_flag > 0 || e is FatalException)