Skip to content

Commit 70753ff

Browse files
committed
[Parse] Update for new regex compiler interface
Update to use the new `swiftCompilerLexRegexLiteral` & `swiftCompilerParseRegexLiteral` SPI entry points.
1 parent 1e35aaf commit 70753ff

File tree

2 files changed

+35
-53
lines changed

2 files changed

+35
-53
lines changed

SwiftCompilerSources/Sources/Parse/Regex.swift

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ import AST
1515
import Basic
1616

1717
#if canImport(_CompilerRegexParser)
18-
import _CompilerRegexParser
18+
@_spi(CompilerInterface) import _CompilerRegexParser
1919

2020
public func registerRegexParser() {
2121
Parser_registerRegexLiteralParsingFn(_RegexLiteralParsingFn)
2222
Parser_registerRegexLiteralLexingFn(_RegexLiteralLexingFn)
2323
}
2424

25-
/// Bridging between C++ lexer and _CompilerRegexParser.lexRegex()
25+
/// Bridging between C++ lexer and swiftCompilerLexRegexLiteral.
2626
///
2727
/// Attempt to lex a regex literal string.
2828
///
@@ -50,47 +50,29 @@ private func _RegexLiteralLexingFn(
5050
) -> /*CompletelyErroneous*/ CBool {
5151
let inputPtr = curPtrPtr.pointee
5252

53-
do {
54-
let (_, _, endPtr) = try lexRegex(start: inputPtr, end: bufferEndPtr)
55-
curPtrPtr.pointee = endPtr.assumingMemoryBound(to: CChar.self)
53+
guard let (resumePtr, error) = swiftCompilerLexRegexLiteral(
54+
start: inputPtr, bufferEnd: bufferEndPtr, mustBeRegex: mustBeRegex
55+
) else {
56+
// Not a regex literal, fallback without advancing the pointer.
5657
return false
57-
} catch let error as DelimiterLexError {
58-
if !mustBeRegex {
59-
// This token can be something else. Let the client fallback.
60-
return false;
61-
}
62-
if error.kind == .unknownDelimiter {
63-
// An unknown delimiter should be recovered from, as we may want to try
64-
// lex something else.
65-
return false
66-
}
58+
}
6759

60+
// Advance the current pointer.
61+
curPtrPtr.pointee = resumePtr.assumingMemoryBound(to: CChar.self)
62+
63+
if let error = error {
64+
// Emit diagnostic if diagnostics are enabled.
6865
if let diagEngine = DiagnosticEngine(bridged: bridgedDiagnosticEngine) {
69-
// Emit diagnostic.
7066
let startLoc = SourceLoc(
71-
locationInFile: UnsafeRawPointer(inputPtr).assumingMemoryBound(to: UInt8.self))!
72-
diagEngine.diagnose(startLoc, .regex_literal_parsing_error, "\(error)")
73-
}
74-
75-
// Advance the current pointer.
76-
curPtrPtr.pointee = error.resumePtr.assumingMemoryBound(to: CChar.self)
77-
78-
switch error.kind {
79-
case .unterminated, .multilineClosingNotOnNewline:
80-
// These can be recovered from.
81-
return false
82-
case .unprintableASCII, .invalidUTF8:
83-
// We don't currently have good recovery behavior for these.
84-
return true
85-
case .unknownDelimiter:
86-
fatalError("Already handled")
67+
locationInFile: error.location.assumingMemoryBound(to: UInt8.self))!
68+
diagEngine.diagnose(startLoc, .regex_literal_parsing_error, error.message)
8769
}
88-
} catch {
89-
fatalError("Should be a DelimiterLexError")
70+
return error.completelyErroneous
9071
}
72+
return false
9173
}
9274

