[jruby-joni] 181/279: Add IGNORE_BACKREF_PROC_READ_NOT syntax option

Hideki Yamane henrich at moszumanska.debian.org
Mon Nov 16 11:27:28 UTC 2015


This is an automated email from the git hooks/post-receive script.

henrich pushed a commit to branch debian/sid
in repository jruby-joni.

commit fbdd0c42d1eec7d958b27ad44640e3d29b1c4b45
Author: Ben Browning <bbrownin at redhat.com>
Date:   Thu Sep 5 21:00:09 2013 -0400

    Add IGNORE_BACKREF_PROC_READ_NOT syntax option
    
    Setting this enables the JavaScript behavior of ignoring any
    backreferences to negative lookahead captures outside of the negative
    lookahead itself.
    
    In otherwords, in a regular expression like "(.*?)a(?!(a+)b\2c)\2(.*)"
    the second backreference to "\2", outside of the ?! group, is ignored.
---
 src/org/joni/Parser.java                     | 47 +++++++++++++++++++++++-----
 src/org/joni/ScanEnvironment.java            | 32 +++++++++++++++++++
 src/org/joni/Syntax.java                     |  4 +++
 src/org/joni/ast/EncloseNode.java            |  1 +
 src/org/joni/constants/SyntaxProperties.java |  1 +
 5 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/src/org/joni/Parser.java b/src/org/joni/Parser.java
