diff --git a/Sources/_StringProcessing/ByteCodeGen+DSLList.swift b/Sources/_StringProcessing/ByteCodeGen+DSLList.swift index 4abf2b90..4d1290cd 100644 --- a/Sources/_StringProcessing/ByteCodeGen+DSLList.swift +++ b/Sources/_StringProcessing/ByteCodeGen+DSLList.swift @@ -369,6 +369,8 @@ fileprivate extension Compiler.ByteCodeGen { case .nonCapturingGroup(let kind): switch kind.ast { case .lookahead, .negativeLookahead, .lookbehind, .negativeLookbehind: + list.skipNode(&position) + position += 1 return false default: return _guaranteesForwardProgressImpl(list, position: &position) diff --git a/Tests/RegexTests/CompileTests.swift b/Tests/RegexTests/CompileTests.swift index 62812087..50cd675b 100644 --- a/Tests/RegexTests/CompileTests.swift +++ b/Tests/RegexTests/CompileTests.swift @@ -531,6 +531,7 @@ extension RegexTests { expectProgram(for: #"(?:\w|(?i))+"#, contains: [.moveCurrentPosition, .condBranchSamePosition]) expectProgram(for: #"(?:A*(?:b|c*))*"#, contains: [.moveCurrentPosition, .condBranchSamePosition]) expectProgram(for: #"(?:[^/]*(?:/|$))*"#, contains: [.moveCurrentPosition, .condBranchSamePosition]) + expectProgram(for: #"(?:(?!a)\d*)*"#, contains: [.moveCurrentPosition, .condBranchSamePosition]) // Bounded quantification, don't emit position checking expectProgram(for: #"(?:(?=a)){1,4}"#, doesNotContain: [.moveCurrentPosition, .condBranchSamePosition]) diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index 97532ff3..e1cfb298 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -2856,6 +2856,7 @@ extension RegexTests { expectCompletion(regex: #"(?:A*(?:b|c*))*"#, in: "ABC") expectCompletion(regex: #"^(?:(?:[^/]*(?:/|$))*)(?:[^/]*)$"#, in: "Sources/main.swift") + expectCompletion(regex: #"(?:(?!a)\d*)*"#, in: "A") } func testQuantifyOptimization() throws {