From 52d98fe79e3c0fef2a89ea515e458db2b8e09689 Mon Sep 17 00:00:00 2001 From: Alex Berezhnykh Date: Tue, 14 Nov 2023 17:03:51 +0300 Subject: [PATCH] DotLambda: add parser recovery (#16238) * wip * wip --- src/Compiler/pars.fsy | 22 ++++++ .../Language/DotLambdaTests.fs | 4 +- .../DotLambda - _ Recovery - Casts.fsx | 3 + .../DotLambda - _ Recovery - Casts.fsx.bsl | 70 +++++++++++++++++++ .../DotLambda - _ Recovery - Eof.fsx | 1 + .../DotLambda - _ Recovery - Eof.fsx.bsl | 23 ++++++ .../Expression/DotLambda - _ Recovery.fsx | 1 + .../Expression/DotLambda - _ Recovery.fsx.bsl | 15 ++++ .../DotLambda - _. Recovery - Eof.fsx | 1 + .../DotLambda - _. Recovery - Eof.fsx.bsl | 26 +++++++ .../Expression/DotLambda - _. Recovery.fsx | 1 + .../DotLambda - _. Recovery.fsx.bsl | 18 +++++ 12 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx create mode 100644 tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx.bsl diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 3a9e75023cd..1e44ef874da 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4885,6 +4885,28 @@ atomicExpr: let trivia: SynExprDotLambdaTrivia = { UnderscoreRange = mUnderscore ; DotRange = mDot } SynExpr.DotLambda(expr, unionRanges mUnderscore expr.Range, trivia), false } + + | UNDERSCORE DOT recover %prec dot_lambda + { let mUnderscore = rhs parseState 1 + let mDot = rhs parseState 2 + let mWhole = unionRanges mUnderscore mDot + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AccessorFunctionShorthand mWhole + + let mExpr = mDot.EndRange + if not $3 then reportParseErrorAt mDot (FSComp.SR.parsUnexpectedEndOfFileExpression()) + + let expr = arbExpr ("dotLambda1", mExpr) + let trivia: SynExprDotLambdaTrivia = { UnderscoreRange = mUnderscore ; DotRange = mDot } + SynExpr.DotLambda(expr, mWhole, trivia), false } + + | UNDERSCORE recover %prec dot_lambda + { let mUnderscore = rhs parseState 1 + + if not $2 then reportParseErrorAt mUnderscore (FSComp.SR.parsUnexpectedEndOfFileExpression()) + + let expr = SynExpr.Ident(Ident("_", mUnderscore)) + SynExpr.FromParseError(expr, mUnderscore), false } + | atomicExpr HIGH_PRECEDENCE_BRACK_APP atomicExpr { let arg1, _ = $1 let arg2, hpa = $3 diff --git a/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs index a91045f49a2..f0e5c77e865 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs @@ -173,9 +173,7 @@ let c = ( _ :> obj) """ |> withDiagnostics [ Error 10, Line 2, Col 20, Line 2, Col 21, "Unexpected symbol ')' in expression. Expected '.' or other token." Error 10, Line 3, Col 13, Line 3, Col 15, "Unexpected symbol ':>' in expression. Expected '.' or other token." - Error 583, Line 3, Col 9, Line 3, Col 10, "Unmatched '('" - Error 10, Line 4, Col 13, Line 4, Col 15, "Unexpected symbol ':>' in expression. Expected '.' or other token." - Error 583, Line 4, Col 9, Line 4, Col 10, "Unmatched '('"] + Error 10, Line 4, Col 13, Line 4, Col 15, "Unexpected symbol ':>' in expression. Expected '.' or other token."] [] let ``ToString with F# 7`` () = diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx new file mode 100644 index 00000000000..6791dc6547a --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx @@ -0,0 +1,3 @@ +let a = ( upcast _ ) : obj +let b = ( _ :> _ ) : obj +let c = ( _ :> obj) diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx.bsl b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx.bsl new file mode 100644 index 00000000000..b65fe6bd9c6 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Casts.fsx.bsl @@ -0,0 +1,70 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/DotLambda - _ Recovery - Casts.fsx", true, + QualifiedNameOfFile DotLambda - _ Recovery - Casts$fsx, [], [], + [SynModuleOrNamespace + ([DotLambda - _ Recovery - Casts], false, AnonModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None, + None), Named (SynIdent (a, None), false, None, (1,4--1,5)), + None, + Typed + (Paren + (InferredUpcast + (FromParseError (Ident _, (1,17--1,18)), (1,10--1,18)), + (1,8--1,9), Some (1,19--1,20), (1,8--1,20)), + LongIdent (SynLongIdent ([obj], [], [None])), (1,8--1,26)), + (1,4--1,5), Yes (1,0--1,26), { LeadingKeyword = Let (1,0--1,3) + InlineKeyword = None + EqualsRange = Some (1,6--1,7) })], + (1,0--1,26)); + Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((2,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None, + None), Named (SynIdent (b, None), false, None, (2,4--2,5)), + None, + Typed + (Paren + (Upcast + (FromParseError (Ident _, (2,10--2,11)), + Anon (2,15--2,16), (2,10--2,16)), (2,8--2,9), + Some (2,17--2,18), (2,8--2,18)), + LongIdent (SynLongIdent ([obj], [], [None])), (2,8--2,24)), + (2,4--2,5), Yes (2,0--2,24), { LeadingKeyword = Let (2,0--2,3) + InlineKeyword = None + EqualsRange = Some (2,6--2,7) })], + (2,0--2,24)); + Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None, + None), Named (SynIdent (c, None), false, None, (3,4--3,5)), + None, + Paren + (Upcast + (FromParseError (Ident _, (3,10--3,11)), + LongIdent (SynLongIdent ([obj], [], [None])), + (3,10--3,18)), (3,8--3,9), Some (3,18--3,19), + (3,8--3,19)), (3,4--3,5), Yes (3,0--3,19), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--3,19))], + PreXmlDocEmpty, [], None, (1,0--4,0), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(1,19)-(1,20) parse error Unexpected symbol ')' in expression. Expected '.' or other token. +(2,12)-(2,14) parse error Unexpected symbol ':>' in expression. Expected '.' or other token. +(3,12)-(3,14) parse error Unexpected symbol ':>' in expression. Expected '.' or other token. diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx new file mode 100644 index 00000000000..3454fffae8c --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx @@ -0,0 +1 @@ +1 |> _ \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx.bsl b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx.bsl new file mode 100644 index 00000000000..f481a08bdd5 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery - Eof.fsx.bsl @@ -0,0 +1,23 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/DotLambda - _ Recovery - Eof.fsx", true, + QualifiedNameOfFile DotLambda - _ Recovery - Eof$fsx, [], [], + [SynModuleOrNamespace + ([DotLambda - _ Recovery - Eof], false, AnonModule, + [Expr + (App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_PipeRight], [], [Some (OriginalNotation "|>")]), + None, (1,2--1,4)), Const (Int32 1, (1,0--1,1)), + (1,0--1,4)), FromParseError (Ident _, (1,5--1,6)), + (1,0--1,6)), (1,0--1,6))], PreXmlDocEmpty, [], None, (1,0--1,6), + { LeadingKeyword = None })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(1,5)-(1,6) parse error Unexpected end of input in expression diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx new file mode 100644 index 00000000000..4c34cbc60d2 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx @@ -0,0 +1 @@ +(_) diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx.bsl b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx.bsl new file mode 100644 index 00000000000..1dfda19d13b --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _ Recovery.fsx.bsl @@ -0,0 +1,15 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/DotLambda - _ Recovery.fsx", true, + QualifiedNameOfFile DotLambda - _ Recovery$fsx, [], [], + [SynModuleOrNamespace + ([DotLambda - _ Recovery], false, AnonModule, + [Expr + (Paren + (FromParseError (Ident _, (1,1--1,2)), (1,0--1,1), + Some (1,2--1,3), (1,0--1,3)), (1,0--1,3))], PreXmlDocEmpty, [], + None, (1,0--1,3), { LeadingKeyword = None })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(1,2)-(1,3) parse error Unexpected symbol ')' in expression. Expected '.' or other token. diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx new file mode 100644 index 00000000000..fa28bf307bf --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx @@ -0,0 +1 @@ +1 |> _. \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx.bsl b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx.bsl new file mode 100644 index 00000000000..878b39bfb7a --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery - Eof.fsx.bsl @@ -0,0 +1,26 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/DotLambda - _. Recovery - Eof.fsx", true, + QualifiedNameOfFile DotLambda - _. Recovery - Eof$fsx, [], [], + [SynModuleOrNamespace + ([DotLambda - _; Recovery - Eof], false, AnonModule, + [Expr + (App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_PipeRight], [], [Some (OriginalNotation "|>")]), + None, (1,2--1,4)), Const (Int32 1, (1,0--1,1)), + (1,0--1,4)), + DotLambda + (ArbitraryAfterError ("dotLambda1", (1,7--1,7)), (1,5--1,7), + { UnderscoreRange = (1,5--1,6) + DotRange = (1,6--1,7) }), (1,0--1,7)), (1,0--1,7))], + PreXmlDocEmpty, [], None, (1,0--1,7), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(1,6)-(1,7) parse error Unexpected end of input in expression diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx new file mode 100644 index 00000000000..56d26b9c9d0 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx @@ -0,0 +1 @@ +(_.) diff --git a/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx.bsl b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx.bsl new file mode 100644 index 00000000000..0bc367b4df3 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/DotLambda - _. Recovery.fsx.bsl @@ -0,0 +1,18 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/DotLambda - _. Recovery.fsx", true, + QualifiedNameOfFile DotLambda - _. Recovery$fsx, [], [], + [SynModuleOrNamespace + ([DotLambda - _; Recovery], false, AnonModule, + [Expr + (Paren + (DotLambda + (ArbitraryAfterError ("dotLambda1", (1,3--1,3)), (1,1--1,3), + { UnderscoreRange = (1,1--1,2) + DotRange = (1,2--1,3) }), (1,0--1,1), Some (1,3--1,4), + (1,0--1,4)), (1,0--1,4))], PreXmlDocEmpty, [], None, (1,0--1,4), + { LeadingKeyword = None })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(1,3)-(1,4) parse error Unexpected symbol ')' in expression