Add line editor to RE2 example. (#6337)

Most inputs are matched against the current regex. An input that starts
and ends with `/` sets a new regex instead. EOF terminates the program.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
This commit is contained in:
Richard Smith
2025-11-10 23:53:23 +00:00
committed by GitHub
co-authored by josh11b
parent 711cd56c0f
commit cb0edef45f
3 changed files with 55 additions and 28 deletions
+8 -4
View File
@@ -19,7 +19,7 @@ def _carbon_binary_impl(ctx):
# Pass any C++ flags from our dependencies onto Carbon.
dep_flags = []
dep_hdrs = []
dep_link_flags = []
dep_link_flags = ["-lc++"]
dep_link_inputs = []
for dep in ctx.attr.deps:
if CcInfo in dep:
@@ -75,7 +75,8 @@ def _carbon_binary_impl(ctx):
inputs = depset(direct = srcs_reordered, transitive = dep_hdrs),
executable = toolchain_driver,
tools = depset(toolchain_data),
arguments = ["compile", "--output=" + out.path, "--clang-arg=-stdlib=libc++"] + [s.path for s in srcs_reordered] + extra_flags,
arguments = ["compile", "--output=" + out.path, "--clang-arg=-stdlib=libc++"] +
[s.path for s in srcs_reordered] + extra_flags + ctx.attr.flags,
mnemonic = "CarbonCompile",
progress_message = "Compiling " + src.short_path,
)
@@ -86,7 +87,7 @@ def _carbon_binary_impl(ctx):
inputs = objs + dep_link_inputs,
executable = toolchain_driver,
tools = depset(toolchain_data),
arguments = ["link", "--output=" + bin.path] + dep_link_flags + [o.path for o in objs],
arguments = ["link", "--output=" + bin.path] + ["--"] + dep_link_flags + [o.path for o in objs],
mnemonic = "CarbonLink",
progress_message = "Linking " + bin.short_path,
)
@@ -96,6 +97,7 @@ _carbon_binary_internal = rule(
implementation = _carbon_binary_impl,
attrs = {
"deps": attr.label_list(allow_files = True, providers = [[CcInfo]]),
"flags": attr.string_list(),
# The exec config toolchain driver and data. These will be `None` when
# using the target config and populated when using the exec config. We
# have to use duplicate attributes here and below to have different
@@ -130,13 +132,14 @@ _carbon_binary_internal = rule(
executable = True,
)
def carbon_binary(name, srcs, deps = [], tags = []):
def carbon_binary(name, srcs, deps = [], flags = [], tags = []):
"""Compiles a Carbon binary.
Args:
name: The name of the build target.
srcs: List of Carbon source files to compile.
deps: List of dependencies.
flags: Extra flags to pass to the Carbon compile command.
tags: Tags to apply to the rule.
"""
_carbon_binary_internal(
@@ -144,6 +147,7 @@ def carbon_binary(name, srcs, deps = [], tags = []):
srcs = srcs,
prelude_srcs = ["//core:prelude_files"],
deps = deps,
flags = flags,
tags = tags,
# We synthesize two sets of attributes from mirrored `select`s here
+5 -1
View File
@@ -7,6 +7,10 @@ load("//bazel/carbon_rules:defs.bzl", "carbon_binary")
carbon_binary(
name = "re2_playground",
srcs = ["re2_playground.carbon"],
flags = ["--clang-arg=-std=c++20"],
tags = ["manual"],
deps = ["@re2"],
deps = [
"@llvm-project//llvm:LineEditor",
"@re2",
],
)
+42 -23
View File
@@ -2,41 +2,60 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
import Cpp library "llvm/LineEditor/LineEditor.h";
import Cpp library "llvm/Support/raw_ostream.h";
import Cpp library "re2/re2.h";
import Cpp inline '''c++
// A wrapper around RE2 working around lack of:
//
// * Overloading support for the constructor.
// * Non-null pointer support for the `submatch` parameter.
struct WrapRE2 : re2::RE2 {
WrapRE2(std::string_view v) : RE2(v) {}
bool Match(absl::string_view text, size_t startpos, size_t endpos,
Anchor re_anchor, absl::string_view* _Nonnull submatch,
int nsubmatch) const {
return RE2::Match(text, startpos, endpos, re_anchor, submatch, nsubmatch);
}
};
''';
import Cpp inline "using OptionalString = std::optional<std::string>;";
import Cpp inline "std::string_view AsStringView(const std::string &s) { return s; }";
import Core library "io";
class RE2 {
extend adapt Cpp.WrapRE2;
extend adapt Cpp.re2.RE2;
fn Make(re: str) -> Self {
return WrapRE2(re) as Self;
return RE2(re) as Self;
}
fn Match[self: Self](text: str) -> bool {
var submatches: str;
return (self as Cpp.WrapRE2).Match(text, 0, text.Size(), UNANCHORED, &submatches, 0);
return FullMatch(text, self as Cpp.re2.RE2);
}
}
impl str as Core.ImplicitAs(Cpp.llvm.StringRef) {
fn Convert[self: Self]() -> Cpp.llvm.StringRef {
return Cpp.llvm.StringRef.StringRef(self);
}
}
fn Print(var s: str) {
*Cpp.llvm.outs() << s;
}
fn Run() -> i32 {
var editor: Cpp.llvm.LineEditor = Cpp.llvm.LineEditor.LineEditor("re2_playground");
editor.setPrompt(Cpp.std.string.basic_string("re2> "));
Print('''
Usage:
/regex/ -- sets the current regular expression to regex
anything else -- matches the entered text against the specified regex
''');
var re: RE2 = RE2.Make("^a*$");
if (re.Match("aaaaaaaab")) {
return 1;
}
if (not re.Match("aaaaaaaaa")) {
return 1;
while (true) {
var line: Cpp.OptionalString = editor.readLine();
if (not line.has_value()) {
break;
}
if (line.value()->starts_with("/") and line.value()->ends_with("/")) {
re = RE2.Make(Cpp.AsStringView(line.value()->substr(1, line.value()->size() - 2)));
continue;
}
if (re.Match(Cpp.AsStringView(*line.value()))) {
Print("Match\n");
} else {
Print("No match\n");
}
}
return 0;
}