瀏覽代碼

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>
Richard Smith 5 月之前
父節點
當前提交
cb0edef45f
共有 3 個文件被更改,包括 55 次插入28 次删除
  1. 8 4
      bazel/carbon_rules/defs.bzl
  2. 5 1
      examples/re2_playground/BUILD
  3. 42 23
      examples/re2_playground/re2_playground.carbon

+ 8 - 4
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

+ 5 - 1
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",
+    ],
 )

+ 42 - 23
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<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;
 }