diff --git a/Sources/_StringProcessing/Regex/DSLList.swift b/Sources/_StringProcessing/Regex/DSLList.swift index 98e478de4..107348995 100644 --- a/Sources/_StringProcessing/Regex/DSLList.swift +++ b/Sources/_StringProcessing/Regex/DSLList.swift @@ -174,6 +174,7 @@ extension DSLList { func indexOfCoalescableAtom(startingAt position: Int, findLast: Bool = false) -> Int? { switch nodes[position] { case .concatenation(let children): + guard children.count > 0 else { return nil } var position = position + 1 if findLast { for _ in 0..<(children.count - 1) { diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift index 3611ee2c0..3bdc8a4e1 100644 --- a/Tests/RegexBuilderTests/RegexDSLTests.swift +++ b/Tests/RegexBuilderTests/RegexDSLTests.swift @@ -1672,7 +1672,30 @@ class RegexDSLTests: XCTestCase { """) } - + + func testManyConcatenatedComponents() throws { + let r = Regex { + #/a\n/# + Regex(verbatim: "/some/path") + #/\n/# + #/b\n/# + Regex(verbatim: "/some/path") + #/\n/# + #/c\n/# + Regex(verbatim: "/some/path") + #/\n/# + #/d\n/# + Regex(verbatim: "/some/path") + #/\n/# + #/e\n/# + Regex(verbatim: "/some/path") + #/\n/# + #/f/# + } + let input = "a\n/some/path\nb\n/some/path\nc\n/some/path\nd\n/some/path\ne\n/some/path\nf" + XCTAssertNotNil(try r.wholeMatch(in: input)) + } + func testRegexComponentBuilderResultType() { // Test that the user can declare a closure or computed property marked with // `@RegexComponentBuilder` with `Regex` as the result type.