[前][次][番号順一覧][スレッド一覧]

ruby-changes:63850

From: Jeremy <ko1@a...>
Date: Thu, 3 Dec 2020 02:42:27 +0900 (JST)
Subject: [ruby-changes:63850] 9e73177d53 (master): Do not reduce quantifiers if it affects which text will be matched

https://git.ruby-lang.org/ruby.git/commit/?id=9e73177d53

From 9e73177d5362c1986814f411961b712967dc5f97 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Mon, 23 Nov 2020 14:40:59 -0800
Subject: Do not reduce quantifiers if it affects which text will be matched

Quantifier reduction when using +?)* and +?)+ should not be done
as it affects which text will be matched.

This removes the need for the RQ_PQ_Q ReduceType, so remove the
enum entry and related switch case.

Test that these are the only two patterns affected by testing all
quantifier reduction tuples for both the captured and uncaptured
cases and making sure the matched text is the same for both.

Fixes [Bug #17341]

diff --git a/regparse.c b/regparse.c
index 7639db3..24ff5b9 100644
--- a/regparse.c
+++ b/regparse.c
@@ -2187,7 +2187,6 @@ enum ReduceType { https://github.com/ruby/ruby/blob/trunk/regparse.c#L2187
   RQ_AQ,       /* to '*?'   */
   RQ_QQ,       /* to '??'   */
   RQ_P_QQ,     /* to '+)??' */
-  RQ_PQ_Q      /* to '+?)?' */
 };
 
 static enum ReduceType const ReduceTypeTable[6][6] = {
@@ -2197,7 +2196,7 @@ static enum ReduceType const ReduceTypeTable[6][6] = { https://github.com/ruby/ruby/blob/trunk/regparse.c#L2196
   {RQ_A,    RQ_A,    RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL},  /* '+'  */
   {RQ_DEL,  RQ_AQ,   RQ_AQ,  RQ_DEL,  RQ_AQ,   RQ_AQ},   /* '??' */
   {RQ_DEL,  RQ_DEL,  RQ_DEL, RQ_DEL,  RQ_DEL,  RQ_DEL},  /* '*?' */
-  {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ,   RQ_AQ,   RQ_DEL}   /* '+?' */
+  {RQ_ASIS, RQ_ASIS, RQ_ASIS, RQ_AQ,  RQ_AQ,   RQ_DEL}   /* '+?' */
 };
 
 extern void
@@ -2234,12 +2233,6 @@ onig_reduce_nested_quantifier(Node* pnode, Node* cnode) https://github.com/ruby/ruby/blob/trunk/regparse.c#L2233
     c->lower  = 1;  c->upper = REPEAT_INFINITE;  c->greedy = 1;
     return ;
     break;
-  case RQ_PQ_Q:
-    p->target = cnode;
-    p->lower  = 0;  p->upper = 1;  p->greedy = 1;
-    c->lower  = 1;  c->upper = REPEAT_INFINITE;  c->greedy = 0;
-    return ;
-    break;
   case RQ_ASIS:
     p->target = cnode;
     return ;
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index e124fc7..e9d1fc3 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -1196,6 +1196,20 @@ class TestRegexp < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_regexp.rb#L1196
     }
   end
 
+  def test_quantifier_reduction
+    assert_equal('aa', eval('/(a+?)*/').match('aa')[0])
+    assert_equal('aa', eval('/(?:a+?)*/').match('aa')[0])
+
+    quantifiers = %w'? * + ?? *? +?'
+    quantifiers.each do |q1|
+      quantifiers.each do |q2|
+        r1 = eval("/(a#{q1})#{q2}/").match('aa')[0]
+        r2 = eval("/(?:a#{q1})#{q2}/").match('aa')[0]
+        assert_equal(r1, r2)
+      end
+    end
+  end
+
   def test_once
     pr1 = proc{|i| /#{i}/o}
     assert_equal(/0/, pr1.call(0))
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]