From 819f9d25eb0c6ca16683e3cb57f061c93498622f Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Tue, 8 Feb 2022 14:19:57 -0500 Subject: [PATCH] Move backtracking into `OneOf` (#108) * wip * wip * wip * docs * readme * format * readme * fix * wip Co-authored-by: Brandon Williams --- .../swift-parsing-benchmark.xcscheme | 6 + README.md | 159 +++-- Sources/Parsing/Builders/Variadics.swift | 588 ++++++++---------- Sources/Parsing/Internal/Deprecations.swift | 126 ++-- Sources/Parsing/Parser.swift | 38 +- Sources/Parsing/Parsers/Double.swift | 18 +- Sources/Parsing/Parsers/Filter.swift | 6 +- Sources/Parsing/Parsers/FlatMap.swift | 10 +- Sources/Parsing/Parsers/Many.swift | 7 +- Sources/Parsing/Parsers/OneOf.swift | 34 +- Sources/Parsing/Parsers/OneOfMany.swift | 4 +- Sources/Parsing/Parsers/Pipe.swift | 10 +- Sources/Parsing/Parsers/PrefixThrough.swift | 1 - Sources/Parsing/Parsers/PrefixUpTo.swift | 1 - .../URLRequestRouter/URLRequestRouter.swift | 6 +- .../swift-parsing-benchmark/XCTestLogs.swift | 6 +- .../VariadicsGenerator.swift | 12 +- Tests/ParsingTests/ConditionalTests.swift | 2 +- Tests/ParsingTests/DoubleTests.swift | 24 +- Tests/ParsingTests/FilterTests.swift | 2 +- Tests/ParsingTests/ManyTests.swift | 4 +- Tests/ParsingTests/PipeTests.swift | 2 +- Tests/ParsingTests/SkipTests.swift | 4 +- 23 files changed, 535 insertions(+), 535 deletions(-) diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/swift-parsing-benchmark.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/swift-parsing-benchmark.xcscheme index 5c3a11edbd..468d153bf2 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/swift-parsing-benchmark.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/swift-parsing-benchmark.xcscheme @@ -64,6 +64,12 @@ ReferencedContainer = "container:"> + + + + -[Getting started](#getting-started)
-[Design](#design)
-[Benchmarks](#benchmarks)
-[Documentation](#documentation)
-[Other libraries](#other-libraries)
-[License](#license)
+* **Ergonomics**: Accomplish all of the above in a simple, fluent API that can succinctly describe your parsing problem. + +--- + +* [Motivation](#motivation) +* [Getting started](#getting-started) +* [Design](#design) + * [Protocol](#protocol) + * [Result builders](#result-builders) + * [Backtracking](#backtracking) + * [Low-level versus high-level](#low-level-versus-high-level) +* [Benchmarks](#benchmarks) +* [Documentation](#documentation) +* [Other libraries](#other-libraries) +* [License](#license) ## Learn More @@ -325,6 +333,53 @@ accountingNumber.parse("100") // 100 accountingNumber.parse("(100)") // -100 ``` +### Backtracking + +Backtracking, which is the process of restoring the input to its original value when a parser fails, is very useful, but can lead to performance issues and cause parsers' logic to be more complicated than necessary. For this reason parsers are not required to backtrack. + +Instead, if backtracking is needed, one should use the `OneOf` parser, which can try many parsers one after another on a single input, backtracking after each failure and taking the first that succeeds. + +By not requiring backtracking of each individual parser we can greatly simply the logic of parsers and we can coalesce all backtracking logic into just a single parser, the ``OneOf`` parser. + +For example, the `.flatMap` operator allows one to sequence two parsers where the second parser can use the output of the first in order to customize its logic. If we required `.flatMap` to do its own backtracking we would be forced to insert logic after each step of the sequence. By not requiring backtracking we can replace 12 lines of code with a single line of code: + +```swift +public func parse(_ input: inout Upstream.Input) -> NewParser.Output? { + // let original = input + // guard let newParser = self.upstream.parse(&input).map(self.transform) + // else { + // input = original + // return nil + // } + // guard let output = newParser.parse(&input) + // else { + // input = original + // return nil + // } + // return output + self.upstream.parse(&input).map(self.transform)?.parse(&input) +} +``` + +If used naively, backtracking can lead to less performant parsing code. For example, if we wanted to parse two integers from a string that were separated by either a dash "-" or slash "/", then we could write this as: + +```swift +OneOf { + Parser { Int.parser(); "-"; Int.parser() } // 1️⃣ + Parser { Int.parser(); "/"; Int.parser() } // 2️⃣ +} +``` + +However, parsing slash-separated integers is not going to be performant because it will first run the entire 1️⃣ parser until it fails, then backtrack to the beginning, and run the 2️⃣ parser. In particular, the first integer will get parsed twice, unnecessarily repeating that work. On the other hand, we can factor out the common work of the parser and localize the backtracking `OneOf` work to make a much more performant parser: + +```swift +Parse { + Int.parser() + OneOf { "-"; "/" } + Int.parser() +} +``` + ### Low-level versus high-level The library makes it easy to choose which abstraction level you want to work on. Both low-level and high-level have their pros and cons. @@ -354,7 +409,7 @@ let city = OneOf { "San José".map { City.sanJose } } -var input = "San José,123" +var input = "San José,123"[...] city.parse(&input) // => City.sanJose input // => ",123" ``` @@ -365,8 +420,9 @@ However, we are incurring the cost of parsing `Substring` for this entire parser let city = OneOf { "London".utf8.map { City.london } "New York".utf8.map { City.newYork } - FromSubstring { "San José" } - .map { City.sanJose } + FromSubstring { + "San José".map { City.sanJose } + } } ``` @@ -411,48 +467,47 @@ Apple M1 Pro (10 cores, 8 performance and 2 efficiency) name time std iterations ---------------------------------------------------------------------------------- -Arithmetic.Parser 875.000 ns ± 14.28 % 1000000 -BinaryData.Parser 42.000 ns ± 49.90 % 1000000 -Bool.Bool.init 41.000 ns ± 69.81 % 1000000 -Bool.Bool.parser 42.000 ns ± 101.10 % 1000000 -Bool.Scanner.scanBool 1041.000 ns ± 25.21 % 1000000 -Color.Parser 167.000 ns ± 30.96 % 1000000 -CSV.Parser 1523520.500 ns ± 1.04 % 936 -CSV.Ad hoc mutating methods 884937.000 ns ± 2.66 % 1596 -Date.Parser 5916.000 ns ± 7.87 % 241818 -Date.DateFormatter 25875.000 ns ± 4.64 % 53747 -Date.ISO8601DateFormatter 35208.000 ns ± 3.84 % 39862 -HTTP.HTTP 4667.000 ns ± 5.52 % 293069 -JSON.Parser 5750.000 ns ± 5.47 % 241193 -JSON.JSONSerialization 1792.000 ns ± 9.81 % 775360 -Numerics.Int.init 41.000 ns ± 79.50 % 1000000 -Numerics.Int.parser 42.000 ns ± 114.44 % 1000000 -Numerics.Scanner.scanInt 125.000 ns ± 30.24 % 1000000 -Numerics.Comma separated: Int.parser 3191125.000 ns ± 0.52 % 439 -Numerics.Comma separated: Scanner.scanInt 49040750.000 ns ± 0.31 % 29 -Numerics.Comma separated: String.split 14892750.000 ns ± 1.48 % 93 -Numerics.Double.init 42.000 ns ± 50.32 % 1000000 -Numerics.Double.parser 84.000 ns ± 32.73 % 1000000 -Numerics.Scanner.scanDouble 167.000 ns ± 28.19 % 1000000 -Numerics.Comma separated: Double.parser 9773042.000 ns ± 0.37 % 143 -Numerics.Comma separated: Scanner.scanDouble 50911166.000 ns ± 0.25 % 27 -Numerics.Comma separated: String.split 18814187.500 ns ± 0.86 % 74 -PrefixUpTo.Parser: Substring 232792.000 ns ± 1.35 % 6019 -PrefixUpTo.Parser: UTF8 14333.000 ns ± 2.20 % 97942 -PrefixUpTo.String.range(of:) 43084.000 ns ± 1.51 % 32462 -PrefixUpTo.Scanner.scanUpToString 47500.000 ns ± 1.35 % 29437 -Race.Parser 26167.000 ns ± 3.20 % 53718 -README Example.Parser: Substring 3708.000 ns ± 5.99 % 374793 -README Example.Parser: UTF8 917.000 ns ± 13.42 % 1000000 -README Example.Ad hoc 3542.000 ns ± 8.50 % 389301 -README Example.Scanner 14250.000 ns ± 3.49 % 98115 -Routing.Parser 14125.000 ns ± 4.03 % 98087 -String Abstractions.Substring 892458.000 ns ± 1.21 % 1572 -String Abstractions.UTF8 36916.000 ns ± 3.35 % 37882 -UUID.UUID.init 209.000 ns ± 24.03 % 1000000 -UUID.UUID.parser 375.000 ns ± 8.28 % 1000000 -Xcode Logs.Parser 3512500.000 ns ± 0.58 % 395 - +Arithmetic.Parser 875.000 ns ± 6.62 % 1000000 +BinaryData.Parser 42.000 ns ± 65.97 % 1000000 +Bool.Bool.init 41.000 ns ± 51.08 % 1000000 +Bool.Bool.parser 42.000 ns ± 67.27 % 1000000 +Bool.Scanner.scanBool 1041.000 ns ± 25.01 % 1000000 +Color.Parser 167.000 ns ± 37.06 % 1000000 +CSV.Parser 1532729.000 ns ± 0.96 % 940 +CSV.Ad hoc mutating methods 890833.000 ns ± 1.87 % 1587 +Date.Parser 5875.000 ns ± 17.11 % 238925 +Date.DateFormatter 25708.000 ns ± 2.39 % 54215 +Date.ISO8601DateFormatter 34458.000 ns ± 1.97 % 40623 +HTTP.HTTP 4666.000 ns ± 7.73 % 303258 +JSON.Parser 5458.000 ns ± 11.09 % 251888 +JSON.JSONSerialization 1792.000 ns ± 7.42 % 774211 +Numerics.Int.init 41.000 ns ± 72.85 % 1000000 +Numerics.Int.parser 42.000 ns ± 51.11 % 1000000 +Numerics.Scanner.scanInt 125.000 ns ± 39.76 % 1000000 +Numerics.Comma separated: Int.parser 3192834.000 ns ± 1.20 % 435 +Numerics.Comma separated: Scanner.scanInt 49151000.000 ns ± 0.18 % 28 +Numerics.Comma separated: String.split 14851083.000 ns ± 0.95 % 93 +Numerics.Double.init 42.000 ns ± 89.65 % 1000000 +Numerics.Double.parser 84.000 ns ± 36.70 % 1000000 +Numerics.Scanner.scanDouble 167.000 ns ± 19.24 % 1000000 +Numerics.Comma separated: Double.parser 9382208.000 ns ± 0.45 % 149 +Numerics.Comma separated: Scanner.scanDouble 50533499.500 ns ± 0.29 % 28 +Numerics.Comma separated: String.split 18779167.000 ns ± 0.62 % 75 +PrefixUpTo.Parser: Substring 232625.000 ns ± 0.83 % 6010 +PrefixUpTo.Parser: UTF8 14333.000 ns ± 2.35 % 98132 +PrefixUpTo.String.range(of:) 43084.000 ns ± 1.65 % 32429 +PrefixUpTo.Scanner.scanUpToString 47459.000 ns ± 2.09 % 29435 +Race.Parser 26167.000 ns ± 14.93 % 53359 +README Example.Parser: Substring 3666.000 ns ± 4.01 % 378810 +README Example.Parser: UTF8 916.000 ns ± 6.78 % 1000000 +README Example.Ad hoc 3542.000 ns ± 7.38 % 396249 +README Example.Scanner 14291.000 ns ± 3.38 % 98263 +Routing.Parser 14333.000 ns ± 3.40 % 97289 +String Abstractions.Substring 887833.000 ns ± 0.69 % 1577 +String Abstractions.UTF8 37375.000 ns ± 1.56 % 37455 +UUID.UUID.init 209.000 ns ± 14.23 % 1000000 +UUID.UUID.parser 375.000 ns ± 60.49 % 1000000 +Xcode Logs.Parser 3499833.000 ns ± 0.71 % 401 ``` ## Documentation diff --git a/Sources/Parsing/Builders/Variadics.swift b/Sources/Parsing/Builders/Variadics.swift index df538f83ff..302151f4ff 100644 --- a/Sources/Parsing/Builders/Variadics.swift +++ b/Sources/Parsing/Builders/Variadics.swift @@ -18,12 +18,10 @@ extension Parsers { P0.Output, P1.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input) else { - input = original return nil } return (o0, o1) @@ -57,12 +55,10 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P0.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input) else { - input = original return nil } return (o0) @@ -96,12 +92,10 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P1.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input) else { - input = original return nil } return (o1) @@ -136,12 +130,10 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input) else { - input = original return nil } return () @@ -179,13 +171,11 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), let o2 = p2.parse(&input) else { - input = original return nil } return (o0, o1, o2) @@ -223,13 +213,11 @@ extension Parsers { P0.Output, P1.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), let _ = p2.parse(&input) else { - input = original return nil } return (o0, o1) @@ -267,13 +255,11 @@ extension Parsers { P0.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), let o2 = p2.parse(&input) else { - input = original return nil } return (o0, o2) @@ -311,13 +297,11 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P0.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), let _ = p2.parse(&input) else { - input = original return nil } return (o0) @@ -355,13 +339,11 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), let o2 = p2.parse(&input) else { - input = original return nil } return (o1, o2) @@ -399,13 +381,11 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P1.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), let _ = p2.parse(&input) else { - input = original return nil } return (o1) @@ -443,13 +423,11 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P2.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), let o2 = p2.parse(&input) else { - input = original return nil } return (o2) @@ -488,13 +466,11 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), let _ = p2.parse(&input) else { - input = original return nil } return () @@ -536,14 +512,12 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), let o2 = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3) @@ -585,14 +559,12 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), let o2 = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o0, o1, o2) @@ -634,14 +606,12 @@ extension Parsers { P1.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), let _ = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o0, o1, o3) @@ -683,14 +653,12 @@ extension Parsers { P0.Output, P1.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), let _ = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o0, o1) @@ -732,14 +700,12 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), let o2 = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o0, o2, o3) @@ -781,14 +747,12 @@ extension Parsers { P0.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), let o2 = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o0, o2) @@ -830,14 +794,12 @@ extension Parsers { P0.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), let _ = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o0, o3) @@ -879,14 +841,12 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P0.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), let _ = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o0) @@ -928,14 +888,12 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), let o2 = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o1, o2, o3) @@ -977,14 +935,12 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), let o2 = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o1, o2) @@ -1026,14 +982,12 @@ extension Parsers { P1.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), let _ = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o1, o3) @@ -1075,14 +1029,12 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P1.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), let _ = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o1) @@ -1124,14 +1076,12 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), let o2 = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o2, o3) @@ -1173,14 +1123,12 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P2.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), let o2 = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return (o2) @@ -1222,14 +1170,12 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P3.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), let _ = p2.parse(&input), let o3 = p3.parse(&input) else { - input = original return nil } return (o3) @@ -1272,14 +1218,12 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), let _ = p2.parse(&input), let _ = p3.parse(&input) else { - input = original return nil } return () @@ -1325,7 +1269,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1333,7 +1276,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3, o4) @@ -1379,7 +1321,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1387,7 +1328,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3) @@ -1433,7 +1373,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1441,7 +1380,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o1, o2, o4) @@ -1487,7 +1425,6 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1495,7 +1432,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o1, o2) @@ -1541,7 +1477,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1549,7 +1484,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o1, o3, o4) @@ -1595,7 +1529,6 @@ extension Parsers { P1.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1603,7 +1536,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o1, o3) @@ -1649,7 +1581,6 @@ extension Parsers { P1.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1657,7 +1588,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o1, o4) @@ -1703,7 +1633,6 @@ extension Parsers { P0.Output, P1.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -1711,7 +1640,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o1) @@ -1757,7 +1685,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -1765,7 +1692,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o2, o3, o4) @@ -1811,7 +1737,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -1819,7 +1744,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o2, o3) @@ -1865,7 +1789,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -1873,7 +1796,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o2, o4) @@ -1919,7 +1841,6 @@ extension Parsers { P0.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -1927,7 +1848,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o2) @@ -1973,7 +1893,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -1981,7 +1900,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o3, o4) @@ -2027,7 +1945,6 @@ extension Parsers { P0.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -2035,7 +1952,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0, o3) @@ -2081,7 +1997,6 @@ extension Parsers { P0.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -2089,7 +2004,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o0, o4) @@ -2135,7 +2049,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P0.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -2143,7 +2056,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o0) @@ -2189,7 +2101,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2197,7 +2108,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o1, o2, o3, o4) @@ -2243,7 +2153,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2251,7 +2160,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o1, o2, o3) @@ -2297,7 +2205,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2305,7 +2212,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o1, o2, o4) @@ -2351,7 +2257,6 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2359,7 +2264,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o1, o2) @@ -2405,7 +2309,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2413,7 +2316,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o1, o3, o4) @@ -2459,7 +2361,6 @@ extension Parsers { P1.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2467,7 +2368,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o1, o3) @@ -2513,7 +2413,6 @@ extension Parsers { P1.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2521,7 +2420,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o1, o4) @@ -2567,7 +2465,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P1.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -2575,7 +2472,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o1) @@ -2621,7 +2517,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2629,7 +2524,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o2, o3, o4) @@ -2675,7 +2569,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2683,7 +2576,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o2, o3) @@ -2729,7 +2621,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2737,7 +2628,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o2, o4) @@ -2783,7 +2673,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P2.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2791,7 +2680,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o2) @@ -2837,7 +2725,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2845,7 +2732,6 @@ extension Parsers { let o3 = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o3, o4) @@ -2891,7 +2777,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P3.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2899,7 +2784,6 @@ extension Parsers { let o3 = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return (o3) @@ -2945,7 +2829,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -2953,7 +2836,6 @@ extension Parsers { let _ = p3.parse(&input), let o4 = p4.parse(&input) else { - input = original return nil } return (o4) @@ -3000,7 +2882,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -3008,7 +2889,6 @@ extension Parsers { let _ = p3.parse(&input), let _ = p4.parse(&input) else { - input = original return nil } return () @@ -3058,7 +2938,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3067,7 +2946,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3, o4, o5) @@ -3117,7 +2995,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3126,7 +3003,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3, o4) @@ -3176,7 +3052,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3185,7 +3060,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3, o5) @@ -3235,7 +3109,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3244,7 +3117,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o3) @@ -3294,7 +3166,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3303,7 +3174,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o4, o5) @@ -3353,7 +3223,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3362,7 +3231,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o4) @@ -3412,7 +3280,6 @@ extension Parsers { P2.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3421,7 +3288,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2, o5) @@ -3471,7 +3337,6 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3480,7 +3345,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o2) @@ -3530,7 +3394,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3539,7 +3402,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o3, o4, o5) @@ -3589,7 +3451,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3598,7 +3459,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o3, o4) @@ -3648,7 +3508,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3657,7 +3516,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o3, o5) @@ -3707,7 +3565,6 @@ extension Parsers { P1.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3716,7 +3573,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o3) @@ -3766,7 +3622,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3775,7 +3630,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o4, o5) @@ -3825,7 +3679,6 @@ extension Parsers { P1.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3834,7 +3687,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1, o4) @@ -3884,7 +3736,6 @@ extension Parsers { P1.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3893,7 +3744,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o1, o5) @@ -3943,7 +3793,6 @@ extension Parsers { P0.Output, P1.Output )? { - let original = input guard let o0 = p0.parse(&input), let o1 = p1.parse(&input), @@ -3952,7 +3801,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o1) @@ -4002,7 +3850,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4011,7 +3858,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o2, o3, o4, o5) @@ -4061,7 +3907,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4070,7 +3915,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o2, o3, o4) @@ -4120,7 +3964,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4129,7 +3972,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o2, o3, o5) @@ -4179,7 +4021,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4188,7 +4029,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o2, o3) @@ -4238,7 +4078,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4247,7 +4086,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o2, o4, o5) @@ -4297,7 +4135,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4306,7 +4143,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o2, o4) @@ -4356,7 +4192,6 @@ extension Parsers { P2.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4365,7 +4200,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o2, o5) @@ -4415,7 +4249,6 @@ extension Parsers { P0.Output, P2.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4424,7 +4257,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o2) @@ -4474,7 +4306,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4483,7 +4314,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o3, o4, o5) @@ -4533,7 +4363,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4542,7 +4371,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o3, o4) @@ -4592,7 +4420,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4601,7 +4428,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o3, o5) @@ -4651,7 +4477,6 @@ extension Parsers { P0.Output, P3.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4660,7 +4485,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o3) @@ -4710,7 +4534,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4719,7 +4542,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o4, o5) @@ -4769,7 +4591,6 @@ extension Parsers { P0.Output, P4.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4778,7 +4599,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0, o4) @@ -4828,7 +4648,6 @@ extension Parsers { P0.Output, P5.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4837,7 +4656,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o0, o5) @@ -4887,7 +4705,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P0.Output )? { - let original = input guard let o0 = p0.parse(&input), let _ = p1.parse(&input), @@ -4896,7 +4713,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o0) @@ -4946,7 +4762,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -4955,7 +4770,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o2, o3, o4, o5) @@ -5005,7 +4819,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5014,7 +4827,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o2, o3, o4) @@ -5064,7 +4876,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5073,7 +4884,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o2, o3, o5) @@ -5123,7 +4933,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5132,7 +4941,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o2, o3) @@ -5182,7 +4990,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5191,7 +4998,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o2, o4, o5) @@ -5241,7 +5047,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5250,7 +5055,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o2, o4) @@ -5300,7 +5104,6 @@ extension Parsers { P2.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5309,7 +5112,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o2, o5) @@ -5359,7 +5161,6 @@ extension Parsers { P1.Output, P2.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5368,7 +5169,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o2) @@ -5418,7 +5218,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5427,7 +5226,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o3, o4, o5) @@ -5477,7 +5275,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5486,7 +5283,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o3, o4) @@ -5536,7 +5332,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5545,7 +5340,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o3, o5) @@ -5595,7 +5389,6 @@ extension Parsers { P1.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5604,7 +5397,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o3) @@ -5654,7 +5446,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5663,7 +5454,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o4, o5) @@ -5713,7 +5503,6 @@ extension Parsers { P1.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5722,7 +5511,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1, o4) @@ -5772,7 +5560,6 @@ extension Parsers { P1.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5781,7 +5568,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o1, o5) @@ -5831,7 +5617,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P1.Output )? { - let original = input guard let _ = p0.parse(&input), let o1 = p1.parse(&input), @@ -5840,7 +5625,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o1) @@ -5890,7 +5674,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -5899,7 +5682,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o2, o3, o4, o5) @@ -5949,7 +5731,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -5958,7 +5739,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o2, o3, o4) @@ -6008,7 +5788,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6017,7 +5796,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o2, o3, o5) @@ -6067,7 +5845,6 @@ extension Parsers { P2.Output, P3.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6076,7 +5853,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o2, o3) @@ -6126,7 +5902,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6135,7 +5910,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o2, o4, o5) @@ -6185,7 +5959,6 @@ extension Parsers { P2.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6194,7 +5967,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o2, o4) @@ -6244,7 +6016,6 @@ extension Parsers { P2.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6253,7 +6024,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o2, o5) @@ -6303,7 +6073,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P2.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6312,7 +6081,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o2) @@ -6362,7 +6130,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6371,7 +6138,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o3, o4, o5) @@ -6421,7 +6187,6 @@ extension Parsers { P3.Output, P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6430,7 +6195,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o3, o4) @@ -6480,7 +6244,6 @@ extension Parsers { P3.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6489,7 +6252,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o3, o5) @@ -6539,7 +6301,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P3.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6548,7 +6309,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o3) @@ -6598,7 +6358,6 @@ extension Parsers { P4.Output, P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6607,7 +6366,6 @@ extension Parsers { let o4 = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o4, o5) @@ -6657,7 +6415,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P4.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6666,7 +6423,6 @@ extension Parsers { let o4 = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return (o4) @@ -6716,7 +6472,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( P5.Output )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6725,7 +6480,6 @@ extension Parsers { let _ = p4.parse(&input), let o5 = p5.parse(&input) else { - input = original return nil } return (o5) @@ -6776,7 +6530,6 @@ extension Parsers { @inlinable public func parse(_ input: inout P0.Input) -> ( )? { - let original = input guard let _ = p0.parse(&input), let _ = p1.parse(&input), @@ -6785,7 +6538,6 @@ extension Parsers { let _ = p4.parse(&input), let _ = p5.parse(&input) else { - input = original return nil } return () @@ -6817,8 +6569,16 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } return nil } } @@ -6852,9 +6612,21 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } return nil } } @@ -6892,10 +6664,26 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } return nil } } @@ -6937,11 +6725,31 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } - if let output = self.p4.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } + var i4 = input + if let output = self.p4.parse(&i4) { + input = i4 + return output + } return nil } } @@ -6987,12 +6795,36 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } - if let output = self.p4.parse(&input) { return output } - if let output = self.p5.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } + var i4 = input + if let output = self.p4.parse(&i4) { + input = i4 + return output + } + var i5 = input + if let output = self.p5.parse(&i5) { + input = i5 + return output + } return nil } } @@ -7042,13 +6874,41 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } - if let output = self.p4.parse(&input) { return output } - if let output = self.p5.parse(&input) { return output } - if let output = self.p6.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } + var i4 = input + if let output = self.p4.parse(&i4) { + input = i4 + return output + } + var i5 = input + if let output = self.p5.parse(&i5) { + input = i5 + return output + } + var i6 = input + if let output = self.p6.parse(&i6) { + input = i6 + return output + } return nil } } @@ -7090,9 +6950,7 @@ extension Parsers { { public let p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7 - @inlinable public init( - _ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7 - ) { + @inlinable public init(_ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7) { self.p0 = p0 self.p1 = p1 self.p2 = p2 @@ -7104,14 +6962,46 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } - if let output = self.p4.parse(&input) { return output } - if let output = self.p5.parse(&input) { return output } - if let output = self.p6.parse(&input) { return output } - if let output = self.p7.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } + var i4 = input + if let output = self.p4.parse(&i4) { + input = i4 + return output + } + var i5 = input + if let output = self.p5.parse(&i5) { + input = i5 + return output + } + var i6 = input + if let output = self.p6.parse(&i6) { + input = i6 + return output + } + var i7 = input + if let output = self.p7.parse(&i7) { + input = i7 + return output + } return nil } } @@ -7156,9 +7046,7 @@ extension Parsers { { public let p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8 - @inlinable public init( - _ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7, _ p8: P8 - ) { + @inlinable public init(_ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7, _ p8: P8) { self.p0 = p0 self.p1 = p1 self.p2 = p2 @@ -7171,15 +7059,51 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } - if let output = self.p4.parse(&input) { return output } - if let output = self.p5.parse(&input) { return output } - if let output = self.p6.parse(&input) { return output } - if let output = self.p7.parse(&input) { return output } - if let output = self.p8.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } + var i4 = input + if let output = self.p4.parse(&i4) { + input = i4 + return output + } + var i5 = input + if let output = self.p5.parse(&i5) { + input = i5 + return output + } + var i6 = input + if let output = self.p6.parse(&i6) { + input = i6 + return output + } + var i7 = input + if let output = self.p7.parse(&i7) { + input = i7 + return output + } + var i8 = input + if let output = self.p8.parse(&i8) { + input = i8 + return output + } return nil } } @@ -7227,10 +7151,7 @@ extension Parsers { { public let p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9 - @inlinable public init( - _ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7, _ p8: P8, - _ p9: P9 - ) { + @inlinable public init(_ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7, _ p8: P8, _ p9: P9) { self.p0 = p0 self.p1 = p1 self.p2 = p2 @@ -7244,16 +7165,56 @@ extension Parsers { } @inlinable public func parse(_ input: inout P0.Input) -> P0.Output? { - if let output = self.p0.parse(&input) { return output } - if let output = self.p1.parse(&input) { return output } - if let output = self.p2.parse(&input) { return output } - if let output = self.p3.parse(&input) { return output } - if let output = self.p4.parse(&input) { return output } - if let output = self.p5.parse(&input) { return output } - if let output = self.p6.parse(&input) { return output } - if let output = self.p7.parse(&input) { return output } - if let output = self.p8.parse(&input) { return output } - if let output = self.p9.parse(&input) { return output } + var i0 = input + if let output = self.p0.parse(&i0) { + input = i0 + return output + } + var i1 = input + if let output = self.p1.parse(&i1) { + input = i1 + return output + } + var i2 = input + if let output = self.p2.parse(&i2) { + input = i2 + return output + } + var i3 = input + if let output = self.p3.parse(&i3) { + input = i3 + return output + } + var i4 = input + if let output = self.p4.parse(&i4) { + input = i4 + return output + } + var i5 = input + if let output = self.p5.parse(&i5) { + input = i5 + return output + } + var i6 = input + if let output = self.p6.parse(&i6) { + input = i6 + return output + } + var i7 = input + if let output = self.p7.parse(&i7) { + input = i7 + return output + } + var i8 = input + if let output = self.p8.parse(&i8) { + input = i8 + return output + } + var i9 = input + if let output = self.p9.parse(&i9) { + input = i9 + return output + } return nil } } @@ -7261,8 +7222,7 @@ extension Parsers { extension OneOfBuilder { @inlinable public static func buildBlock( - _ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7, _ p8: P8, - _ p9: P9 + _ p0: P0, _ p1: P1, _ p2: P2, _ p3: P3, _ p4: P4, _ p5: P5, _ p6: P6, _ p7: P7, _ p8: P8, _ p9: P9 ) -> Parsers.OneOf10 { Parsers.OneOf10(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) } diff --git a/Sources/Parsing/Internal/Deprecations.swift b/Sources/Parsing/Internal/Deprecations.swift index e7aeafa1c4..c0966e6fc6 100644 --- a/Sources/Parsing/Internal/Deprecations.swift +++ b/Sources/Parsing/Internal/Deprecations.swift @@ -271,17 +271,10 @@ extension Parsers { @inlinable public func parse(_ input: inout A.Input) -> B.Output? { - let original = input - - guard self.a.parse(&input) != nil + guard + self.a.parse(&input) != nil, + let b = self.b.parse(&input) else { return nil } - - guard let b = self.b.parse(&input) - else { - input = original - return nil - } - return b } } @@ -304,17 +297,10 @@ extension Parsers { @inlinable @inline(__always) public func parse(_ input: inout A.Input) -> A.Output? { - let original = input - - guard let a = self.a.parse(&input) + guard + let a = self.a.parse(&input), + self.b.parse(&input) != nil else { return nil } - - guard self.b.parse(&input) != nil - else { - input = original - return nil - } - return a } } @@ -617,14 +603,10 @@ extension Parsers { @inlinable public func parse(_ input: inout A.Input) -> (A.Output, B.Output)? { - let original = input - guard let a = self.a.parse(&input) + guard + let a = self.a.parse(&input), + let b = self.b.parse(&input) else { return nil } - guard let b = self.b.parse(&input) - else { - input = original - return nil - } return (a, b) } } @@ -655,14 +637,10 @@ extension Parsers { @inlinable public func parse(_ input: inout AB.Input) -> (A, B, C.Output)? { - let original = input - guard let (a, b) = self.ab.parse(&input) + guard + let (a, b) = self.ab.parse(&input), + let c = self.c.parse(&input) else { return nil } - guard let c = self.c.parse(&input) - else { - input = original - return nil - } return (a, b, c) } } @@ -693,14 +671,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABC.Input) -> (A, B, C, D.Output)? { - let original = input - guard let (a, b, c) = self.abc.parse(&input) + guard + let (a, b, c) = self.abc.parse(&input), + let d = self.d.parse(&input) else { return nil } - guard let d = self.d.parse(&input) - else { - input = original - return nil - } return (a, b, c, d) } } @@ -731,14 +705,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCD.Input) -> (A, B, C, D, E.Output)? { - let original = input - guard let (a, b, c, d) = self.abcd.parse(&input) + guard + let (a, b, c, d) = self.abcd.parse(&input), + let e = self.e.parse(&input) else { return nil } - guard let e = self.e.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e) } } @@ -769,14 +739,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCDE.Input) -> (A, B, C, D, E, F.Output)? { - let original = input - guard let (a, b, c, d, e) = self.abcde.parse(&input) + guard + let (a, b, c, d, e) = self.abcde.parse(&input), + let f = self.f.parse(&input) else { return nil } - guard let f = self.f.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e, f) } } @@ -807,14 +773,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCDEF.Input) -> (A, B, C, D, E, F, G.Output)? { - let original = input - guard let (a, b, c, d, e, f) = self.abcdef.parse(&input) + guard + let (a, b, c, d, e, f) = self.abcdef.parse(&input), + let g = self.g.parse(&input) else { return nil } - guard let g = self.g.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e, f, g) } } @@ -845,14 +807,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCDEFG.Input) -> (A, B, C, D, E, F, G, H.Output)? { - let original = input - guard let (a, b, c, d, e, f, g) = self.abcdefg.parse(&input) + guard + let (a, b, c, d, e, f, g) = self.abcdefg.parse(&input), + let h = self.h.parse(&input) else { return nil } - guard let h = self.h.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e, f, g, h) } } @@ -883,14 +841,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCDEFGH.Input) -> (A, B, C, D, E, F, G, H, I.Output)? { - let original = input - guard let (a, b, c, d, e, f, g, h) = self.abcdefgh.parse(&input) + guard + let (a, b, c, d, e, f, g, h) = self.abcdefgh.parse(&input), + let i = self.i.parse(&input) else { return nil } - guard let i = self.i.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e, f, g, h, i) } } @@ -921,14 +875,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCDEFGHI.Input) -> (A, B, C, D, E, F, G, H, I, J.Output)? { - let original = input - guard let (a, b, c, d, e, f, g, h, i) = self.abcdefghi.parse(&input) + guard + let (a, b, c, d, e, f, g, h, i) = self.abcdefghi.parse(&input), + let j = self.j.parse(&input) else { return nil } - guard let j = self.j.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e, f, g, h, i, j) } } @@ -960,14 +910,10 @@ extension Parsers { @inlinable public func parse(_ input: inout ABCDEFGHIJ.Input) -> (A, B, C, D, E, F, G, H, I, J, K.Output)? { - let original = input - guard let (a, b, c, d, e, f, g, h, i, j) = self.abcdefghij.parse(&input) + guard + let (a, b, c, d, e, f, g, h, i, j) = self.abcdefghij.parse(&input), + let k = self.k.parse(&input) else { return nil } - guard let k = self.k.parse(&input) - else { - input = original - return nil - } return (a, b, c, d, e, f, g, h, i, j, k) } } diff --git a/Sources/Parsing/Parser.swift b/Sources/Parsing/Parser.swift index 0c689976df..1cb52844db 100644 --- a/Sources/Parsing/Parser.swift +++ b/Sources/Parsing/Parser.swift @@ -19,9 +19,41 @@ /// precondition(input == " Hello world") /// ``` /// -/// It is best practice for a parser to _not_ consume any of the input if it fails to produce an -/// output. This allows for "backtracking", which means if a parser fails then another parser can -/// try on the original input. +/// # Backtracking +/// +/// Parsers may consume input even if they throw an error, and you should not depend on a parser +/// restoring the input to the original value when failing. The process of restoring the input to the +/// original value is known as "backtracking". Backtracking can be handy when wanting to try many parsers +/// on the same input, and one usually does this by using the ``OneOf`` parser, which automatically backtracks +/// when one of its parsers fails. +/// +/// By not requiring backtracking of each individual parser we can greatly simply the logic of parsers and we +/// can coalesce all backtracking logic into just a single parser, the ``OneOf`` parser. For example, the +/// `.flatMap` operator allows one to sequence two parsers where the second parser can use the output of the +/// first in order to customize its logic. If we required `.flatMap` to do its own backtracking we would be +/// forced to insert logic after each step of the sequence. By not requiring backtracking we can replace 12 +/// lines of code with a single line of code: +/// +/// ```swift +/// public func parse(_ input: inout Upstream.Input) -> NewParser.Output? { +/// // let original = input +/// // guard let newParser = self.upstream.parse(&input).map(self.transform) +/// // else { +/// // input = original +/// // return nil +/// // } +/// // guard let output = newParser.parse(&input) +/// // else { +/// // input = original +/// // return nil +/// // } +/// // return output +/// self.upstream.parse(&input).map(self.transform)?.parse(&input) +/// } +/// ``` +/// +/// If you really need backtracking capabilities then we recommend using the ``OneOf`` parser to control +/// backtracking. public protocol Parser { /// The kind of values this parser receives. associatedtype Input diff --git a/Sources/Parsing/Parsers/Double.swift b/Sources/Parsing/Parsers/Double.swift index d512e3079f..70aef2d764 100644 --- a/Sources/Parsing/Parsers/Double.swift +++ b/Sources/Parsing/Parsers/Double.swift @@ -180,14 +180,10 @@ extension Parsers { @inlinable public func parse(_ input: inout Input) -> Double? { - let original = input guard let s = input.parseFloat(), let n = Double(String(decoding: s, as: UTF8.self)) - else { - input = original - return nil - } + else { return nil } return n } } @@ -207,14 +203,10 @@ extension Parsers { @inlinable public func parse(_ input: inout Input) -> Float? { - let original = input guard let s = input.parseFloat(), let n = Float(String(decoding: s, as: UTF8.self)) - else { - input = original - return nil - } + else { return nil } return n } } @@ -235,14 +227,10 @@ extension Parsers { @inlinable public func parse(_ input: inout Input) -> Float80? { - let original = input guard let s = input.parseFloat(), let n = Float80(String(decoding: s, as: UTF8.self)) - else { - input = original - return nil - } + else { return nil } return n } } diff --git a/Sources/Parsing/Parsers/Filter.swift b/Sources/Parsing/Parsers/Filter.swift index f8b768eb9c..005ecbec47 100644 --- a/Sources/Parsing/Parsers/Filter.swift +++ b/Sources/Parsing/Parsers/Filter.swift @@ -31,14 +31,10 @@ extension Parsers { @inlinable public func parse(_ input: inout Upstream.Input) -> Upstream.Output? { - let original = input guard let output = self.upstream.parse(&input), self.predicate(output) - else { - input = original - return nil - } + else { return nil } return output } } diff --git a/Sources/Parsing/Parsers/FlatMap.swift b/Sources/Parsing/Parsers/FlatMap.swift index 3b2004afe9..2eff237d18 100644 --- a/Sources/Parsing/Parsers/FlatMap.swift +++ b/Sources/Parsing/Parsers/FlatMap.swift @@ -37,15 +37,7 @@ extension Parsers { @inlinable public func parse(_ input: inout Upstream.Input) -> NewParser.Output? { - let original = input - guard let newParser = self.upstream.parse(&input).map(self.transform) - else { return nil } - guard let output = newParser.parse(&input) - else { - input = original - return nil - } - return output + self.upstream.parse(&input).map(self.transform)?.parse(&input) } } } diff --git a/Sources/Parsing/Parsers/Many.swift b/Sources/Parsing/Parsers/Many.swift index f2ceaae254..401c34d4b3 100644 --- a/Sources/Parsing/Parsers/Many.swift +++ b/Sources/Parsing/Parsers/Many.swift @@ -76,7 +76,6 @@ where @inlinable public func parse(_ input: inout Element.Input) -> Result? { - let original = input var rest = input #if DEBUG var previous = input @@ -118,10 +117,8 @@ where } #endif } - guard count >= self.minimum else { - input = original - return nil - } + guard count >= self.minimum + else { return nil } input = rest return result } diff --git a/Sources/Parsing/Parsers/OneOf.swift b/Sources/Parsing/Parsers/OneOf.swift index a1037f6dfa..3f55c613b4 100644 --- a/Sources/Parsing/Parsers/OneOf.swift +++ b/Sources/Parsing/Parsers/OneOf.swift @@ -11,7 +11,7 @@ /// ``` /// /// If you are optionally parsing input that should coalesce into some default, you can skip the -/// optionality and instead use ``OneOf`` with an ``Always`` parser, given a default: +/// optionality and instead use `OneOf` with an ``Always`` parser, given a default: /// /// ```swift /// enum Currency { case eur, gbp, usd, unknown } @@ -23,6 +23,38 @@ /// Always(Currency.unknown) /// } /// ``` +/// +/// # Backtracking +/// +/// `OneOf` will automatically revert any changes made to input when one of its parsers fails. This +/// process is often called "backtracking", and simplifies the logic of other parsers by not forcing them +/// to be responsible for their own backtracking when they fail. +/// +/// If used naively, backtracking can lead to less performant parsing code. For example, if we wanted to parse +/// two integers from a string that were separated by either a dash "-" or slash "/", then we could write this +/// as: +/// +/// ```swift +/// OneOf { +/// Parser { Int.parser(); "-"; Int.parser() } // 1️⃣ +/// Parser { Int.parser(); "/"; Int.parser() } // 2️⃣ +/// } +/// ``` +/// +/// However, parsing slash-separated integers is not going to be performant because it will first run the +/// entire 1️⃣ parser until it fails, then backtrack to the beginning, and run the 2️⃣ parser. In particular, +/// the first integer will get parsed twice, unnecessarily repeating that work. +/// +/// On the other hand, we can factor out the common work of the parser and localize the backtracking `OneOf` +/// work to make a much more performant parser: +/// +/// ```swift +/// Parse { +/// Int.parser() +/// OneOf { "-"; "/" } +/// Int.parser() +/// } +/// ``` public struct OneOf: Parser where Parsers: Parser { public let parsers: Parsers diff --git a/Sources/Parsing/Parsers/OneOfMany.swift b/Sources/Parsing/Parsers/OneOfMany.swift index 3f8271f5aa..60aa710f29 100644 --- a/Sources/Parsing/Parsers/OneOfMany.swift +++ b/Sources/Parsing/Parsers/OneOfMany.swift @@ -29,7 +29,9 @@ extension Parsers { @inline(__always) public func parse(_ input: inout Parsers.Input) -> Parsers.Output? { for parser in self.parsers { - if let output = parser.parse(&input) { + var i = input + if let output = parser.parse(&i) { + input = i return output } } diff --git a/Sources/Parsing/Parsers/Pipe.swift b/Sources/Parsing/Parsers/Pipe.swift index 64e8510ee9..6f385351a1 100644 --- a/Sources/Parsing/Parsers/Pipe.swift +++ b/Sources/Parsing/Parsers/Pipe.swift @@ -34,18 +34,10 @@ extension Parsers { @inlinable public func parse(_ input: inout Upstream.Input) -> Downstream.Output? { - let original = input - guard var downstreamInput = self.upstream.parse(&input) else { return nil } - guard let output = self.downstream.parse(&downstreamInput) - else { - input = original - return nil - } - - return output + return self.downstream.parse(&downstreamInput) } } } diff --git a/Sources/Parsing/Parsers/PrefixThrough.swift b/Sources/Parsing/Parsers/PrefixThrough.swift index a1b97ac7b7..147e265c94 100644 --- a/Sources/Parsing/Parsers/PrefixThrough.swift +++ b/Sources/Parsing/Parsers/PrefixThrough.swift @@ -45,7 +45,6 @@ where } input.removeFirst() } - input = original return nil } } diff --git a/Sources/Parsing/Parsers/PrefixUpTo.swift b/Sources/Parsing/Parsers/PrefixUpTo.swift index 886de01be2..438e59ed73 100644 --- a/Sources/Parsing/Parsers/PrefixUpTo.swift +++ b/Sources/Parsing/Parsers/PrefixUpTo.swift @@ -43,7 +43,6 @@ where } input.removeFirst() } - input = original return nil } } diff --git a/Sources/swift-parsing-benchmark/URLRequestRouter/URLRequestRouter.swift b/Sources/swift-parsing-benchmark/URLRequestRouter/URLRequestRouter.swift index ed5dda4976..c65d7d33ef 100644 --- a/Sources/swift-parsing-benchmark/URLRequestRouter/URLRequestRouter.swift +++ b/Sources/swift-parsing-benchmark/URLRequestRouter/URLRequestRouter.swift @@ -213,15 +213,11 @@ @inlinable func parse(_ input: inout URLRequestData) -> Parsers.Output? { - let original = input guard let output = self.parsers.parse(&input), input.path.isEmpty, input.method == nil || Method.get.parse(&input) != nil - else { - input = original - return nil - } + else { return nil } return output } } diff --git a/Sources/swift-parsing-benchmark/XCTestLogs.swift b/Sources/swift-parsing-benchmark/XCTestLogs.swift index aed185712e..8ec877a4e1 100644 --- a/Sources/swift-parsing-benchmark/XCTestLogs.swift +++ b/Sources/swift-parsing-benchmark/XCTestLogs.swift @@ -66,8 +66,10 @@ struct TestCaseBody: Parser { input.removeFirst(filePathPrefix.count) guard - var failure = PrefixUpTo(filePathPrefix).parse(&input) - ?? PrefixUpTo("Test Case '-[".utf8).parse(&input) + var failure = OneOf({ + PrefixUpTo(filePathPrefix) + PrefixUpTo("Test Case '-[".utf8) + }).parse(&input) else { input = original return nil diff --git a/Sources/variadics-generator/VariadicsGenerator.swift b/Sources/variadics-generator/VariadicsGenerator.swift index 84e5be84e8..ea5f0ed2b5 100644 --- a/Sources/variadics-generator/VariadicsGenerator.swift +++ b/Sources/variadics-generator/VariadicsGenerator.swift @@ -120,12 +120,12 @@ struct VariadicsGenerator: ParsableCommand { outputForEach(0.. (\n") outputForEach(permutation.captureIndices, separator: ",\n") { " P\($0).Output" } - output("\n )? {\n let original = input\n guard\n ") + output("\n )? {\n guard\n ") outputForEach(0.. P0.Output? {") output("\n ") outputForEach(0..