93-
/// Bridging between C++ parser and _CompilerRegexParser.parseWithDelimiters()
75+
/// Bridging between C++ parser and swiftCompilerParseRegexLiteral.
9476
///
9577
/// - Parameters:
9678
/// - inputPtr: A null-terminated C string.
@@ -103,6 +85,8 @@ private func _RegexLiteralLexingFn(
10385
/// greater than or equal to `strlen(inputPtr)`.
10486
/// - bridgedDiagnosticBaseLoc: Source location of the start of the literal
10587
/// - bridgedDiagnosticEngine: Diagnostic engine to emit diagnostics.
88+
///
89+
/// - Returns: `true` if there was a parse error, `false` otherwise.
10690
public func _RegexLiteralParsingFn(
10791
_ inputPtr: UnsafePointer<CChar>,
10892
_ versionOut: UnsafeMutablePointer<CUnsignedInt>,
@@ -111,30 +95,27 @@ public func _RegexLiteralParsingFn(
11195
_ bridgedDiagnosticBaseLoc: BridgedSourceLoc,
11296
_ bridgedDiagnosticEngine: BridgedDiagnosticEngine
11397
) -> Bool {
114-
versionOut.pointee = currentRegexLiteralFormatVersion
115-
11698
let str = String(cString: inputPtr)
99+
let captureBuffer = UnsafeMutableRawBufferPointer(
100+
start: captureStructureOut, count: Int(captureStructureSize))
117101
do {
118-
let ast = try parseWithDelimiters(str)
119-
// Serialize the capture structure for later type inference.
120-
assert(captureStructureSize >= str.utf8.count)
121-
let buffer = UnsafeMutableRawBufferPointer(
122-
start: captureStructureOut, count: Int(captureStructureSize))
123-
ast.captureStructure.encode(to: buffer)
124-
return false;
125-
} catch {
102+
// FIXME: We need to plumb through the 'regexToEmit' result to the caller.
103+
// For now, it is the same as the input.
104+
let (_, version) = try swiftCompilerParseRegexLiteral(
105+
str, captureBufferOut: captureBuffer)
106+
versionOut.pointee = CUnsignedInt(version)
107+
return false
108+
} catch let error as CompilerParseError {
126109
var diagLoc = SourceLoc(bridged: bridgedDiagnosticBaseLoc)
127110
let diagEngine = DiagnosticEngine(bridged: bridgedDiagnosticEngine)
128-
if let _diagLoc = diagLoc,
129-
let locatedError = error as? LocatedErrorProtocol {
130-
let offset = str.utf8.distance(from: str.startIndex,
131-
to: locatedError.location.start)
111+
if let _diagLoc = diagLoc, let errorLoc = error.location {
112+
let offset = str.utf8.distance(from: str.startIndex, to: errorLoc)
132113
diagLoc = _diagLoc.advanced(by: offset)
133114
}
134-
diagEngine.diagnose(
135-
diagLoc, .regex_literal_parsing_error,
136-
"cannot parse regular expression: \(String(describing: error))")
115+
diagEngine.diagnose(diagLoc, .regex_literal_parsing_error, error.message)
137116
return true
117+
} catch {
118+
fatalError("Expected CompilerParseError")
138119
}
139120
}
140121

lib/Parse/ParseRegex.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ ParserResult<Expr> Parser::parseExprRegexLiteral() {
4343

4444
// Let the Swift library parse the contents, returning an error, or null if
4545
// successful.
46-
unsigned version;
46+
unsigned version = 0;
4747
auto capturesBuf = Context.AllocateUninitialized<uint8_t>(
4848
RegexLiteralExpr::getCaptureStructureSerializationAllocationSize(
4949
regexText.size()));
@@ -57,6 +57,7 @@ ParserResult<Expr> Parser::parseExprRegexLiteral() {
5757
if (hadError) {
5858
return makeParserResult(new (Context) ErrorExpr(loc));
5959
}
60+
assert(version >= 1);
6061
return makeParserResult(RegexLiteralExpr::createParsed(
6162
Context, loc, regexText, version, capturesBuf));
6263
}

0 commit comments

Comments
 (0)