Skip to content

Commit dae522b

Browse files
committed
Handle missing group specifier
Avoid crashing on '(?' by emitting a new diagnostic.
1 parent 3b5533f commit dae522b

File tree

3 files changed

+12
-2
lines changed

3 files changed

+12
-2
lines changed

Sources/_MatchingEngine/Regex/Parse/Diagnostics.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ enum ParseError: Error, Hashable {
2424

2525
case invalidPOSIXSetName(String)
2626
case emptyProperty
27+
28+
case expectedGroupSpecifier
2729
}
2830

2931
extension ParseError: CustomStringConvertible {
@@ -57,6 +59,8 @@ extension ParseError: CustomStringConvertible {
5759
return "invalid character set name: '\(n)'"
5860
case .emptyProperty:
5961
return "empty property"
62+
case .expectedGroupSpecifier:
63+
return "expected group specifier"
6064
}
6165
}
6266
}

Sources/_MatchingEngine/Regex/Parse/LexicalAnalysis.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,10 @@ extension Source {
502502
return .namedCapture(name)
503503
}
504504

505-
throw ParseError.misc(
506-
"Unknown group kind '(?\(src.peek()!)'")
505+
guard let next = src.peek() else {
506+
throw ParseError.expectedGroupSpecifier
507+
}
508+
throw ParseError.misc("Unknown group kind '(?\(next)'")
507509
}
508510

509511
// Explicitly spelled out PRCE2 syntax for some groups.

Tests/RegexTests/LexTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ extension RegexTests {
107107
diagnose(#"\p{a="#, expecting: .expected("}")) { try $0.lexBasicAtom() }
108108
diagnose(#"(?#"#, expecting: .expected(")")) { _ = try $0.lexComment() }
109109

110+
diagnose(#"(?"#, expecting: .expectedGroupSpecifier) {
111+
_ = try $0.lexGroupStart()
112+
}
113+
110114
// TODO: want to dummy print out source ranges, etc, test that.
111115
}
112116

0 commit comments

Comments
 (0)