diff --git a/mrbgems/mruby-regexp/include/re_internal.h b/mrbgems/mruby-regexp/include/re_internal.h index 82ace6461..5ad3245be 100644 --- a/mrbgems/mruby-regexp/include/re_internal.h +++ b/mrbgems/mruby-regexp/include/re_internal.h @@ -56,6 +56,7 @@ typedef struct mrb_regexp_pattern { uint16_t num_captures; /* number of capture groups (including group 0) */ uint32_t flags; mrb_bool has_backref; /* true if pattern uses \1-\9 */ + mrb_bool has_nongreedy; /* true if pattern uses *?, +?, ?? */ } mrb_regexp_pattern; /* Regexp flags */ diff --git a/mrbgems/mruby-regexp/src/re_compile.c b/mrbgems/mruby-regexp/src/re_compile.c index b873585b9..a667e1eec 100644 --- a/mrbgems/mruby-regexp/src/re_compile.c +++ b/mrbgems/mruby-regexp/src/re_compile.c @@ -26,6 +26,7 @@ typedef struct { uint16_t num_captures; uint32_t flags; mrb_bool has_backref; + mrb_bool has_nongreedy; } re_compiler; static void compile_alt(re_compiler *c); /* forward */ @@ -427,7 +428,10 @@ compile_quantified(re_compiler *c) if (ch == '*' || ch == '+' || ch == '?') { next_char(c); mrb_bool nongreedy = (peek(c) == '?'); - if (nongreedy) next_char(c); + if (nongreedy) { + next_char(c); + c->has_nongreedy = TRUE; + } if (ch == '*') { @@ -458,7 +462,10 @@ compile_quantified(re_compiler *c) return; /* not a quantifier */ } mrb_bool nongreedy = (peek(c) == '?'); - if (nongreedy) next_char(c); + if (nongreedy) { + next_char(c); + c->has_nongreedy = TRUE; + } /* For {n,m}: repeat atom min times, then optional (max-min) times */ uint32_t atom_end = c->code_len; @@ -595,6 +602,7 @@ re_compile(mrb_state *mrb, const char *pattern, mrb_int len, uint32_t flags) pat->num_captures = c.num_captures; pat->flags = flags; pat->has_backref = c.has_backref; + pat->has_nongreedy = c.has_nongreedy; return pat; } diff --git a/mrbgems/mruby-regexp/src/re_exec.c b/mrbgems/mruby-regexp/src/re_exec.c index 198e65452..959d3bd55 100644 --- a/mrbgems/mruby-regexp/src/re_exec.c +++ b/mrbgems/mruby-regexp/src/re_exec.c @@ -426,7 +426,7 @@ re_exec(mrb_state *mrb, const mrb_regexp_pattern *pat, const char *str, mrb_int len, mrb_int start, int *captures, int captures_size) { - if (pat->has_backref) { + if (pat->has_backref || pat->has_nongreedy) { return backtrack_exec(mrb, pat, str, len, start, captures, captures_size); } return pike_vm(mrb, pat, str, len, start, captures, captures_size); diff --git a/mrbgems/mruby-regexp/test/regexp.rb b/mrbgems/mruby-regexp/test/regexp.rb index a9a304114..76ba4e802 100644 --- a/mrbgems/mruby-regexp/test/regexp.rb +++ b/mrbgems/mruby-regexp/test/regexp.rb @@ -178,9 +178,9 @@ assert("Regexp - nested captures") do end assert("Regexp - non-greedy quantifiers") do - # TODO: non-greedy a+? returns "aaa" instead of "a" (needs priority fix) - assert_equal "aaa", /a+?/.match("aaa")[0] - # non-greedy a*? test skipped: needs further debugging + + assert_equal "a", /a+?/.match("aaa")[0] + assert_equal "", /a*?/.match("aaa")[0] end assert("Regexp - word boundary") do