@@ -107,20 +107,26 @@ func parseTest(
107
107
serializedCaptures. deallocate ( )
108
108
}
109
109
110
- func parseWithDelimitersTest(
111
- _ input: String , _ expecting: AST . Node ,
112
- file: StaticString = #file, line: UInt = #line
110
+ func delimiterLexingTest(
111
+ _ input: String , file: StaticString = #file, line: UInt = #line
113
112
) {
114
- // First try lexing.
115
- input. withCString { ptr in
116
- let ( contents, delim, end) = try ! lexRegex ( start: ptr,
117
- end: ptr + input. count)
118
- XCTAssertEqual ( end, ptr + input. count, file: file, line: line)
113
+ input. withCString ( encodedAs: UTF8 . self) { ptr in
114
+ let endPtr = ptr + input. utf8. count
115
+ let ( contents, delim, end) = try ! lexRegex ( start: ptr, end: endPtr)
116
+ XCTAssertEqual ( end, endPtr, file: file, line: line)
119
117
120
118
let ( parseContents, parseDelim) = droppingRegexDelimiters ( input)
121
119
XCTAssertEqual ( contents, parseContents, file: file, line: line)
122
120
XCTAssertEqual ( delim, parseDelim, file: file, line: line)
123
121
}
122
+ }
123
+
124
+ func parseWithDelimitersTest(
125
+ _ input: String , _ expecting: AST . Node ,
126
+ file: StaticString = #file, line: UInt = #line
127
+ ) {
128
+ // First try lexing.
129
+ delimiterLexingTest ( input, file: file, line: line)
124
130
125
131
let orig = try ! parseWithDelimiters ( input)
126
132
let ast = orig. root
@@ -199,6 +205,32 @@ func diagnosticTest(
199
205
}
200
206
}
201
207
208
+ func delimiterLexingDiagnosticTest(
209
+ _ input: String , _ expected: DelimiterLexError . Kind ,
210
+ syntax: SyntaxOptions = . traditional,
211
+ file: StaticString = #file, line: UInt = #line
212
+ ) {
213
+ do {
214
+ _ = try input. withCString { ptr in
215
+ try lexRegex ( start: ptr, end: ptr + input. count)
216
+ }
217
+ XCTFail ( """
218
+ Passed, but expected error: \( expected)
219
+ """ , file: file, line: line)
220
+ } catch let e as DelimiterLexError {
221
+ guard e. kind == expected else {
222
+ XCTFail ( """
223
+
224
+ Expected: \( expected)
225
+ Actual: \( e. kind)
226
+ """ , file: file, line: line)
227
+ return
228
+ }
229
+ } catch let e {
230
+ XCTFail ( " Unexpected error type: \( e) " , file: file, line: line)
231
+ }
232
+ }
233
+
202
234
func libswiftDiagnosticMessageTest(
203
235
_ input: String , _ expectedErr: String , file: StaticString = #file,
204
236
line: UInt = #line
@@ -1468,6 +1500,11 @@ extension RegexTests {
1468
1500
1469
1501
parseWithDelimitersTest ( " re'x*' " , zeroOrMore ( of: " x " ) )
1470
1502
1503
+ parseWithDelimitersTest ( #"re'🔥🇩🇰'"# , concat ( " 🔥 " , " 🇩🇰 " ) )
1504
+ parseWithDelimitersTest ( #"re'\🔥✅'"# , concat ( " 🔥 " , " ✅ " ) )
1505
+
1506
+ // Printable ASCII characters.
1507
+ delimiterLexingTest ( ##"re' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'"## )
1471
1508
// MARK: Parse not-equal
1472
1509
1473
1510
// Make sure dumping output correctly reflects differences in AST.
@@ -1886,6 +1923,16 @@ extension RegexTests {
1886
1923
diagnosticTest ( " (*LIMIT_DEPTH=-1 " , . expectedNumber( " " , kind: . decimal) )
1887
1924
}
1888
1925
1926
+ func testDelimiterLexingErrors( ) {
1927
+ delimiterLexingDiagnosticTest ( #"re'\\#n'"# , . endOfString)
1928
+ for i : UInt8 in 0x1 ..< 0x20 where i != 0xA && i != 0xD { // U+A & U+D are \n and \r.
1929
+ delimiterLexingDiagnosticTest ( " re' \( UnicodeScalar ( i) ) ' " , . unprintableASCII)
1930
+ }
1931
+ delimiterLexingDiagnosticTest ( " re' \n ' " , . endOfString)
1932
+ delimiterLexingDiagnosticTest ( " re' \r ' " , . endOfString)
1933
+ delimiterLexingDiagnosticTest ( " re' \u{7F} ' " , . unprintableASCII)
1934
+ }
1935
+
1889
1936
func testlibswiftDiagnostics( ) {
1890
1937
libswiftDiagnosticMessageTest (
1891
1938
" #/[x*/# " , " cannot parse regular expression: expected ']' " )
0 commit comments