index f0a049b..4f9764b 100644
--- a/src/org/joni/Parser.java
+++ b/src/org/joni/Parser.java
@@ -429,6 +429,9 @@ class Parser extends Lexer {
                 break;
             case '!':  /*         preceding read */
                 node = new AnchorNode(AnchorType.PREC_READ_NOT);
+                if (syntax.ignoreBackrefPrecReadNot()) {
+                    env.pushPrecReadNotNode(node);
+                }
                 break;
             case '>':  /* (?>...) stop backtrack */
                 node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
@@ -579,10 +582,16 @@ class Parser extends Lexer {
         if (node.getType() == NodeType.ANCHOR) {
             AnchorNode an = (AnchorNode) node;
             an.setTarget(target);
+            if (syntax.ignoreBackrefPrecReadNot() && an.type == AnchorType.PREC_READ_NOT) {
+                env.popPrecReadNotNode(an);
+            }
         } else {
             EncloseNode en = (EncloseNode)node;
             en.setTarget(target);
             if (en.type == EncloseType.MEMORY) {
+                if (syntax.ignoreBackrefPrecReadNot()) {
+                    en.containingAnchor = env.currentPrecReadNotNode();
+                }
                 /* Don't move this to previous of parse_subexp() */
                 env.setMemNode(en.regNum, node);
             }
@@ -750,13 +759,37 @@ class Parser extends Lexer {
             break;
 
         case BACKREF:
-            int[]backRefs = token.getBackrefNum() > 1 ? token.getBackrefRefs() : new int[]{token.getBackrefRef1()};
-            node = new BackRefNode(token.getBackrefNum(),
-                            backRefs,
-                            token.getBackrefByName(),
-                            token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
-                            token.getBackrefLevel(),      // ...
-                            env);
+            if (syntax.ignoreBackrefPrecReadNot() && token.getBackrefNum() == 1 && env.memNodes != null) {
+                EncloseNode encloseNode = (EncloseNode) env.memNodes[token.getBackrefRef1()];
+                boolean shouldIgnore = false;
+                if (encloseNode != null && encloseNode.containingAnchor != null) {
+                    shouldIgnore = true;
+                    for (Node anchorNode : env.precReadNotNodes) {
+                        if (anchorNode == encloseNode.containingAnchor) {
+                            shouldIgnore = false;
+                            break;
+                        }
+                    }
+                }
+                if (shouldIgnore) {
+                    node = StringNode.EMPTY;
+                } else {
+                    node = new BackRefNode(token.getBackrefNum(),
+                                    new int[]{token.getBackrefRef1()},
+                                    token.getBackrefByName(),
+                                    token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
+                                    token.getBackrefLevel(),      // ...
+                                    env);
+                }
+            } else {
+                int[]backRefs = token.getBackrefNum() > 1 ? token.getBackrefRefs() : new int[]{token.getBackrefRef1()};
+                node = new BackRefNode(token.getBackrefNum(),
+                                backRefs,
+                                token.getBackrefByName(),
+                                token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
+                                token.getBackrefLevel(),      // ...
+                                env);
+            }
 
             break;
 
diff --git a/src/org/joni/ScanEnvironment.java b/src/org/joni/ScanEnvironment.java
index 02a1ad7..0dbce24 100644
--- a/src/org/joni/ScanEnvironment.java
+++ b/src/org/joni/ScanEnvironment.java
@@ -55,6 +55,9 @@ public final class ScanEnvironment {
     int currMaxRegNum;
     boolean hasRecursion;
 
+    int numPrecReadNotNodes;
+    Node precReadNotNodes[];
+
     public ScanEnvironment(Regex regex, Syntax syntax) {
         this.reg = regex;
         option = regex.options;
@@ -80,6 +83,9 @@ public final class ScanEnvironment {
         combExpMaxRegNum = 0;
         currMaxRegNum = 0;
         hasRecursion = false;
+
+        numPrecReadNotNodes = 0;
+        precReadNotNodes = null;
     }
 
     public int addMemEntry() {
@@ -102,6 +108,32 @@ public final class ScanEnvironment {
         }
     }
 
+    public void pushPrecReadNotNode(Node node) {
+        numPrecReadNotNodes++;
+        if (precReadNotNodes == null) {
+            precReadNotNodes = new Node[SCANENV_MEMNODES_SIZE];
+        } else if (numPrecReadNotNodes >= precReadNotNodes.length) {
+            Node[]tmp = new Node[precReadNotNodes.length << 1];
+            System.arraycopy(precReadNotNodes, 0, tmp, 0, precReadNotNodes.length);
+            precReadNotNodes = tmp;
+        }
+        precReadNotNodes[numPrecReadNotNodes - 1] = node;
+    }
+
+    public void popPrecReadNotNode(Node node) {
+        if (precReadNotNodes != null && precReadNotNodes[numPrecReadNotNodes - 1] == node) {
+            precReadNotNodes[numPrecReadNotNodes - 1] = null;
+            numPrecReadNotNodes--;
+        }
+    }
+
+    public Node currentPrecReadNotNode() {
+        if (numPrecReadNotNodes > 0) {
+            return precReadNotNodes[numPrecReadNotNodes - 1];
+        }
+        return null;
+    }
+
     public int convertBackslashValue(int c) {
         if (syntax.opEscControlChars()) {
             switch (c) {
diff --git a/src/org/joni/Syntax.java b/src/org/joni/Syntax.java
index 774284c..89ead78 100644
--- a/src/org/joni/Syntax.java
+++ b/src/org/joni/Syntax.java
@@ -326,6 +326,10 @@ public final class Syntax implements SyntaxProperties{
         return isBehavior(FIXED_INTERVAL_IS_GREEDY_ONLY);
     }
 
+    public boolean ignoreBackrefPrecReadNot() {
+        return isBehavior(IGNORE_BACKREF_PREC_READ_NOT);
+    }
+
 
     public boolean notNewlineInNegativeCC() {
         return isBehavior(NOT_NEWLINE_IN_NEGATIVE_CC);
diff --git a/src/org/joni/ast/EncloseNode.java b/src/org/joni/ast/EncloseNode.java
index 0a07ed1..7c45d14 100644
--- a/src/org/joni/ast/EncloseNode.java
+++ b/src/org/joni/ast/EncloseNode.java
@@ -34,6 +34,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
     public int maxLength;           // OnigDistance
     public int charLength;
     public int optCount;            // referenced count in optimize_node_left()
+    public Node containingAnchor;   // 
 
     // node_new_enclose / onig_node_new_enclose
     public EncloseNode(int type) {
diff --git a/src/org/joni/constants/SyntaxProperties.java b/src/org/joni/constants/SyntaxProperties.java
index 78191ec..b31b6cb 100644
--- a/src/org/joni/constants/SyntaxProperties.java
+++ b/src/org/joni/constants/SyntaxProperties.java
@@ -88,6 +88,7 @@ public interface SyntaxProperties {
     final int ALLOW_MULTIPLEX_DEFINITION_NAME = (1<<8);  /* (?<x>);(?<x>); */
     final int FIXED_INTERVAL_IS_GREEDY_ONLY   = (1<<9);  /* a{n}?=(?:a{n});? */
     final int ALLOW_NESTED_REPEAT             = (1<<10); /* a{0,}{1}{2} */
+    final int IGNORE_BACKREF_PREC_READ_NOT    = (1<<11); /* /(?!(a+)b\2c)\2 */
 
     /* syntax (behavior); in char class [...] */
     final int NOT_NEWLINE_IN_NEGATIVE_CC      = (1<<20); /* [^...] */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jruby-joni.git



More information about the pkg-java-commits mailing list