[jruby-joni] 116/194: absent operator
Hideki Yamane
henrich at moszumanska.debian.org
Thu Feb 1 12:04:33 UTC 2018
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 5a50f34e0c57f900fc2df6e3cd4e4d088aaba7ef
Author: Marcin Mielzynski <lopx at gazeta.pl>
Date: Sun Jan 7 23:45:40 2018 +0100
absent operator
---
src/org/joni/Analyser.java | 21 +++++++++++++++
src/org/joni/ArrayCompiler.java | 12 +++++++++
src/org/joni/ByteCodeMachine.java | 53 ++++++++++++++++++++++++++++++++++++--
src/org/joni/Parser.java | 7 +++++
src/org/joni/StackEntry.java | 14 ++++++++++
src/org/joni/StackMachine.java | 35 +++++++++++++++++++++++++
src/org/joni/Syntax.java | 8 +++++-
src/org/joni/ast/EncloseNode.java | 4 +++
src/org/joni/constants/OPCode.java | 2 +-
test/org/joni/test/TestU8.java | 9 +++++++
10 files changed, 161 insertions(+), 4 deletions(-)
diff --git a/src/org/joni/Analyser.java b/src/org/joni/Analyser.java
index c9b2048..b92d534 100644
--- a/src/org/joni/Analyser.java
+++ b/src/org/joni/Analyser.java
@@ -383,6 +383,7 @@ final class Analyser extends Parser {
case EncloseType.OPTION:
case EncloseNode.STOP_BACKTRACK:
case EncloseNode.CONDITION:
+ case EncloseNode.ABSENT:
info = quantifiersMemoryInfo(en.target);
break;
@@ -501,6 +502,9 @@ final class Analyser extends Parser {
case EncloseNode.CONDITION:
min = getMinMatchLength(en.target);
break;
+
+ case EncloseType.ABSENT:
+ break;
} // inner switch
break;
@@ -607,6 +611,9 @@ final class Analyser extends Parser {
case EncloseNode.CONDITION:
max = getMaxMatchLength(en.target);
break;
+
+ case EncloseType.ABSENT:
+ break;
} // inner switch
break;
@@ -720,6 +727,9 @@ final class Analyser extends Parser {
case EncloseNode.CONDITION:
len = getCharLengthTree(en.target, level);
break;
+
+ case EncloseType.ABSENT:
+ break;
} // inner switch
break;
@@ -968,6 +978,9 @@ final class Analyser extends Parser {
case EncloseNode.CONDITION:
n = getHeadValueNode(en.target, exact);
break;
+
+ case EncloseType.ABSENT:
+ break;
} // inner switch
break;
@@ -1945,6 +1958,10 @@ final class Analyser extends Parser {
}
setupTree(en.target, state);
break;
+
+ case EncloseType.ABSENT:
+ setupTree(en.target, state);
+ break;
} // inner switch
break;
@@ -2265,6 +2282,10 @@ final class Analyser extends Parser {
case EncloseType.CONDITION:
optimizeNodeLeft(en.target, opt, oenv);
break;
+
+ case EncloseType.ABSENT:
+ opt.length.set(0, MinMaxLen.INFINITE_DISTANCE);
+ break;
} // inner switch
break;
}
diff --git a/src/org/joni/ArrayCompiler.java b/src/org/joni/ArrayCompiler.java
index d999992..8b1d963 100644
--- a/src/org/joni/ArrayCompiler.java
+++ b/src/org/joni/ArrayCompiler.java
@@ -874,6 +874,9 @@ final class ArrayCompiler extends Compiler {
newInternalException(ERR_PARSER_BUG);
}
break;
+ case EncloseType.ABSENT:
+ len = OPSize.PUSH_ABSENT_POS + OPSize.ABSENT + tlen + OPSize.ABSENT_END;
+ break;
default:
newInternalException(ERR_PARSER_BUG);
return 0; // not reached
@@ -972,6 +975,15 @@ final class ArrayCompiler extends Compiler {
}
break;
+ case EncloseType.ABSENT:
+ regex.requireStack = true;
+ len = compileLengthTree(node.target);
+ addOpcode(OPCode.PUSH_ABSENT_POS);
+ addOpcodeRelAddr(OPCode.ABSENT, len + OPSize.ABSENT_END);
+ compileTree(node.target);
+ addOpcode(OPCode.ABSENT_END);
+ break;
+
default:
newInternalException(ERR_PARSER_BUG);
break;
diff --git a/src/org/joni/ByteCodeMachine.java b/src/org/joni/ByteCodeMachine.java
index e55cfc8..ed4f63a 100644
--- a/src/org/joni/ByteCodeMachine.java
+++ b/src/org/joni/ByteCodeMachine.java
@@ -306,7 +306,10 @@ class ByteCodeMachine extends StackMachine {
case OPCode.PUSH_LOOK_BEHIND_NOT: opPushLookBehindNot(); continue;
case OPCode.FAIL_LOOK_BEHIND_NOT: opFailLookBehindNot(); continue;
- // USE_SUBEXP_CALL
+ case OPCode.PUSH_ABSENT_POS: opPushAbsentPos(); continue;
+ case OPCode.ABSENT: opAbsent(); continue;
+ case OPCode.ABSENT_END: opAbsentEnd(); continue;
+
case OPCode.CALL: opCall(); continue;
case OPCode.RETURN: opReturn(); continue;
case OPCode.CONDITION: opCondition(); continue;
@@ -439,7 +442,10 @@ class ByteCodeMachine extends StackMachine {
case OPCode.PUSH_LOOK_BEHIND_NOT: opPushLookBehindNot(); continue;
case OPCode.FAIL_LOOK_BEHIND_NOT: opFailLookBehindNot(); continue;
- // USE_SUBEXP_CALL
+ case OPCode.PUSH_ABSENT_POS: opPushAbsentPos(); continue;
+ case OPCode.ABSENT: opAbsent(); continue;
+ case OPCode.ABSENT_END: opAbsentEnd(); continue;
+
case OPCode.CALL: opCall(); continue;
case OPCode.RETURN: opReturn(); continue;
case OPCode.CONDITION: opCondition(); continue;
@@ -1882,6 +1888,49 @@ class ByteCodeMachine extends StackMachine {
opFail();
}
+ private void opPushAbsentPos() {
+ pushAbsentPos(s, end);
+ }
+
+ private void opAbsent() {
+ int aend = range; // use end for USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
+ int selfip = ip - 1;
+ StackEntry e = stack[--stk];
+ int absent = e.getAbsentStr();
+ range = e.getAbsentEndStr();
+ int addr = code[ip++];
+
+ if (Config.DEBUG_MATCH) System.out.println("ABSENT: s:" + s + " end:" + end + " absent:" + absent + " aend:" + aend);
+
+ if (absent > aend && s > absent) {
+ pop();
+ opFail();
+ return;
+ } else if (s >= aend && s > absent) {
+ if (s > aend || s > end) {
+ opFail();
+ return;
+ }
+ ip += addr;
+ } else {
+ pushAlt(ip + addr, s, sprev, pkeep);
+ int n = enc.length(bytes, s, end);
+ pushAbsentPos(absent, range);
+ pushAlt(selfip, s + n, s, pkeep);
+ pushAbsent();
+ range = aend;
+ }
+ }
+
+ private void opAbsentEnd() {
+ if (sprev < range) range = sprev;
+ if (Config.DEBUG_MATCH) System.out.println("ABSENT_END: end:" + range);
+ popTilAbsent();
+ opFail();
+ return;
+ // sprev = sbegin; // break;
+ }
+
private void opCall() {
int addr = code[ip++];
pushCallFrame(ip);
diff --git a/src/org/joni/Parser.java b/src/org/joni/Parser.java
index 7854833..702fceb 100644
--- a/src/org/joni/Parser.java
+++ b/src/org/joni/Parser.java
@@ -458,6 +458,13 @@ class Parser extends Lexer {
case '>': /* (?>...) stop backtrack */
node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
break;
+ case '~': /* (?~...) absent operator */
+ if (syntax.op2QMarkTildeAbsent()) {
+ node = new EncloseNode(EncloseType.ABSENT);
+ break;
+ } else {
+ newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
+ }
case '\'':
if (Config.USE_NAMED_GROUP) {
if (syntax.op2QMarkLtNamedGroup()) {
diff --git a/src/org/joni/StackEntry.java b/src/org/joni/StackEntry.java
index 24de7b6..883f563 100644
--- a/src/org/joni/StackEntry.java
+++ b/src/org/joni/StackEntry.java
@@ -169,4 +169,18 @@ final class StackEntry {
int getCallFramePStr() {
return E3;
}
+
+ void setAbsentStr(int pos) {
+ E1 = pos;
+ }
+ int getAbsentStr() {
+ return E1;
+ }
+
+ void setAbsentEndStr(int pos) {
+ E2 = pos;
+ }
+ int getAbsentEndStr() {
+ return E2;
+ }
}
diff --git a/src/org/joni/StackMachine.java b/src/org/joni/StackMachine.java
index 7715ae9..f7fe7eb 100644
--- a/src/org/joni/StackMachine.java
+++ b/src/org/joni/StackMachine.java
@@ -314,6 +314,20 @@ abstract class StackMachine extends Matcher implements StackType {
stk++;
}
+ protected final void pushAbsent() {
+ StackEntry e = ensure1();
+ e.type = ABSENT;
+ stk++;
+ }
+
+ protected final void pushAbsentPos(int start, int end) {
+ StackEntry e = ensure1();
+ e.type = ABSENT_POS;
+ e.setAbsentStr(start);
+ e.setAbsentEndStr(end);
+ stk++;
+ }
+
// stack debug routines here
// ...
@@ -427,6 +441,27 @@ abstract class StackMachine extends Matcher implements StackType {
}
}
+ protected final void popTilAbsent() {
+ while (true) {
+ stk--;
+ StackEntry e = stack[stk];
+
+ if (e.type == ABSENT) {
+ break;
+ } else if (e.type == MEM_START) {
+ repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
+ repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
+ } else if (e.type == REPEAT_INC) {
+ stack[e.getSi()].decreaseRepeatCount();
+ } else if (e.type == MEM_END) {
+ repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
+ repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
+ } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
+ if (e.type == STATE_CHECK_MARK) stateCheckMark();
+ }
+ }
+ }
+
protected final int posEnd() {
int k = stk;
while (true) {
diff --git a/src/org/joni/Syntax.java b/src/org/joni/Syntax.java
index 087c730..0b06267 100644
--- a/src/org/joni/Syntax.java
+++ b/src/org/joni/Syntax.java
@@ -303,6 +303,10 @@ public final class Syntax implements SyntaxProperties {
return isOp2(OP2_ESC_CAPITAL_K_KEEP);
}
+ public boolean op2QMarkTildeAbsent() {
+ return isOp2(OP2_QMARK_TILDE_ABSENT);
+ }
+
public boolean op2EscGBraceBackref() {
return isOp2(OP2_ESC_G_BRACE_BACKREF);
}
@@ -432,7 +436,9 @@ public final class Syntax implements SyntaxProperties {
OP2_ESC_H_XDIGIT |
OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER |
OP2_QMARK_LPAREN_CONDITION |
- OP2_ESC_CAPITAL_R_LINEBREAK | OP2_ESC_CAPITAL_K_KEEP
+ OP2_ESC_CAPITAL_R_LINEBREAK |
+ OP2_ESC_CAPITAL_K_KEEP |
+ OP2_QMARK_TILDE_ABSENT
),
0,
diff --git a/src/org/joni/ast/EncloseNode.java b/src/org/joni/ast/EncloseNode.java
index 17646ac..cc86d92 100644
--- a/src/org/joni/ast/EncloseNode.java
+++ b/src/org/joni/ast/EncloseNode.java
@@ -96,6 +96,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
if (isMemory()) types.append("MEMORY ");
if (isOption()) types.append("OPTION ");
if (isCondition()) types.append("CONDITION ");
+ if (isAbsent()) types.append("ABSENT ");
return types.toString();
}
@@ -123,4 +124,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
return (type & STOP_BACKTRACK) != 0;
}
+ public boolean isAbsent() {
+ return (type & ABSENT) != 0;
+ }
}
diff --git a/src/org/joni/constants/OPCode.java b/src/org/joni/constants/OPCode.java
index 01e4fae..3e95aad 100644
--- a/src/org/joni/constants/OPCode.java
+++ b/src/org/joni/constants/OPCode.java
@@ -121,7 +121,7 @@ public interface OPCode {
final int PUSH_LOOK_BEHIND_NOT = 83; /* (?<!...) start */
final int FAIL_LOOK_BEHIND_NOT = 84; /* (?<!...) end */
- final int ABSENT_POS = 85; /* (?~...) start */
+ final int PUSH_ABSENT_POS = 85; /* (?~...) start */
final int ABSENT = 86; /* (?~...) start of inner loop */
final int ABSENT_END = 87; /* (?~...) end */
diff --git a/test/org/joni/test/TestU8.java b/test/org/joni/test/TestU8.java
index b474199..9782d85 100755
--- a/test/org/joni/test/TestU8.java
+++ b/test/org/joni/test/TestU8.java
@@ -282,5 +282,14 @@ public class TestU8 extends Test {
x2s("\\b.*abc.*\\b", "abc", 0, 3);
x2s("(?!a).*b", "ab", 1, 2);
x2s("(?!^a).*b", "ab", 1, 2);
+
+ x2s("<-(?~->)->", "<- ->->", 0, 5);
+ x2s("<-(?~->)->\n", "<-1->2<-3->\n", 6, 12);
+ x2s("<-(?~->)->.*<-(?~->)->", "<-1->2<-3->4<-5->", 0, 17);
+ x2s("<-(?~->)->.*?<-(?~->)->", "<-1->2<-3->4<-5->", 0, 11);
+ x2s("(?~abc)c", "abc", 0, 3);
+ x2s("(?~abc)bc", "abc", 0, 3);
+ x2s("(?~abc)abc", "abc", 0, 3);
+
}
}
--
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