Skip to content

Commit 2740e27

Browse files
authored
Experimental Regex Strawperson (use Swift in the parser) (swiftlang#40117)
[regex] Use Swift in the parser Add in a strawperson use of Swift by the parser, for future regex support.
1 parent 0603991 commit 2740e27

File tree

15 files changed

+120
-10
lines changed

15 files changed

+120
-10
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ ERROR(lex_unprintable_ascii_character,none,
107107
"unprintable ASCII character found in source file", ())
108108
ERROR(lex_invalid_utf8,none,
109109
"invalid UTF-8 found in source file", ())
110+
111+
NOTE(lex_experimental_regex_strawperson,none,
112+
"'%0'", (StringRef))
113+
110114
ERROR(lex_single_quote_string,none,
111115
"single-quoted string literal found, use '\"'", ())
112116
ERROR(lex_invalid_curly_quote,none,

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ namespace swift {
144144
/// PackageDescription version to compile for.
145145
version::Version PackageDescriptionVersion;
146146

147+
/// Enable experimental string processing
148+
bool EnableExperimentalRegex = false;
149+
147150
/// Disable API availability checking.
148151
bool DisableAvailabilityChecking = false;
149152

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ def disable_deserialization_recovery :
469469
Flag<["-"], "disable-deserialization-recovery">,
470470
HelpText<"Don't attempt to recover from missing xrefs (etc) in swiftmodules">;
471471

472+
def enable_experimental_regex :
473+
Flag<["-"], "enable-experimental-regex">,
474+
HelpText<"Enable experimental string processing">;
475+
472476
def disable_availability_checking : Flag<["-"],
473477
"disable-availability-checking">,
474478
HelpText<"Disable checking for potentially unavailable APIs">;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef EXPERIMENTAL_REGEX_BRIDGING
2+
#define EXPERIMENTAL_REGEX_BRIDGING
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
typedef const char *(* ParseRegexStrawperson)(const char *);
9+
10+
void Parser_registerParseRegexStrawperson(ParseRegexStrawperson fn);
11+
12+
#ifdef __cplusplus
13+
} // extern "C"
14+
#endif
15+
16+
#endif // EXPERIMENTAL_REGEX_BRIDGING
17+
18+
19+
//const char* experimental_regex_strawperson(const char *in);
20+

include/swift/Parse/Lexer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,15 @@ class Lexer {
607607
bool lexUnknown(bool EmitDiagnosticsIfToken);
608608

609609
NulCharacterKind getNulCharacterKind(const char *Ptr) const;
610+
611+
/// Emit diagnostics for single-quote string and suggest replacement
612+
/// with double-quoted equivalent.
613+
///
614+
/// Or, if we're in strawperson mode, we will emit a custom
615+
/// error message instead, determined by the Swift library.
616+
void diagnoseSingleQuoteStringLiteral(const char *TokStart,
617+
const char *TokEnd);
618+
610619
};
611620

612621
/// A lexer that can lex trivia into its pieces

include/swift/module.modulemap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ module OptimizerBridging {
88
export *
99
}
1010

11+
module ExperimentalRegexBridging {
12+
header "Parse/ExperimentalRegexBridging.h"
13+
export *
14+
}

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
471471
= A->getOption().matches(OPT_enable_deserialization_recovery);
472472
}
473473

474+
// Experimental string processing
475+
Opts.EnableExperimentalRegex |=
476+
Args.hasArg(OPT_enable_experimental_regex);
477+
474478
Opts.DisableAvailabilityChecking |=
475479
Args.hasArg(OPT_disable_availability_checking);
476480
Opts.CheckAPIAvailabilityOnly |=

lib/Parse/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ _swift_gyb_target_sources(swiftParse PRIVATE
3131
target_link_libraries(swiftParse PRIVATE
3232
swiftAST
3333
swiftSyntax
34-
swiftSyntaxParse)
34+
swiftSyntaxParse
35+
)
3536

3637
add_dependencies(swiftParse swift-parse-syntax-generated-headers)
3738

lib/Parse/Lexer.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030
// FIXME: Figure out if this can be migrated to LLVM.
3131
#include "clang/Basic/CharInfo.h"
3232

33+
// Regex parser delivered via libSwift
34+
#include "swift/Parse/ExperimentalRegexBridging.h"
35+
static ParseRegexStrawperson parseRegexStrawperson = nullptr;
36+
void Parser_registerParseRegexStrawperson(ParseRegexStrawperson fn) {
37+
parseRegexStrawperson = fn;
38+
}
39+
3340
#include <limits>
3441

3542
using namespace swift;
@@ -1788,13 +1795,27 @@ static void validateMultilineIndents(const Token &Str,
17881795

17891796
/// Emit diagnostics for single-quote string and suggest replacement
17901797
/// with double-quoted equivalent.
1791-
static void diagnoseSingleQuoteStringLiteral(const char *TokStart,
1792-
const char *TokEnd,
1793-
DiagnosticEngine *D) {
1798+
///
1799+
/// Or, if we're in experimental regex mode, we will emit a custom
1800+
/// error message instead, determined by the Swift library.
1801+
void Lexer::diagnoseSingleQuoteStringLiteral(const char *TokStart,
1802+
const char *TokEnd) {
17941803
assert(*TokStart == '\'' && TokEnd[-1] == '\'');
1795-
if (!D)
1804+
if (!Diags) // or assert?
17961805
return;
17971806

1807+
auto startLoc = Lexer::getSourceLoc(TokStart);
1808+
auto endLoc = Lexer::getSourceLoc(TokEnd);
1809+
1810+
if (LangOpts.EnableExperimentalRegex) {
1811+
if (parseRegexStrawperson) {
1812+
auto copy = std::string(TokStart, TokEnd-TokStart);
1813+
auto msg = parseRegexStrawperson(copy.c_str());
1814+
assert(msg != nullptr);
1815+
Diags->diagnose(startLoc, diag::lex_experimental_regex_strawperson, msg);
1816+
}
1817+
}
1818+
17981819
SmallString<32> replacement;
17991820
replacement.push_back('"');
18001821
const char *Ptr = TokStart + 1;
@@ -1826,9 +1847,8 @@ static void diagnoseSingleQuoteStringLiteral(const char *TokStart,
18261847
replacement.append(OutputPtr, Ptr - 1);
18271848
replacement.push_back('"');
18281849

1829-
D->diagnose(Lexer::getSourceLoc(TokStart), diag::lex_single_quote_string)
1830-
.fixItReplaceChars(Lexer::getSourceLoc(TokStart),
1831-
Lexer::getSourceLoc(TokEnd), replacement);
1850+
Diags->diagnose(startLoc, diag::lex_single_quote_string)
1851+
.fixItReplaceChars(startLoc, endLoc, replacement);
18321852
}
18331853

18341854
/// lexStringLiteral:
@@ -1895,7 +1915,7 @@ void Lexer::lexStringLiteral(unsigned CustomDelimiterLen) {
18951915
if (QuoteChar == '\'') {
18961916
assert(!IsMultilineString && CustomDelimiterLen == 0 &&
18971917
"Single quoted string cannot have custom delimitor, nor multiline");
1898-
diagnoseSingleQuoteStringLiteral(TokStart, CurPtr, Diags);
1918+
diagnoseSingleQuoteStringLiteral(TokStart, CurPtr);
18991919
}
19001920

19011921
if (wasErroneous)

libswift/Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
# See http://swift.org/LICENSE.txt for license information
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

9+
add_subdirectory(ExperimentalRegex)
910
add_subdirectory(SIL)
1011
add_subdirectory(Optimizer)

0 commit comments

Comments
 (0)