From ee48992e52521b0c320b2ddde43b1910acdd88e2 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 12 Jun 2023 14:58:23 +0200 Subject: [PATCH 1/2] Parser: fix 'done' range in expressions --- src/Compiler/Service/ServiceLexing.fs | 12 +- src/Compiler/SyntaxTree/LexFilter.fs | 59 ++--- src/Compiler/SyntaxTree/LexHelpers.fs | 2 +- src/Compiler/pars.fsy | 219 +++++++++--------- .../data/SyntaxTree/Expression/Do 01.fs | 6 + .../data/SyntaxTree/Expression/Do 01.fs.bsl | 11 + .../data/SyntaxTree/Expression/Do 02.fs | 7 + .../data/SyntaxTree/Expression/Do 02.fs.bsl | 11 + .../data/SyntaxTree/Expression/For 01.fs | 6 + .../data/SyntaxTree/Expression/For 01.fs.bsl | 15 ++ .../data/SyntaxTree/Expression/For 02.fs | 7 + .../data/SyntaxTree/Expression/For 02.fs.bsl | 15 ++ .../data/SyntaxTree/Expression/While 01.fs | 6 + .../SyntaxTree/Expression/While 01.fs.bsl | 14 ++ .../data/SyntaxTree/Expression/While 02.fs | 7 + .../SyntaxTree/Expression/While 02.fs.bsl | 14 ++ 16 files changed, 270 insertions(+), 141 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Expression/Do 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Do 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Do 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Do 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/For 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/For 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/For 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/For 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/While 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/While 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/While 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/While 02.fs.bsl diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs index 09f3d6b8016..d1186d2557b 100644 --- a/src/Compiler/Service/ServiceLexing.fs +++ b/src/Compiler/Service/ServiceLexing.fs @@ -316,12 +316,12 @@ module internal TokenClassifications = | NAMESPACE | OASSERT | OLAZY - | ODECLEND + | ODECLEND _ | OBLOCKSEP | OEND | OBLOCKBEGIN - | ORIGHT_BLOCK_END - | OBLOCKEND + | ORIGHT_BLOCK_END _ + | OBLOCKEND _ | OBLOCKEND_COMING_SOON | OBLOCKEND_IS_HERE | OTHEN @@ -1506,9 +1506,9 @@ type FSharpToken = | STRING_TEXT _ -> FSharpTokenKind.StringText | FIXED -> FSharpTokenKind.Fixed | OINTERFACE_MEMBER -> FSharpTokenKind.OffsideInterfaceMember - | OBLOCKEND -> FSharpTokenKind.OffsideBlockEnd - | ORIGHT_BLOCK_END -> FSharpTokenKind.OffsideRightBlockEnd - | ODECLEND -> FSharpTokenKind.OffsideDeclEnd + | OBLOCKEND _ -> FSharpTokenKind.OffsideBlockEnd + | ORIGHT_BLOCK_END _ -> FSharpTokenKind.OffsideRightBlockEnd + | ODECLEND _ -> FSharpTokenKind.OffsideDeclEnd | OEND -> FSharpTokenKind.OffsideEnd | OBLOCKSEP -> FSharpTokenKind.OffsideBlockSep | OBLOCKBEGIN -> FSharpTokenKind.OffsideBlockBegin diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs index e163646f688..270a9f3c96f 100644 --- a/src/Compiler/SyntaxTree/LexFilter.fs +++ b/src/Compiler/SyntaxTree/LexFilter.fs @@ -210,7 +210,7 @@ let rec isIfBlockContinuator token = // end else ... | END | RPAREN -> true // The following arise during reprocessing of the inserted tokens, e.g. when we hit a DONE - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true | ODUMMY token -> isIfBlockContinuator token | _ -> false @@ -224,7 +224,7 @@ let rec isMatchBlockContinuator token = // with ... | WITH -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true | ODUMMY token -> isMatchBlockContinuator token | _ -> false @@ -237,14 +237,14 @@ let rec isTryBlockContinuator token = // with ... | FINALLY | WITH -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true | ODUMMY token -> isTryBlockContinuator token | _ -> false let rec isThenBlockContinuator token = match token with // The following arise during reprocessing of the inserted tokens when we hit a DONE - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true | ODUMMY token -> isThenBlockContinuator token | _ -> false @@ -256,7 +256,7 @@ let rec isDoContinuator token = // ... // done *) | DONE -> true - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE | ODUMMY token -> isDoContinuator token | _ -> false @@ -267,7 +267,7 @@ let rec isInterfaceContinuator token = // ... // end | END -> true - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE | ODUMMY token -> isInterfaceContinuator token | _ -> false @@ -304,7 +304,7 @@ let rec isTypeContinuator token = | RBRACE _ | WITH | BAR | AND | END -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true | ODUMMY token -> isTypeContinuator token | _ -> false @@ -315,7 +315,7 @@ let rec isForLoopContinuator token = // ... // done | DONE -> true - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true// The following arise during reprocessing of the inserted tokens when we hit a DONE + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true// The following arise during reprocessing of the inserted tokens when we hit a DONE | ODUMMY token -> isForLoopContinuator token | _ -> false @@ -326,7 +326,7 @@ let rec isWhileBlockContinuator token = // ... // done | DONE -> true - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE | ODUMMY token -> isWhileBlockContinuator token | _ -> false @@ -336,7 +336,7 @@ let rec isLetContinuator token = // let ... // and ... | AND -> true - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE | ODUMMY token -> isLetContinuator token | _ -> false @@ -349,7 +349,7 @@ let rec isTypeSeqBlockElementContinuator token = // member x.M1 // member x.M2 | BAR -> true - | OBLOCKBEGIN | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE + | OBLOCKBEGIN | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE | ODUMMY token -> isTypeSeqBlockElementContinuator token | _ -> false @@ -373,7 +373,7 @@ let rec isSeqBlockElementContinuator token = | END | AND | WITH | THEN | RPAREN | RBRACE _ | BAR_RBRACE | RBRACK | BAR_RBRACK | RQUOTE _ -> true // The following arise during reprocessing of the inserted tokens when we hit a DONE - | ORIGHT_BLOCK_END | OBLOCKEND | ODECLEND -> true + | ORIGHT_BLOCK_END _ | OBLOCKEND _ | ODECLEND _ -> true | ODUMMY token -> isSeqBlockElementContinuator token | _ -> false @@ -1271,6 +1271,10 @@ type LexFilterImpl ( delayToken tokenTup hwTokenFetch false + let getLastTokenEndRange () = + let lastTokenPos = tokenTup.LastTokenPos + mkSynRange lastTokenPos lastTokenPos + let insertTokenFromPrevPosToCurrentPos tok = delayToken tokenTup if debug then dprintf "inserting %+A\n" tok @@ -1344,18 +1348,17 @@ type LexFilterImpl ( | CtxtWithAsLet _ -> Some OEND - | CtxtWithAsAugment _ -> - Some ODECLEND + | CtxtWithAsAugment _ | CtxtDo _ | CtxtLetDecl (true, _) -> - Some ODECLEND + Some (ODECLEND(getLastTokenEndRange ())) | CtxtSeqBlock(_, _, AddBlockEnd) -> - Some OBLOCKEND + Some (OBLOCKEND(getLastTokenEndRange ())) | CtxtSeqBlock(_, _, AddOneSidedBlockEnd) -> - Some ORIGHT_BLOCK_END + Some (ORIGHT_BLOCK_END(getLastTokenEndRange ())) | _ -> None @@ -1426,7 +1429,7 @@ type LexFilterImpl ( popCtxt() effectsToDo <- (fun() -> if debug then dprintf "--> because %s is coming, inserting OBLOCKEND\n" keywordName - delayTokenNoProcessing (pool.UseLocation(tokenTup, OBLOCKEND))) :: effectsToDo + delayTokenNoProcessing (pool.UseLocation(tokenTup, OBLOCKEND(getLastTokenEndRange ())))) :: effectsToDo | CtxtSeqBlock(_, _, NoAddBlockEnd) -> if debug then dprintf "--> because %s is coming, popping CtxtSeqBlock\n" keywordName popCtxt() @@ -1434,7 +1437,7 @@ type LexFilterImpl ( popCtxt() effectsToDo <- (fun() -> if debug then dprintf "--> because %s is coming, inserting ORIGHT_BLOCK_END\n" keywordName - delayTokenNoProcessing (pool.UseLocation(tokenTup, ORIGHT_BLOCK_END))) :: effectsToDo + delayTokenNoProcessing (pool.UseLocation(tokenTup, ORIGHT_BLOCK_END(getLastTokenEndRange ())))) :: effectsToDo | CtxtVanilla _ -> if debug then dprintf "--> because %s is coming, popping CtxtVanilla\n" keywordName popCtxt() @@ -1497,7 +1500,7 @@ type LexFilterImpl ( popCtxt() // Make sure we queue a dummy token at this position to check if any other pop rules apply delayToken(pool.UseLocation(tokenTup, ODUMMY token)) - returnToken tokenLexbufState (if blockLet then ODECLEND else token) + returnToken tokenLexbufState (if blockLet then ODECLEND(getLastTokenEndRange ()) else token) // Balancing rule. Encountering a 'done' balances with a 'do'. i.e. even a non-offside 'done' closes a 'do' // The 'DONE' token is thrown away and becomes an ODECLEND @@ -1505,7 +1508,7 @@ type LexFilterImpl ( if debug then dprintf "DONE at %a terminates CtxtDo(offsidePos=%a)\n" outputPos tokenStartPos outputPos offsidePos popCtxt() // reprocess as the DONE may close a DO context - delayToken(pool.UseLocation(tokenTup, ODECLEND)) + delayToken(pool.UseLocation(tokenTup, ODECLEND(mkSynRange tokenTup.StartPos tokenTup.EndPos))) pool.Return tokenTup hwTokenFetch useBlockRule @@ -1670,8 +1673,8 @@ type LexFilterImpl ( popCtxt() if debug then (match addBlockEnd with AddBlockEnd -> dprintf "end of CtxtSeqBlock, insert OBLOCKEND \n" | _ -> ()) match addBlockEnd with - | AddBlockEnd -> insertToken OBLOCKEND - | AddOneSidedBlockEnd -> insertToken ORIGHT_BLOCK_END + | AddBlockEnd -> insertToken (OBLOCKEND(getLastTokenEndRange ())) + | AddOneSidedBlockEnd -> insertToken (ORIGHT_BLOCK_END(getLastTokenEndRange ())) | NoAddBlockEnd -> reprocess() // Offside rule for SeqBlock. @@ -1753,7 +1756,7 @@ type LexFilterImpl ( isSemiSemi || (if relaxWhitespace2OffsideRule || isLetContinuator token then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column -> if debug then dprintf "token at column %d is offside from LET(offsidePos=%a)! delaying token, returning ODECLEND\n" tokenStartCol outputPos offsidePos popCtxt() - insertToken ODECLEND + insertToken (ODECLEND(getLastTokenEndRange ())) // do ignore ( // 1 @@ -1763,7 +1766,7 @@ type LexFilterImpl ( when isSemiSemi || (if isDoContinuator token then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column -> if debug then dprintf "token at column %d is offside from DO(offsidePos=%a)! delaying token, returning ODECLEND\n" tokenStartCol outputPos offsidePos popCtxt() - insertToken ODECLEND + insertToken (ODECLEND(getLastTokenEndRange ())) // class // interface AAA @@ -1815,7 +1818,7 @@ type LexFilterImpl ( | _, CtxtMemberBody offsidePos :: _ when isSemiSemi || (if false then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column -> if debug then dprintf "token at column %d is offside from MEMBER/OVERRIDE head with offsidePos %a!\n" tokenStartCol outputPos offsidePos popCtxt() - insertToken ODECLEND + insertToken (ODECLEND(getLastTokenEndRange ())) // Pop CtxtMemberHead when offside | _, CtxtMemberHead offsidePos :: _ when isSemiSemi || (if relaxWhitespace2OffsideRule then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column -> @@ -1839,7 +1842,7 @@ type LexFilterImpl ( when isSemiSemi || (if relaxWhitespace2OffsideRule || isWithAugmentBlockContinuator token then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column -> if debug then dprintf "offside from CtxtWithAsAugment, isWithAugmentBlockContinuator = %b\n" (isWithAugmentBlockContinuator token) popCtxt() - insertToken ODECLEND + insertToken (ODECLEND(getLastTokenEndRange ())) | _, CtxtMatch offsidePos :: _ when isSemiSemi || (if relaxWhitespace2OffsideRule || relaxWhitespace2 && isMatchBlockContinuator token then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column -> @@ -2593,7 +2596,7 @@ type LexFilter (indentationSyntaxStatus: IndentationAwareSyntaxStatus, compiling | RPAREN -> insertComingSoonTokens RPAREN_COMING_SOON RPAREN_IS_HERE lexer.GetToken() - | OBLOCKEND -> + | OBLOCKEND _ -> insertComingSoonTokens OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE lexer.GetToken() | _ -> token diff --git a/src/Compiler/SyntaxTree/LexHelpers.fs b/src/Compiler/SyntaxTree/LexHelpers.fs index f1de8c6b814..eb204fc18b1 100644 --- a/src/Compiler/SyntaxTree/LexHelpers.fs +++ b/src/Compiler/SyntaxTree/LexHelpers.fs @@ -390,7 +390,7 @@ module Keywords = (*------- for prototyping and explaining offside rule *) FSHARP, "__token_OBLOCKSEP", OBLOCKSEP FSHARP, "__token_OWITH", OWITH - FSHARP, "__token_ODECLEND", ODECLEND + FSHARP, "__token_ODECLEND", ODECLEND range0 FSHARP, "__token_OTHEN", OTHEN FSHARP, "__token_OELSE", OELSE FSHARP, "__token_OEND", OEND diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 4d7f77d6e73..aa740772ca0 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -134,11 +134,12 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) -> */ %token OBLOCKSEP /* LexFilter #light inserts when transforming CtxtSeqBlock(NotFirstInSeqBlock, _, AddBlockEnd) to CtxtSeqBlock(FirstInSeqBlock, _, AddBlockEnd) on exact alignment */ -/* REVIEW: merge OEND, ODECLEND, OBLOCKEND and ORIGHT_BLOCK_END into one token */ -%token OEND /* LexFilter #light inserts when closing CtxtFun, CtxtMatchClauses, CtxtWithAsLet _ */ -%token ODECLEND /* LexFilter #light inserts when closing CtxtDo and CtxtLetDecl(block) */ -%token ORIGHT_BLOCK_END /* LexFilter #light inserts when closing CtxtSeqBlock(_, _, AddOneSidedBlockEnd) */ -%token OBLOCKEND OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE /* LexFilter #light inserts when closing CtxtSeqBlock(_, _, AddBlockEnd) */ +/* LexFilter #light inserts these tokens when closing offside contexts */ +%token OEND // CtxtFun, CtxtMatchClauses, CtxtWithAsLet _ +%token ODECLEND // CtxtDo and CtxtLetDecl(block) +%token ORIGHT_BLOCK_END // CtxtSeqBlock(_, _, AddOneSidedBlockEnd) +%token OBLOCKEND // CtxtSeqBlock(_, _, AddBlockEnd) +%token OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE // CtxtSeqBlock(_, _, AddBlockEnd) %token OINTERFACE_MEMBER /* inserted for non-paranthetical use of 'INTERFACE', i.e. not INTERFACE/END */ %token FIXED @@ -2682,7 +2683,7 @@ hardwhiteLetBindings: else SynLeadingKeyword.Let(mLetKwd) - let report, mIn = $4 + let report, mIn, _ = $4 report (if isUse then "use" else "let") mLetKwd // report unterminated error let localBindingsLastRangeOpt, localBindingsBuilder = $3 @@ -2709,12 +2710,14 @@ hardwhiteLetBindings: /* A 'do ...' statement */ hardwhiteDoBinding: | ODO typedSequentialExprBlock hardwhiteDefnBindingsTerminator - { let mDoKwd = rhs parseState 1 - let bindingSetRange = unionRanges mDoKwd $2.Range + { let mDo = rhs parseState 1 + let _, _, mDone = $3 + let mEnd = mDone |> Option.defaultWith (fun _ -> $2.Range) + let mAll = unionRanges mDo mEnd let seqPt = DebugPointAtBinding.NoneAtDo // any attributes prior to the 'let' are left free, e.g. become top-level attributes // associated with the module, 'main' function or assembly depending on their target - BindingSetPreAttrs(mDoKwd, false, false, (fun attrs vis -> attrs, [mkSynDoBinding (vis, mDoKwd, $2, bindingSetRange)]), bindingSetRange), $2 } + BindingSetPreAttrs(mDo, false, false, (fun attrs vis -> attrs, [mkSynDoBinding (vis, mDo, $2, mAll)]), mAll), $2 } /* The bindings in a class type definition */ @@ -2739,7 +2742,7 @@ hardwhiteDefnBindingsTerminator: { let mToken = rhs parseState 1 // In LexFilter.fs the IN token could have been transformed to an ODECLEND one. let mIn = if (mToken.EndColumn - mToken.StartColumn) = 2 then Some mToken else None - (fun _ m -> ()), mIn } + (fun _ m -> ()), mIn, Some $1 } | recover { (fun kwd m -> @@ -2749,7 +2752,7 @@ hardwhiteDefnBindingsTerminator: | "use!" -> FSComp.SR.parsUnmatchedUseBang() | "use" -> FSComp.SR.parsUnmatchedUse() | _ (*"let" *) -> FSComp.SR.parsUnmatchedLet() - reportParseErrorAt m msg), None } + reportParseErrorAt m msg), None, None } /* An 'extern' DllImport function definition in C-style syntax */ cPrototype: @@ -3611,7 +3614,7 @@ moreBinders: SynExprAndBang(spBind, $1, true, $2, $4, m, { EqualsRange = mEquals; InKeyword = Some mIn }) :: $6 } | OAND_BANG headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let - { let report, mIn = $5 + { let report, mIn, _ = $5 report "and!" (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let mEquals = rhs parseState 3 @@ -3652,8 +3655,8 @@ declExpr: mkLocalBindings (unionRanges m (rhs parseState 3), hwlb, mIn, arbExpr ("declExpr3", (rhs parseState 3))) } | hardwhiteDoBinding %prec expr_let - { let e = snd $1 - SynExpr.Do(e, unionRanges (rhs parseState 1).StartRange e.Range) } + { let (BindingSetPreAttrs(_, _, _, _, m)), e = $1 + SynExpr.Do(e, m) } | anonMatchingExpr %prec expr_function { $1 } @@ -3769,143 +3772,143 @@ declExpr: { raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsAssertIsNotFirstClassValue()) } | WHILE declExpr doToken typedSequentialExprBlock doneDeclEnd - { let mWhileHeader = unionRanges (rhs parseState 1) $2.Range + { let mWhile = rhs parseState 1 + let mWhileHeader = unionRanges mWhile $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader - let mWhileAll = unionRanges (rhs parseState 1) $4.Range - SynExpr.While(spWhile, $2, $4, mWhileAll) } + SynExpr.While(spWhile, $2, $4, unionRanges mWhile $5) } | WHILE declExpr doToken typedSequentialExprBlock recover - { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWhile()) - let mWhileHeader = unionRanges (rhs parseState 1) $2.Range + { let mWhile = rhs parseState 1 + if not $5 then reportParseErrorAt mWhile (FSComp.SR.parsUnexpectedEndOfFileWhile ()) + let mWhileHeader = unionRanges mWhile $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader - let mWhileAll = unionRanges (rhs parseState 1) $4.Range - exprFromParseError (SynExpr.While(spWhile, $2, $4, mWhileAll)) } + let mWhileAll = unionRanges mWhile $4.Range + SynExpr.While(spWhile, $2, $4, mWhileAll) } | WHILE declExpr doToken error doneDeclEnd - { // silent recovery - let mWhileHeader = unionRanges (rhs parseState 1) $2.Range + { let mWhile = rhs parseState 1 + let mExpr = $2.Range + let mWhileHeader = unionRanges mWhile mExpr let spWhile = DebugPointAtWhile.Yes mWhileHeader - let mWhileBodyArb = unionRanges (rhs parseState 4) (rhs parseState 5) - let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 5) - SynExpr.While(spWhile, $2, arbExpr ("whileBody1", mWhileBodyArb), mWhileAll) } + let mWhileBodyArb = rhs parseState 4 + SynExpr.While(spWhile, $2, arbExpr ("whileBody1", mWhileBodyArb), unionRanges mWhile $5) } | WHILE declExpr recover - { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsWhileDoExpected()) - let mWhileHeader = unionRanges (rhs parseState 1) $2.Range + { let mWhile = rhs parseState 1 + reportParseErrorAt mWhile (FSComp.SR.parsWhileDoExpected ()) + let mExpr = $2.Range + let mWhileHeader = unionRanges mWhile mExpr let spWhile = DebugPointAtWhile.Yes mWhileHeader - let mWhileBodyArb = rhs parseState 3 - let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 3) - exprFromParseError (SynExpr.While(spWhile, $2, arbExpr ("whileBody2", mWhileBodyArb), mWhileAll)) } + SynExpr.While(spWhile, $2, arbExpr ("whileBody2", mExpr.EndRange), mWhileHeader) } | WHILE recover - { if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWhile()) - arbExpr ("whileLoop1", rhs parseState 1) } + { let mWhile = rhs parseState 1 + if not $2 then reportParseErrorAt mWhile (FSComp.SR.parsUnexpectedEndOfFileWhile ()) + let spWhile = DebugPointAtWhile.Yes mWhile + let expr1 = arbExpr ("whileLoop1", mWhile.EndRange) + let expr2 = arbExpr ("whileLoop2", mWhile.EndRange) + SynExpr.While(spWhile, expr1, expr2, mWhile) } | WHILE error doneDeclEnd - { //silent recovery - let mWhileHeader = rhs parseState 1 - let spWhile = DebugPointAtWhile.Yes mWhileHeader - let mWhileBodyArb = rhs parseState 3 - let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 3) - exprFromParseError (SynExpr.While(spWhile, arbExpr ("whileGuard1", mWhileHeader), arbExpr ("whileBody3", mWhileBodyArb), mWhileAll)) } + { let mWhile = rhs parseState 1 + let spWhile = DebugPointAtWhile.Yes mWhile + let mWhileBodyArb = rhs parseState 2 + let expr1 = arbExpr ("whileGuard1", mWhile.EndRange) + let expr2 = arbExpr ("whileBody3", mWhileBodyArb.EndRange) + SynExpr.While(spWhile, expr1, expr2, unionRanges mWhile $3) } | FOR forLoopBinder doToken typedSequentialExprBlock doneDeclEnd { let mFor = rhs parseState 1 let mDo = rhs parseState 3 let spFor = DebugPointAtFor.Yes mFor - let (a, b, _, spIn) = $2 - SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, $4, unionRanges (rhs parseState 1) $4.Range) } + let (pat, expr, _, spIn) = $2 + SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, pat, expr, $4, unionRanges mFor $5) } | FOR forLoopBinder doToken typedSequentialExprBlock ends_coming_soon_or_recover - { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 + if not $5 then reportParseErrorAt mFor (FSComp.SR.parsUnexpectedEndOfFileFor ()) let spFor = DebugPointAtFor.Yes mFor - let (a, b, _, spIn) = $2 - let mForLoopAll = unionRanges (rhs parseState 1) $4.Range - SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, $4, mForLoopAll) } + let (pat, expr, _, spIn) = $2 + SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, pat, expr, $4, unionRanges mFor $4.Range) } | FOR forLoopBinder doToken error doneDeclEnd - { // Silent recovery - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor - let (a, b, _, spIn) = $2 - let mForLoopBodyArb = rhs parseState 5 - let mForLoopAll = rhs2 parseState 1 5 - SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, arbExpr ("forLoopBody2a", mForLoopBodyArb), mForLoopAll) } + let (pat, expr, _, spIn) = $2 + let bodyExpr = arbExpr ("forLoopBody2a", rhs parseState 4) + SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, pat, expr, bodyExpr, unionRanges mFor $5) } | FOR forLoopBinder doToken ends_coming_soon_or_recover - { if not $4 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsExpectedExpressionAfterToken()) - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 + if not $4 then reportParseErrorAt mFor (FSComp.SR.parsExpectedExpressionAfterToken ()) let spFor = DebugPointAtFor.Yes mFor - let (a, b, _, spIn) = $2 - let mForLoopBodyArb = rhs parseState 3 - let mForLoopAll = rhs2 parseState 1 3 - SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, arbExpr ("forLoopBody2", mForLoopBodyArb), mForLoopAll) } + let (pat, expr, _, spIn) = $2 + let mDo = rhs parseState 3 + let bodyExpr = arbExpr ("forLoopBody2", mDo.EndRange) + SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, pat, expr, bodyExpr, unionRanges mFor mDo) } | FOR forLoopBinder ends_coming_soon_or_recover - { let (a, b, ok, spIn) = $2 - if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsForDoExpected()) - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 + let (pat, expr, ok, spIn) = $2 + if not $3 then reportParseErrorAt mFor (FSComp.SR.parsForDoExpected ()) let spFor = DebugPointAtFor.Yes mFor - let mForLoopBodyArb = rhs parseState 3 - let mForLoopAll = rhs2 parseState 1 3 - SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, arbExpr ("forLoopBody1", mForLoopBodyArb), mForLoopAll) } + let mExpr = expr.Range + let mForLoopBodyArb = mExpr.EndRange + let bodyExpr = arbExpr ("forLoopBody1", mForLoopBodyArb) + SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, pat, expr, bodyExpr, unionRanges mFor mForLoopBodyArb) } | FOR forLoopBinder opt_OBLOCKSEP arrowThenExprR %prec expr_let - { let spFor = DebugPointAtFor.Yes(rhs parseState 1) - let (a, b, _, spIn) = $2 - SynExpr.ForEach(spFor, spIn, SeqExprOnly true, true, a, b, $4, unionRanges (rhs parseState 1) $4.Range) } + { let mFor = rhs parseState 1 + let spFor = DebugPointAtFor.Yes mFor + let (pat, expr, _, spIn) = $2 + SynExpr.ForEach(spFor, spIn, SeqExprOnly true, true, pat, expr, $4, unionRanges mFor $4.Range) } | FOR forLoopRange doToken typedSequentialExprBlock doneDeclEnd { let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor - let (a, b, c, d, e, spTo) = $2 - let mForLoopAll = unionRanges (rhs parseState 1) $4.Range - SynExpr.For(spFor, spTo, a, b, c, d, e, $4, mForLoopAll) } + let (a, b, c, d, exprTo, spTo) = $2 + SynExpr.For(spFor, spTo, a, b, c, d, exprTo, $4, unionRanges mFor $5) } | FOR forLoopRange doToken typedSequentialExprBlock recover - { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) - // Still produce an expression - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 + if not $5 then reportParseErrorAt mFor (FSComp.SR.parsUnexpectedEndOfFileFor ()) let spFor = DebugPointAtFor.Yes mFor - let (a, b, c, d, e, spTo) = $2 - let mForLoopAll = unionRanges (rhs parseState 1) $4.Range - exprFromParseError (SynExpr.For(spFor, spTo, a, b, c, d, e, $4, mForLoopAll)) } + let (a, b, c, d, exprTo, spTo) = $2 + SynExpr.For(spFor, spTo, a, b, c, d, exprTo, $4, unionRanges mFor $4.Range) } | FOR forLoopRange doToken error doneDeclEnd - { // silent recovery - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor - let (a, b, c, d, e, spTo) = $2 - let mForLoopBodyArb = rhs parseState 5 - let mForLoopAll = rhs2 parseState 1 5 - SynExpr.For(spFor, spTo, a, b, c, d, e, arbExpr ("declExpr11", mForLoopBodyArb), mForLoopAll) } + let (a, b, c, d, exprTo, spTo) = $2 + let mForLoopBodyArb = rhs parseState 4 + let bodyExpr = arbExpr ("declExpr11", mForLoopBodyArb) + SynExpr.For(spFor, spTo, a, b, c, d, exprTo, bodyExpr, unionRanges mFor $5) } | FOR forLoopRange doToken recover - { if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 + if not $4 then reportParseErrorAt mFor (FSComp.SR.parsUnexpectedEndOfFileFor ()) let spFor = DebugPointAtFor.Yes mFor - let (a, b, c, d, e, spTo) = $2 - let mForLoopBodyArb = rhs parseState 3 - let mForLoopAll = rhs2 parseState 1 3 - exprFromParseError (SynExpr.For(spFor, spTo, a, b, c, d, e, arbExpr ("declExpr11", mForLoopBodyArb), mForLoopAll)) } + let (a, b, c, d, exprTo, spTo) = $2 + let mDo = rhs parseState 3 + let bodyExpr = arbExpr ("declExpr11", mDo.EndRange) + SynExpr.For(spFor, spTo, a, b, c, d, exprTo, bodyExpr, rhs2 parseState 1 3) } | FOR forLoopRange recover - { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 + if not $3 then reportParseErrorAt mFor (FSComp.SR.parsUnexpectedEndOfFileFor ()) let spFor = DebugPointAtFor.Yes mFor - let (a, b, c, d, e, spTo) = $2 - let mForLoopBodyArb = (rhs parseState 2).EndRange - let mForLoopAll = rhs2 parseState 1 2 - exprFromParseError (SynExpr.For(spFor, spTo, a, b, c, d, e, arbExpr ("declExpr11", mForLoopBodyArb), mForLoopAll)) } + let (a, b, c, d, exprTo, spTo) = $2 + let mExpr = exprTo.Range + let bodyExpr = arbExpr ("declExpr11", mExpr.EndRange) + SynExpr.For(spFor, spTo, a, b, c, d, exprTo, bodyExpr, unionRanges mFor mExpr) } | FOR error doToken typedSequentialExprBlock doneDeclEnd - { // silent recovery - let mFor = rhs parseState 1 + { let mFor = rhs parseState 1 let spToFake = DebugPointAtInOrTo.Yes mFor - let mForLoopAll = unionRanges (rhs parseState 1) $4.Range let spFor = DebugPointAtFor.Yes mFor - SynExpr.For(spFor, spToFake, mkSynId mFor "_loopVar", None, arbExpr ("startLoopRange1", mFor), true, arbExpr ("endLoopRange1", rhs parseState 3), $4, mForLoopAll) } + let expr1 = arbExpr ("startLoopRange1", mFor) + let expr2 = arbExpr ("endLoopRange1", rhs parseState 3) + SynExpr.For(spFor, spToFake, mkSynId mFor "_loopVar", None, expr1, true, expr2, $4, unionRanges mFor $4.Range) } | FOR ends_coming_soon_or_recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsIdentifierExpected()) @@ -3952,7 +3955,7 @@ declExpr: SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) } | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let - { let report, mIn = $5 + { let report, mIn, _ = $5 report (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let mEquals = rhs parseState 3 @@ -4881,15 +4884,17 @@ arrowThenExprR: forLoopBinder: | parenPattern IN declExpr - { ($1, $3, true, DebugPointAtInOrTo.Yes(rhs parseState 2)) } + { $1, $3, true, DebugPointAtInOrTo.Yes(rhs parseState 2) } | parenPattern IN ends_coming_soon_or_recover - { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedExpressionAfterToken()) - ($1, arbExpr ("forLoopBinder", (rhs parseState 2)), false, DebugPointAtInOrTo.Yes(rhs parseState 2)) } + { let mIn = rhs parseState 2 + if not $3 then reportParseErrorAt mIn (FSComp.SR.parsExpectedExpressionAfterToken ()) + $1, arbExpr ("forLoopBinder1", mIn.EndRange), false, DebugPointAtInOrTo.Yes mIn } | parenPattern ends_coming_soon_or_recover - { if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInOrEqualExpected()) - ($1, arbExpr ("forLoopBinder2", (rhs parseState 1).EndRange), false, DebugPointAtInOrTo.Yes(rhs parseState 2)) } + { let mPat = rhs parseState 1 + if not $2 then reportParseErrorAt mPat (FSComp.SR.parsInOrEqualExpected ()) + $1, arbExpr ("forLoopBinder2", mPat.EndRange), false, DebugPointAtInOrTo.Yes(rhs parseState 2) } forLoopRange: | parenPattern EQUALS declExpr forLoopDirection declExpr @@ -6239,8 +6244,10 @@ doToken: | ODO { } doneDeclEnd: - | DONE { } - | ODECLEND { } /* DONE gets thrown away by the lexfilter in favour of ODECLEND */ + | DONE + { rhs parseState 1 } + | ODECLEND + { $1 } structOrBegin: | STRUCT diff --git a/tests/service/data/SyntaxTree/Expression/Do 01.fs b/tests/service/data/SyntaxTree/Expression/Do 01.fs new file mode 100644 index 00000000000..9f04145fbfe --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Do 01.fs @@ -0,0 +1,6 @@ +module Module + +do + 1 + +2 diff --git a/tests/service/data/SyntaxTree/Expression/Do 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Do 01.fs.bsl new file mode 100644 index 00000000000..bbac8331c5c --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Do 01.fs.bsl @@ -0,0 +1,11 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Do 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr (Do (Const (Int32 1, (4,4--4,5)), (3,0--4,5)), (3,0--4,5)); + Expr (Const (Int32 2, (6,0--6,1)), (6,0--6,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Do 02.fs b/tests/service/data/SyntaxTree/Expression/Do 02.fs new file mode 100644 index 00000000000..8213e30e28a --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Do 02.fs @@ -0,0 +1,7 @@ +module Module + +do + 1 +done + +2 diff --git a/tests/service/data/SyntaxTree/Expression/Do 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Do 02.fs.bsl new file mode 100644 index 00000000000..a1c56a5016b --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Do 02.fs.bsl @@ -0,0 +1,11 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Do 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr (Do (Const (Int32 1, (4,4--4,5)), (3,0--5,4)), (3,0--5,4)); + Expr (Const (Int32 2, (7,0--7,1)), (7,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/For 01.fs b/tests/service/data/SyntaxTree/Expression/For 01.fs new file mode 100644 index 00000000000..23ec889a20d --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/For 01.fs @@ -0,0 +1,6 @@ +module Module + +for _ in 1 do + 2 + +3 diff --git a/tests/service/data/SyntaxTree/Expression/For 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/For 01.fs.bsl new file mode 100644 index 00000000000..97d7c7cb03e --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/For 01.fs.bsl @@ -0,0 +1,15 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/For 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (ForEach + (Yes (3,0--3,3), Yes (3,6--3,8), SeqExprOnly false, true, + Wild (3,4--3,5), Const (Int32 1, (3,9--3,10)), + Const (Int32 2, (4,4--4,5)), (3,0--4,5)), (3,0--4,5)); + Expr (Const (Int32 3, (6,0--6,1)), (6,0--6,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/For 02.fs b/tests/service/data/SyntaxTree/Expression/For 02.fs new file mode 100644 index 00000000000..6c19445689e --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/For 02.fs @@ -0,0 +1,7 @@ +module Module + +for _ in 1 do + 2 +done + +3 diff --git a/tests/service/data/SyntaxTree/Expression/For 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/For 02.fs.bsl new file mode 100644 index 00000000000..aad044dcf30 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/For 02.fs.bsl @@ -0,0 +1,15 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/For 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (ForEach + (Yes (3,0--3,3), Yes (3,6--3,8), SeqExprOnly false, true, + Wild (3,4--3,5), Const (Int32 1, (3,9--3,10)), + Const (Int32 2, (4,4--4,5)), (3,0--5,4)), (3,0--5,4)); + Expr (Const (Int32 3, (7,0--7,1)), (7,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/While 01.fs b/tests/service/data/SyntaxTree/Expression/While 01.fs new file mode 100644 index 00000000000..4787c61a89d --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/While 01.fs @@ -0,0 +1,6 @@ +module Module + +while 1 do + 2 + +3 diff --git a/tests/service/data/SyntaxTree/Expression/While 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/While 01.fs.bsl new file mode 100644 index 00000000000..e8039cbe2cf --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/While 01.fs.bsl @@ -0,0 +1,14 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/While 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (While + (Yes (3,0--3,7), Const (Int32 1, (3,6--3,7)), + Const (Int32 2, (4,4--4,5)), (3,0--4,5)), (3,0--4,5)); + Expr (Const (Int32 3, (6,0--6,1)), (6,0--6,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/While 02.fs b/tests/service/data/SyntaxTree/Expression/While 02.fs new file mode 100644 index 00000000000..59fd8f2ae25 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/While 02.fs @@ -0,0 +1,7 @@ +module Module + +while 1 do + 2 +done + +3 diff --git a/tests/service/data/SyntaxTree/Expression/While 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/While 02.fs.bsl new file mode 100644 index 00000000000..99e63d5e069 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/While 02.fs.bsl @@ -0,0 +1,14 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/While 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (While + (Yes (3,0--3,7), Const (Int32 1, (3,6--3,7)), + Const (Int32 2, (4,4--4,5)), (3,0--5,4)), (3,0--5,4)); + Expr (Const (Int32 3, (7,0--7,1)), (7,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) From d3dfe199a90868ecdf3822d5e52957477e799113 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 12 Jun 2023 18:34:08 +0200 Subject: [PATCH 2/2] Use match --- src/Compiler/pars.fsy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index aa740772ca0..9784dee0c33 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -2712,7 +2712,7 @@ hardwhiteDoBinding: | ODO typedSequentialExprBlock hardwhiteDefnBindingsTerminator { let mDo = rhs parseState 1 let _, _, mDone = $3 - let mEnd = mDone |> Option.defaultWith (fun _ -> $2.Range) + let mEnd = match mDone with Some m -> m | _ -> $2.Range let mAll = unionRanges mDo mEnd let seqPt = DebugPointAtBinding.NoneAtDo // any attributes prior to the 'let' are left free, e.g. become top-level attributes