mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-regexp: add /regex/ literal support, $~, Regexp.compile
- /regex/ literal syntax now works (compiler generates Regexp.compile) - Regexp#match and Regexp#=~ set $~ global variable - Regexp.last_match(n) for accessing capture groups - Regexp.compile as alias for Regexp.new - Regexp#options Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
class Regexp
|
||||
def self.compile(pattern, *args)
|
||||
new(pattern, *args)
|
||||
end
|
||||
|
||||
def options
|
||||
@flags.to_i
|
||||
end
|
||||
|
||||
# $1-$9 convenience methods via $~
|
||||
def self.last_match(n = nil)
|
||||
md = $~
|
||||
return md if n.nil?
|
||||
md ? md[n] : nil
|
||||
end
|
||||
end
|
||||
@@ -429,7 +429,6 @@ compile_quantified(re_compiler *c)
|
||||
mrb_bool nongreedy = (peek(c) == '?');
|
||||
if (nongreedy) next_char(c);
|
||||
|
||||
uint32_t atom_len = c->code_len - start;
|
||||
|
||||
if (ch == '*') {
|
||||
/* e* → L: SPLIT(body, end); body; JMP L; end:
|
||||
|
||||
@@ -105,6 +105,7 @@ create_matchdata(mrb_state *mrb, mrb_value str, int *captures, int ncap)
|
||||
|
||||
mrb_value obj = mrb_obj_value(mrb_data_object_alloc(mrb, md_class, md, &matchdata_type));
|
||||
/* store in $~ */
|
||||
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$~"), obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -127,7 +128,10 @@ regexp_match(mrb_state *mrb, mrb_value self)
|
||||
int ncap = re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), pos,
|
||||
captures, pat->num_captures * 2);
|
||||
|
||||
if (ncap == 0) return mrb_nil_value();
|
||||
if (ncap == 0) {
|
||||
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$~"), mrb_nil_value());
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
return create_matchdata(mrb, str, captures, pat->num_captures * 2);
|
||||
}
|
||||
@@ -171,7 +175,11 @@ regexp_match_op(mrb_state *mrb, mrb_value self)
|
||||
int ncap = re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), 0,
|
||||
captures, pat->num_captures * 2);
|
||||
|
||||
if (ncap == 0) return mrb_nil_value();
|
||||
if (ncap == 0) {
|
||||
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$~"), mrb_nil_value());
|
||||
return mrb_nil_value();
|
||||
}
|
||||
create_matchdata(mrb, str, captures, pat->num_captures * 2);
|
||||
return mrb_int_value(mrb, captures[0]);
|
||||
}
|
||||
|
||||
@@ -393,7 +401,7 @@ mrb_mruby_regexp_gem_init(mrb_state *mrb)
|
||||
|
||||
/* Class methods */
|
||||
mrb_define_method(mrb, re, "initialize", regexp_init, MRB_ARGS_ARG(1, 2));
|
||||
mrb_define_class_method(mrb, re, "compile", regexp_init, MRB_ARGS_ARG(1, 2));
|
||||
/* compile is defined in Ruby (mrblib) as alias for new */
|
||||
mrb_define_class_method(mrb, re, "escape", regexp_escape, MRB_ARGS_REQ(1));
|
||||
mrb_define_class_method(mrb, re, "quote", regexp_escape, MRB_ARGS_REQ(1));
|
||||
|
||||
|
||||
@@ -139,3 +139,27 @@ end
|
||||
assert("String#scan") do
|
||||
assert_equal ["1", "2", "3"], "a1b2c3".scan(Regexp.new("\\d"))
|
||||
end
|
||||
|
||||
assert("Regexp literal /regex/") do
|
||||
assert_true /abc/.match?("abc")
|
||||
assert_equal "123", /\d+/.match("abc123")[0]
|
||||
assert_true /hello/i.match?("HELLO")
|
||||
end
|
||||
|
||||
assert("$~ global variable") do
|
||||
/(\w+)@(\w+)/ =~ "user@host"
|
||||
assert_kind_of MatchData, $~
|
||||
assert_equal "user", $~[1]
|
||||
assert_equal "host", $~[2]
|
||||
end
|
||||
|
||||
assert("$~ is nil on no match") do
|
||||
/xyz/ =~ "abc"
|
||||
assert_nil $~
|
||||
end
|
||||
|
||||
assert("Regexp.last_match") do
|
||||
/(\d+)/ =~ "abc123"
|
||||
assert_equal "123", Regexp.last_match(1)
|
||||
assert_equal "123", Regexp.last_match(0)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user