From cb0edef45f29445f0b959acac95ffb6eeeba5390 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 10 Nov 2025 15:53:23 -0800 Subject: [PATCH] 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> --- bazel/carbon_rules/defs.bzl | 12 ++-- examples/re2_playground/BUILD | 6 +- examples/re2_playground/re2_playground.carbon | 65 ++++++++++++------- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/bazel/carbon_rules/defs.bzl b/bazel/carbon_rules/defs.bzl index 22b457ec9a69..5d58516b43f6 100644 --- a/bazel/carbon_rules/defs.bzl +++ b/bazel/carbon_rules/defs.bzl @@ -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 diff --git a/examples/re2_playground/BUILD b/examples/re2_playground/BUILD index bd7bffedb1a5..eab25664c4ab 100644 --- a/examples/re2_playground/BUILD +++ b/examples/re2_playground/BUILD @@ -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", + ], ) diff --git a/examples/re2_playground/re2_playground.carbon b/examples/re2_playground/re2_playground.carbon index 26de1ff25422..e1a770efe813 100644 --- a/examples/re2_playground/re2_playground.carbon +++ b/examples/re2_playground/re2_playground.carbon @@ -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;"; +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; }