diff --git a/mrbgems/mruby-regexp/mrblib/regexp.rb b/mrbgems/mruby-regexp/mrblib/regexp.rb new file mode 100644 index 000000000..f56b066f6 --- /dev/null +++ b/mrbgems/mruby-regexp/mrblib/regexp.rb @@ -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 diff --git a/mrbgems/mruby-regexp/src/re_compile.c b/mrbgems/mruby-regexp/src/re_compile.c index 0cf9e3928..b873585b9 100644 --- a/mrbgems/mruby-regexp/src/re_compile.c +++ b/mrbgems/mruby-regexp/src/re_compile.c @@ -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: diff --git a/mrbgems/mruby-regexp/src/regexp.c b/mrbgems/mruby-regexp/src/regexp.c index 1c6ec180c..953fac50e 100644 --- a/mrbgems/mruby-regexp/src/regexp.c +++ b/mrbgems/mruby-regexp/src/regexp.c @@ -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)); diff --git a/mrbgems/mruby-regexp/test/regexp.rb b/mrbgems/mruby-regexp/test/regexp.rb index 45ee42051..feef4ae61 100644 --- a/mrbgems/mruby-regexp/test/regexp.rb +++ b/mrbgems/mruby-regexp/test/regexp.rb @@ -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