diff --git a/Tests/RegexTests/RenderDSLTests.swift b/Tests/RegexTests/RenderDSLTests.swift new file mode 100644 index 000000000..4d244e2cc --- /dev/null +++ b/Tests/RegexTests/RenderDSLTests.swift @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import XCTest +import _RegexParser +@_spi(PatternConverter) @testable +import _StringProcessing + +class RenderDSLTests: XCTestCase {} + +func testConversion( + _ regex: String, + _ expectedDSL: String, + file: StaticString = #file, line: UInt = #line +) throws { + let ast = try _RegexParser.parse(regex, .semantic, .traditional) + let actualDSL = renderAsBuilderDSL(ast: ast)._trimmingSuffix(while: \.isWhitespace) + XCTAssertEqual(actualDSL, expectedDSL[...], file: file, line: line) +} + +extension RenderDSLTests { + func testSimpleConversions() throws { + try testConversion(#"ab+c"#, """ + Regex { + "a" + OneOrMore { + "b" + } + "c" + } + """) + + try testConversion(#"(?:a*)b?(c+)"#, """ + Regex { + ZeroOrMore { + "a" + } + Optionally { + "b" + } + Capture { + OneOrMore { + "c" + } + } + } + """) + + try testConversion(#"\d+"#, """ + Regex { + OneOrMore { + .digit + } + } + """) + try XCTExpectFailure("Invalid leading dot syntax in non-initial position") { + try testConversion(#":\d:"#, """ + Regex { + ":" + CharacterClass.digit + ":" + } + """) + } + } + + func testOptions() throws { + try XCTExpectFailure("Options like '(?i)' aren't converted") { + try testConversion(#"(?i)abc"#, """ + Regex { + "abc" + }.ignoresCase() + """) + } + + try XCTExpectFailure("Options like '(?i:...)' aren't converted") { + try testConversion(#"(?i:abc)"#, """ + Regex { + "abc" + }.ignoresCase() + """) + } + } + + func testAlternations() throws { + try testConversion(#"a|b"#, """ + Regex { + ChoiceOf { + "a" + "b" + } + } + """) + + try XCTExpectFailure("Concatenations in alternations aren't grouped") { + try testConversion(#"\da|b"#, """ + Regex { + ChoiceOf { + Regex { + .digit + "a" + } + "bc" + } + } + """) + } + } +} diff --git a/Tests/RegexTests/UTS18Tests.swift b/Tests/RegexTests/UTS18Tests.swift index 7306632da..bf41c5f2e 100644 --- a/Tests/RegexTests/UTS18Tests.swift +++ b/Tests/RegexTests/UTS18Tests.swift @@ -62,7 +62,7 @@ fileprivate func expectFirstMatch( } #if os(Linux) -func XCTExpectFailure(_ message: String? = nil, body: () -> Void) {} +func XCTExpectFailure(_ message: String? = nil, body: () throws -> Void) rethrows {} #endif // MARK: - Basic Unicode Support: Level 1