8012359: Increase code coverage in Joni
Reviewed-by: jlaskey, lagergren
This commit is contained in:
parent
aeda283b75
commit
2c97733af0
@ -305,6 +305,8 @@
|
||||
<include name="**/codegen/*Test.class"/>
|
||||
<include name="**/parser/*Test.class"/>
|
||||
<include name="**/runtime/*Test.class"/>
|
||||
<include name="**/runtime/regexp/*Test.class"/>
|
||||
<include name="**/runtime/regexp/joni/*Test.class"/>
|
||||
<include name="**/framework/*Test.class"/>
|
||||
</fileset>
|
||||
|
||||
|
@ -41,7 +41,7 @@ import java.util.regex.PatternSyntaxException;
|
||||
* Note that this class is not thread-safe as it stores the current match result
|
||||
* and the string being matched in instance fields.
|
||||
*/
|
||||
public class DefaultRegExp extends RegExp {
|
||||
public class JdkRegExp extends RegExp {
|
||||
|
||||
/** Java regexp pattern to use for match. We compile to one of these */
|
||||
private Pattern pattern;
|
||||
@ -56,7 +56,7 @@ public class DefaultRegExp extends RegExp {
|
||||
* @param flags RegExp flag string
|
||||
* @throws ParserException if flags is invalid or source string has syntax error.
|
||||
*/
|
||||
public DefaultRegExp(final String source, final String flags) throws ParserException {
|
||||
public JdkRegExp(final String source, final String flags) throws ParserException {
|
||||
super(source, flags);
|
||||
|
||||
int intFlags = 0;
|
@ -113,7 +113,7 @@ public class JoniRegExp extends RegExp {
|
||||
public static class Factory extends RegExpFactory {
|
||||
|
||||
@Override
|
||||
protected RegExp compile(final String pattern, final String flags) throws ParserException {
|
||||
public RegExp compile(final String pattern, final String flags) throws ParserException {
|
||||
return new JoniRegExp(pattern, flags);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ import jdk.nashorn.internal.runtime.ParserException;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
|
||||
/**
|
||||
* Factory class for regular expressions. This class creates instances of {@link DefaultRegExp}.
|
||||
* Factory class for regular expressions. This class creates instances of {@link JdkRegExp}.
|
||||
* An alternative factory can be installed using the {@code nashorn.regexp.impl} system property.
|
||||
*/
|
||||
public class RegExpFactory {
|
||||
@ -62,8 +62,8 @@ public class RegExpFactory {
|
||||
* @return new RegExp
|
||||
* @throws ParserException if flags is invalid or pattern string has syntax error.
|
||||
*/
|
||||
protected RegExp compile(final String pattern, final String flags) throws ParserException {
|
||||
return new DefaultRegExp(pattern, flags);
|
||||
public RegExp compile(final String pattern, final String flags) throws ParserException {
|
||||
return new JdkRegExp(pattern, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,10 +21,7 @@ package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAll;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsClear;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAt;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
|
||||
@ -36,8 +33,6 @@ import java.util.HashSet;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
|
||||
@ -49,9 +44,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.ObjPtr;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
|
||||
|
||||
final class Analyser extends Parser {
|
||||
|
||||
@ -74,38 +67,9 @@ final class Analyser extends Parser {
|
||||
//regex.repeatRangeAlloc = 0;
|
||||
regex.repeatRangeLo = null;
|
||||
regex.repeatRangeHi = null;
|
||||
regex.numCombExpCheck = 0;
|
||||
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) regex.numCombExpCheck = 0;
|
||||
|
||||
parse();
|
||||
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
/* mixed use named group and no-named group */
|
||||
if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(regex.options)) {
|
||||
if (env.numNamed != env.numMem) {
|
||||
root = disableNoNameGroupCapture(root);
|
||||
} else {
|
||||
numberedRefCheck(root);
|
||||
}
|
||||
}
|
||||
} // USE_NAMED_GROUP
|
||||
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
if (env.numCall > 0) {
|
||||
env.unsetAddrList = new UnsetAddrList(env.numCall);
|
||||
setupSubExpCall(root);
|
||||
// r != 0 ???
|
||||
subexpRecursiveCheckTrav(root);
|
||||
// r < 0 -< err, FOUND_CALLED_NODE = 1
|
||||
subexpInfRecursiveCheckTrav(root);
|
||||
// r != 0 recursion infinite ???
|
||||
regex.numCall = env.numCall;
|
||||
} else {
|
||||
regex.numCall = 0;
|
||||
}
|
||||
} // USE_NAMED_GROUP
|
||||
|
||||
if (Config.DEBUG_PARSE_TREE_RAW && Config.DEBUG_PARSE_TREE) {
|
||||
Config.log.println("<RAW TREE>");
|
||||
Config.log.println(root + "\n");
|
||||
@ -129,27 +93,6 @@ final class Analyser extends Parser {
|
||||
regex.btMemEnd |= regex.captureHistory;
|
||||
}
|
||||
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
if (env.backrefedMem == 0 || (Config.USE_SUBEXP_CALL && env.numCall == 0)) {
|
||||
setupCombExpCheck(root, 0);
|
||||
|
||||
if (Config.USE_SUBEXP_CALL && env.hasRecursion) {
|
||||
env.numCombExpCheck = 0;
|
||||
} else { // USE_SUBEXP_CALL
|
||||
if (env.combExpMaxRegNum > 0) {
|
||||
for (int i=1; i<env.combExpMaxRegNum; i++) {
|
||||
if (bsAt(env.backrefedMem, i)) {
|
||||
env.numCombExpCheck = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // USE_SUBEXP_CALL
|
||||
regex.numCombExpCheck = env.numCombExpCheck;
|
||||
} // USE_COMBINATION_EXPLOSION_CHECK
|
||||
|
||||
regex.clearOptimizeInfo();
|
||||
|
||||
if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);
|
||||
@ -167,7 +110,6 @@ final class Analyser extends Parser {
|
||||
}
|
||||
|
||||
if (Config.DEBUG_COMPILE) {
|
||||
if (Config.USE_NAMED_GROUP) Config.log.print(regex.nameTableToString());
|
||||
Config.log.println("stack used: " + regex.stackNeeded);
|
||||
if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
|
||||
Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
|
||||
@ -177,157 +119,6 @@ final class Analyser extends Parser {
|
||||
regex.state = RegexState.NORMAL;
|
||||
}
|
||||
|
||||
private void noNameDisableMapFor_cosAlt(Node node, int[]map, Ptr counter) {
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
can.setCar(noNameDisableMap(can.car, map, counter));
|
||||
} while ((can = can.cdr) != null);
|
||||
}
|
||||
|
||||
private void noNameDisableMapFor_quantifier(Node node, int[]map, Ptr counter) {
|
||||
QuantifierNode qn = (QuantifierNode)node;
|
||||
Node target = qn.target;
|
||||
Node old = target;
|
||||
target = noNameDisableMap(target, map, counter);
|
||||
|
||||
if (target != old) {
|
||||
qn.setTarget(target);
|
||||
if (target.getType() == NodeType.QTFR) qn.reduceNestedQuantifier((QuantifierNode)target);
|
||||
}
|
||||
}
|
||||
|
||||
private Node noNameDisableMapFor_enclose(Node node, int[]map, Ptr counter) {
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
if (en.type == EncloseType.MEMORY) {
|
||||
if (en.isNamedGroup()) {
|
||||
counter.p++;
|
||||
map[en.regNum] = counter.p;
|
||||
en.regNum = counter.p;
|
||||
//en.target = noNameDisableMap(en.target, map, counter);
|
||||
en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
|
||||
} else {
|
||||
node = en.target;
|
||||
en.target = null; // remove first enclose: /(a)(?<b>c)/
|
||||
node = noNameDisableMap(node, map, counter);
|
||||
}
|
||||
} else {
|
||||
//en.target = noNameDisableMap(en.target, map, counter);
|
||||
en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private void noNameDisableMapFor_anchor(Node node, int[]map, Ptr counter) {
|
||||
AnchorNode an = (AnchorNode)node;
|
||||
switch (an.type) {
|
||||
case AnchorNode.PREC_READ:
|
||||
case AnchorNode.PREC_READ_NOT:
|
||||
case AnchorNode.LOOK_BEHIND:
|
||||
case AnchorNode.LOOK_BEHIND_NOT:
|
||||
an.setTarget(noNameDisableMap(an.target, map, counter));
|
||||
}
|
||||
}
|
||||
|
||||
private Node noNameDisableMap(Node node, int[]map, Ptr counter) {
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
case NodeType.ALT:
|
||||
noNameDisableMapFor_cosAlt(node, map, counter);
|
||||
break;
|
||||
case NodeType.QTFR:
|
||||
noNameDisableMapFor_quantifier(node, map, counter);
|
||||
break;
|
||||
case NodeType.ENCLOSE:
|
||||
node = noNameDisableMapFor_enclose(node, map, counter);
|
||||
break;
|
||||
case NodeType.ANCHOR:
|
||||
noNameDisableMapFor_anchor(node, map, counter);
|
||||
break;
|
||||
} // switch
|
||||
return node;
|
||||
}
|
||||
|
||||
private void renumberByMap(Node node, int[]map) {
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
renumberByMap(can.car, map);
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
renumberByMap(((QuantifierNode)node).target, map);
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
renumberByMap(((EncloseNode)node).target, map);
|
||||
break;
|
||||
|
||||
case NodeType.BREF:
|
||||
((BackRefNode)node).renumber(map);
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
protected final void numberedRefCheck(Node node) {
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
numberedRefCheck(can.car);
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
numberedRefCheck(((QuantifierNode)node).target);
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
numberedRefCheck(((EncloseNode)node).target);
|
||||
break;
|
||||
|
||||
case NodeType.BREF:
|
||||
BackRefNode br = (BackRefNode)node;
|
||||
if (!br.isNameRef()) newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
protected final Node disableNoNameGroupCapture(Node root) {
|
||||
int[]map = new int[env.numMem + 1];
|
||||
|
||||
for (int i=1; i<=env.numMem; i++) map[i] = 0;
|
||||
|
||||
root = noNameDisableMap(root, map, new Ptr(0));
|
||||
renumberByMap(root, map);
|
||||
|
||||
for (int i=1, pos=1; i<=env.numMem; i++) {
|
||||
if (map[i] > 0) {
|
||||
env.memNodes[pos] = env.memNodes[i];
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
int loc = env.captureHistory;
|
||||
env.captureHistory = bsClear();
|
||||
|
||||
for (int i=1; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
|
||||
if (bsAt(loc, i)) {
|
||||
env.captureHistory = bsOnAtSimple(env.captureHistory, map[i]);
|
||||
}
|
||||
}
|
||||
|
||||
env.numMem = env.numNamed;
|
||||
regex.numMem = env.numNamed;
|
||||
|
||||
regex.renumberNameTable(map);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void swap(Node a, Node b) {
|
||||
a.swap(b);
|
||||
|
||||
@ -352,17 +143,6 @@ final class Analyser extends Parser {
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
CallNode cn = (CallNode)node;
|
||||
if (cn.isRecursion()) {
|
||||
return TargetInfo.IS_EMPTY_REC; /* tiny version */
|
||||
} else {
|
||||
info = quantifiersMemoryInfo(cn.target);
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
QuantifierNode qn = (QuantifierNode)node;
|
||||
if (qn.upper != 0) {
|
||||
@ -417,18 +197,6 @@ final class Analyser extends Parser {
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
CallNode cn = (CallNode)node;
|
||||
if (cn.isRecursion()) {
|
||||
EncloseNode en = (EncloseNode)cn.target;
|
||||
if (en.isMinFixed()) min = en.minLength;
|
||||
} else {
|
||||
min = getMinMatchLength(cn.target);
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case NodeType.LIST:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
@ -474,15 +242,13 @@ final class Analyser extends Parser {
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
switch (en.type) {
|
||||
case EncloseType.MEMORY:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
if (en.isMinFixed()) {
|
||||
min = en.minLength;
|
||||
} else {
|
||||
min = getMinMatchLength(en.target);
|
||||
en.minLength = min;
|
||||
en.setMinFixed();
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
if (en.isMinFixed()) {
|
||||
min = en.minLength;
|
||||
} else {
|
||||
min = getMinMatchLength(en.target);
|
||||
en.minLength = min;
|
||||
en.setMinFixed();
|
||||
}
|
||||
break;
|
||||
|
||||
case EncloseType.OPTION:
|
||||
@ -547,17 +313,6 @@ final class Analyser extends Parser {
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
CallNode cn = (CallNode)node;
|
||||
if (!cn.isRecursion()) {
|
||||
max = getMaxMatchLength(cn.target);
|
||||
} else {
|
||||
max = MinMaxLen.INFINITE_DISTANCE;
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
QuantifierNode qn = (QuantifierNode)node;
|
||||
if (qn.upper != 0) {
|
||||
@ -576,15 +331,13 @@ final class Analyser extends Parser {
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
switch (en.type) {
|
||||
case EncloseType.MEMORY:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
if (en.isMaxFixed()) {
|
||||
max = en.maxLength;
|
||||
} else {
|
||||
max = getMaxMatchLength(en.target);
|
||||
en.maxLength = max;
|
||||
en.setMaxFixed();
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
if (en.isMaxFixed()) {
|
||||
max = en.maxLength;
|
||||
} else {
|
||||
max = getMaxMatchLength(en.target);
|
||||
en.maxLength = max;
|
||||
en.setMaxFixed();
|
||||
}
|
||||
break;
|
||||
|
||||
case EncloseType.OPTION:
|
||||
@ -663,17 +416,6 @@ final class Analyser extends Parser {
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
CallNode cn = (CallNode)node;
|
||||
if (!cn.isRecursion()) {
|
||||
len = getCharLengthTree(cn.target, level);
|
||||
} else {
|
||||
returnCode = GET_CHAR_LEN_VARLEN;
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case NodeType.CTYPE:
|
||||
len = 1;
|
||||
|
||||
@ -686,17 +428,15 @@ final class Analyser extends Parser {
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
switch(en.type) {
|
||||
case EncloseType.MEMORY:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
if (en.isCLenFixed()) {
|
||||
len = en.charLength;
|
||||
} else {
|
||||
len = getCharLengthTree(en.target, level);
|
||||
if (returnCode == 0) {
|
||||
en.charLength = len;
|
||||
en.setCLenFixed();
|
||||
}
|
||||
if (en.isCLenFixed()) {
|
||||
len = en.charLength;
|
||||
} else {
|
||||
len = getCharLengthTree(en.target, level);
|
||||
if (returnCode == 0) {
|
||||
en.charLength = len;
|
||||
en.setCLenFixed();
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
}
|
||||
break;
|
||||
|
||||
case EncloseType.OPTION:
|
||||
@ -727,10 +467,6 @@ final class Analyser extends Parser {
|
||||
switch(x.getType()) {
|
||||
case NodeType.CTYPE:
|
||||
switch(yType) {
|
||||
case NodeType.CTYPE:
|
||||
CTypeNode cny = (CTypeNode)y;
|
||||
CTypeNode cnx = (CTypeNode)x;
|
||||
return cny.ctype == cnx.ctype && cny.not != cnx.not;
|
||||
|
||||
case NodeType.CCLASS:
|
||||
// !swap:!
|
||||
@ -756,37 +492,6 @@ final class Analyser extends Parser {
|
||||
CClassNode xc = (CClassNode)x;
|
||||
|
||||
switch(yType) {
|
||||
case NodeType.CTYPE:
|
||||
switch(((CTypeNode)y).ctype) {
|
||||
case CharacterType.WORD:
|
||||
if (!((CTypeNode)y).not) {
|
||||
if (xc.mbuf == null && !xc.isNot()) {
|
||||
for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
|
||||
if (xc.bs.at(i)) {
|
||||
if (EncodingHelper.isWord(i)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
|
||||
if (!EncodingHelper.isWord(i)) {
|
||||
if (!xc.isNot()) {
|
||||
if (xc.bs.at(i)) return false;
|
||||
} else {
|
||||
if (!xc.bs.at(i)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// break; not reached
|
||||
|
||||
default:
|
||||
break;
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.CCLASS:
|
||||
CClassNode yc = (CClassNode)y;
|
||||
@ -820,17 +525,6 @@ final class Analyser extends Parser {
|
||||
if (xs.length() == 0) break;
|
||||
|
||||
switch (yType) {
|
||||
case NodeType.CTYPE:
|
||||
CTypeNode cy = ((CTypeNode)y);
|
||||
switch (cy.ctype) {
|
||||
case CharacterType.WORD:
|
||||
return !cy.not;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.CCLASS:
|
||||
CClassNode cc = (CClassNode)y;
|
||||
@ -873,9 +567,6 @@ final class Analyser extends Parser {
|
||||
case NodeType.CANY:
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
break; // if (Config.USE_SUBEXP_CALL)
|
||||
|
||||
case NodeType.CTYPE:
|
||||
case NodeType.CCLASS:
|
||||
if (!exact) n = node;
|
||||
@ -977,316 +668,6 @@ final class Analyser extends Parser {
|
||||
return invalid;
|
||||
}
|
||||
|
||||
private static final int RECURSION_EXIST = 1;
|
||||
private static final int RECURSION_INFINITE = 2;
|
||||
private int subexpInfRecursiveCheck(Node node, boolean head) {
|
||||
int r = 0;
|
||||
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
int min;
|
||||
ConsAltNode x = (ConsAltNode)node;
|
||||
do {
|
||||
int ret = subexpInfRecursiveCheck(x.car, head);
|
||||
if (ret == RECURSION_INFINITE) return ret;
|
||||
r |= ret;
|
||||
if (head) {
|
||||
min = getMinMatchLength(x.car);
|
||||
if (min != 0) head = false;
|
||||
}
|
||||
} while ((x = x.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
r = RECURSION_EXIST;
|
||||
do {
|
||||
int ret = subexpInfRecursiveCheck(can.car, head);
|
||||
if (ret == RECURSION_INFINITE) return ret;
|
||||
r &= ret;
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
QuantifierNode qn = (QuantifierNode)node;
|
||||
r = subexpInfRecursiveCheck(qn.target, head);
|
||||
if (r == RECURSION_EXIST) {
|
||||
if (qn.lower == 0) r = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.ANCHOR:
|
||||
AnchorNode an = (AnchorNode)node;
|
||||
switch (an.type) {
|
||||
case AnchorType.PREC_READ:
|
||||
case AnchorType.PREC_READ_NOT:
|
||||
case AnchorType.LOOK_BEHIND:
|
||||
case AnchorType.LOOK_BEHIND_NOT:
|
||||
r = subexpInfRecursiveCheck(an.target, head);
|
||||
break;
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
r = subexpInfRecursiveCheck(((CallNode)node).target, head);
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
if (en.isMark2()) {
|
||||
return 0;
|
||||
} else if (en.isMark1()) {
|
||||
return !head ? RECURSION_EXIST : RECURSION_INFINITE;
|
||||
// throw exception here ???
|
||||
} else {
|
||||
en.setMark2();
|
||||
r = subexpInfRecursiveCheck(en.target, head);
|
||||
en.clearMark2();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
return r;
|
||||
}
|
||||
|
||||
protected final int subexpInfRecursiveCheckTrav(Node node) {
|
||||
int r = 0;
|
||||
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
r = subexpInfRecursiveCheckTrav(can.car);
|
||||
} while (r == 0 && (can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
r = subexpInfRecursiveCheckTrav(((QuantifierNode)node).target);
|
||||
break;
|
||||
|
||||
case NodeType.ANCHOR:
|
||||
AnchorNode an = (AnchorNode)node;
|
||||
switch (an.type) {
|
||||
case AnchorType.PREC_READ:
|
||||
case AnchorType.PREC_READ_NOT:
|
||||
case AnchorType.LOOK_BEHIND:
|
||||
case AnchorType.LOOK_BEHIND_NOT:
|
||||
r = subexpInfRecursiveCheckTrav(an.target);
|
||||
break;
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
if (en.isRecursion()) {
|
||||
en.setMark1();
|
||||
r = subexpInfRecursiveCheck(en.target, true);
|
||||
if (r > 0) newValueException(ERR_NEVER_ENDING_RECURSION);
|
||||
en.clearMark1();
|
||||
}
|
||||
r = subexpInfRecursiveCheckTrav(en.target);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private int subexpRecursiveCheck(Node node) {
|
||||
int r = 0;
|
||||
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
r |= subexpRecursiveCheck(can.car);
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
r = subexpRecursiveCheck(((QuantifierNode)node).target);
|
||||
break;
|
||||
|
||||
case NodeType.ANCHOR:
|
||||
AnchorNode an = (AnchorNode)node;
|
||||
switch (an.type) {
|
||||
case AnchorType.PREC_READ:
|
||||
case AnchorType.PREC_READ_NOT:
|
||||
case AnchorType.LOOK_BEHIND:
|
||||
case AnchorType.LOOK_BEHIND_NOT:
|
||||
r = subexpRecursiveCheck(an.target);
|
||||
break;
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
CallNode cn = (CallNode)node;
|
||||
r = subexpRecursiveCheck(cn.target);
|
||||
if (r != 0) cn.setRecursion();
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
if (en.isMark2()) {
|
||||
return 0;
|
||||
} else if (en.isMark1()) {
|
||||
return 1; /* recursion */
|
||||
} else {
|
||||
en.setMark2();
|
||||
r = subexpRecursiveCheck(en.target);
|
||||
en.clearMark2();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private static final int FOUND_CALLED_NODE = 1;
|
||||
protected final int subexpRecursiveCheckTrav(Node node) {
|
||||
int r = 0;
|
||||
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
int ret = subexpRecursiveCheckTrav(can.car);
|
||||
if (ret == FOUND_CALLED_NODE) {
|
||||
r = FOUND_CALLED_NODE;
|
||||
}
|
||||
// else if (ret < 0) return ret; ???
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
QuantifierNode qn = (QuantifierNode)node;
|
||||
r = subexpRecursiveCheckTrav(qn.target);
|
||||
if (qn.upper == 0) {
|
||||
if (r == FOUND_CALLED_NODE) qn.isRefered = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.ANCHOR:
|
||||
AnchorNode an = (AnchorNode)node;
|
||||
switch (an.type) {
|
||||
case AnchorType.PREC_READ:
|
||||
case AnchorType.PREC_READ_NOT:
|
||||
case AnchorType.LOOK_BEHIND:
|
||||
case AnchorType.LOOK_BEHIND_NOT:
|
||||
r = subexpRecursiveCheckTrav(an.target);
|
||||
break;
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
if (!en.isRecursion()) {
|
||||
if (en.isCalled()) {
|
||||
en.setMark1();
|
||||
r = subexpRecursiveCheck(en.target);
|
||||
if (r != 0) en.setRecursion();
|
||||
en.clearMark1();
|
||||
}
|
||||
}
|
||||
r = subexpRecursiveCheckTrav(en.target);
|
||||
if (en.isCalled()) r |= FOUND_CALLED_NODE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private void setCallAttr(CallNode cn) {
|
||||
cn.target = env.memNodes[cn.groupNum]; // no setTarget in call nodes!
|
||||
if (cn.target == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
|
||||
|
||||
((EncloseNode)cn.target).setCalled();
|
||||
env.btMemStart = BitStatus.bsOnAt(env.btMemStart, cn.groupNum);
|
||||
cn.unsetAddrList = env.unsetAddrList;
|
||||
}
|
||||
|
||||
protected final void setupSubExpCall(Node node) {
|
||||
|
||||
switch(node.getType()) {
|
||||
case NodeType.LIST:
|
||||
ConsAltNode ln = (ConsAltNode)node;
|
||||
do {
|
||||
setupSubExpCall(ln.car);
|
||||
} while ((ln = ln.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.ALT:
|
||||
ConsAltNode can = (ConsAltNode)node;
|
||||
do {
|
||||
setupSubExpCall(can.car);
|
||||
} while ((can = can.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
setupSubExpCall(((QuantifierNode)node).target);
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
setupSubExpCall(((EncloseNode)node).target);
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
CallNode cn = (CallNode)node;
|
||||
|
||||
if (cn.groupNum != 0) {
|
||||
int gNum = cn.groupNum;
|
||||
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(env.option)) {
|
||||
newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
|
||||
}
|
||||
} // USE_NAMED_GROUP
|
||||
if (gNum > env.numMem) newValueException(ERR_UNDEFINED_GROUP_REFERENCE, cn.nameP, cn.nameEnd);
|
||||
setCallAttr(cn);
|
||||
} else {
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
NameEntry ne = regex.nameToGroupNumbers(cn.name, cn.nameP, cn.nameEnd);
|
||||
|
||||
if (ne == null) {
|
||||
newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
|
||||
} else if (ne.backNum > 1) {
|
||||
newValueException(ERR_MULTIPLEX_DEFINITION_NAME_CALL, cn.nameP, cn.nameEnd);
|
||||
} else {
|
||||
cn.groupNum = ne.backRef1; // ne.backNum == 1 ? ne.backRef1 : ne.backRefs[0]; // ??? need to check ?
|
||||
setCallAttr(cn);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.ANCHOR:
|
||||
AnchorNode an = (AnchorNode)node;
|
||||
switch (an.type) {
|
||||
case AnchorType.PREC_READ:
|
||||
case AnchorType.PREC_READ_NOT:
|
||||
case AnchorType.LOOK_BEHIND:
|
||||
case AnchorType.LOOK_BEHIND_NOT:
|
||||
setupSubExpCall(an.target);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
} // switch
|
||||
}
|
||||
|
||||
/* divide different length alternatives in look-behind.
|
||||
(?<=A|B) ==> (?<=A)|(?<=B)
|
||||
(?<!A|B) ==> (?<!A)(?<!B)
|
||||
@ -1523,125 +904,6 @@ final class Analyser extends Parser {
|
||||
return xnode;
|
||||
}
|
||||
|
||||
private static final int CEC_THRES_NUM_BIG_REPEAT = 512;
|
||||
private static final int CEC_INFINITE_NUM = 0x7fffffff;
|
||||
|
||||
private static final int CEC_IN_INFINITE_REPEAT = (1<<0);
|
||||
private static final int CEC_IN_FINITE_REPEAT = (1<<1);
|
||||
private static final int CEC_CONT_BIG_REPEAT = (1<<2);
|
||||
|
||||
protected final int setupCombExpCheck(Node node, int state) {
|
||||
int r = state;
|
||||
int ret;
|
||||
|
||||
switch (node.getType()) {
|
||||
case NodeType.LIST:
|
||||
ConsAltNode ln = (ConsAltNode)node;
|
||||
|
||||
do {
|
||||
r = setupCombExpCheck(ln.car, r);
|
||||
//prev = ((ConsAltNode)node).car;
|
||||
} while (r >= 0 && (ln = ln.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.ALT:
|
||||
ConsAltNode an = (ConsAltNode)node;
|
||||
do {
|
||||
ret = setupCombExpCheck(an.car, state);
|
||||
r |= ret;
|
||||
} while (ret >= 0 && (an = an.cdr) != null);
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
QuantifierNode qn = (QuantifierNode)node;
|
||||
int childState = state;
|
||||
int addState = 0;
|
||||
int varNum;
|
||||
|
||||
if (!isRepeatInfinite(qn.upper)) {
|
||||
if (qn.upper > 1) {
|
||||
/* {0,1}, {1,1} are allowed */
|
||||
childState |= CEC_IN_FINITE_REPEAT;
|
||||
|
||||
/* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
|
||||
if (env.backrefedMem == 0) {
|
||||
if (qn.target.getType() == NodeType.ENCLOSE) {
|
||||
EncloseNode en = (EncloseNode)qn.target;
|
||||
if (en.type == EncloseType.MEMORY) {
|
||||
if (en.target.getType() == NodeType.QTFR) {
|
||||
QuantifierNode q = (QuantifierNode)en.target;
|
||||
if (isRepeatInfinite(q.upper) && q.greedy == qn.greedy) {
|
||||
qn.upper = qn.lower == 0 ? 1 : qn.lower;
|
||||
if (qn.upper == 1) childState = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((state & CEC_IN_FINITE_REPEAT) != 0) {
|
||||
qn.combExpCheckNum = -1;
|
||||
} else {
|
||||
if (isRepeatInfinite(qn.upper)) {
|
||||
varNum = CEC_INFINITE_NUM;
|
||||
childState |= CEC_IN_INFINITE_REPEAT;
|
||||
} else {
|
||||
varNum = qn.upper - qn.lower;
|
||||
}
|
||||
|
||||
if (varNum >= CEC_THRES_NUM_BIG_REPEAT) addState |= CEC_CONT_BIG_REPEAT;
|
||||
|
||||
if (((state & CEC_IN_INFINITE_REPEAT) != 0 && varNum != 0) ||
|
||||
((state & CEC_CONT_BIG_REPEAT) != 0 && varNum >= CEC_THRES_NUM_BIG_REPEAT)) {
|
||||
if (qn.combExpCheckNum == 0) {
|
||||
env.numCombExpCheck++;
|
||||
qn.combExpCheckNum = env.numCombExpCheck;
|
||||
if (env.currMaxRegNum > env.combExpMaxRegNum) {
|
||||
env.combExpMaxRegNum = env.currMaxRegNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r = setupCombExpCheck(qn.target, childState);
|
||||
r |= addState;
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
EncloseNode en = (EncloseNode)node;
|
||||
switch( en.type) {
|
||||
case EncloseNode.MEMORY:
|
||||
if (env.currMaxRegNum < en.regNum) {
|
||||
env.currMaxRegNum = en.regNum;
|
||||
}
|
||||
r = setupCombExpCheck(en.target, state);
|
||||
break;
|
||||
|
||||
default:
|
||||
r = setupCombExpCheck(en.target, state);
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
CallNode cn = (CallNode)node;
|
||||
if (cn.isRecursion()) {
|
||||
env.hasRecursion = true;
|
||||
} else {
|
||||
r = setupCombExpCheck(cn.target, state);
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
} // switch
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private static final int IN_ALT = (1<<0);
|
||||
private static final int IN_NOT = (1<<1);
|
||||
private static final int IN_REPEAT = (1<<2);
|
||||
@ -1691,20 +953,12 @@ final class Analyser extends Parser {
|
||||
case NodeType.CANY:
|
||||
break;
|
||||
|
||||
case NodeType.CALL: // if (Config.USE_SUBEXP_CALL) ?
|
||||
break;
|
||||
|
||||
case NodeType.BREF:
|
||||
BackRefNode br = (BackRefNode)node;
|
||||
for (int i=0; i<br.backNum; i++) {
|
||||
if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
|
||||
env.backrefedMem = bsOnAt(env.backrefedMem, br.back[i]);
|
||||
env.btMemStart = bsOnAt(env.btMemStart, br.back[i]);
|
||||
if (Config.USE_BACKREF_WITH_LEVEL) {
|
||||
if (br.isNestLevel()) {
|
||||
env.btMemEnd = bsOnAt(env.btMemEnd, br.back[i]);
|
||||
}
|
||||
} // USE_BACKREF_AT_LEVEL
|
||||
((EncloseNode)env.memNodes[br.back[i]]).setMemBackrefed();
|
||||
}
|
||||
break;
|
||||
@ -1916,37 +1170,6 @@ final class Analyser extends Parser {
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeType.CTYPE: {
|
||||
int min;
|
||||
int max = 1;
|
||||
if (max == 1) {
|
||||
min = 1;
|
||||
CTypeNode cn = (CTypeNode)node;
|
||||
|
||||
switch (cn.ctype) {
|
||||
case CharacterType.WORD:
|
||||
if (cn.not) {
|
||||
for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
|
||||
if (!EncodingHelper.isWord(i)) {
|
||||
opt.map.addChar(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
|
||||
if (EncodingHelper.isWord(i)) {
|
||||
opt.map.addChar(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // inner switch
|
||||
} else {
|
||||
min = 1;
|
||||
}
|
||||
opt.length.set(min, max);
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeType.CANY: {
|
||||
opt.length.set(1, 1);
|
||||
break;
|
||||
@ -2008,20 +1231,6 @@ final class Analyser extends Parser {
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeType.CALL: {
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
CallNode cn = (CallNode)node;
|
||||
if (cn.isRecursion()) {
|
||||
opt.length.set(0, MinMaxLen.INFINITE_DISTANCE);
|
||||
} else {
|
||||
int safe = oenv.options;
|
||||
oenv.options = ((EncloseNode)cn.target).option;
|
||||
optimizeNodeLeft(cn.target, opt, oenv);
|
||||
oenv.options = safe;
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeType.QTFR: {
|
||||
NodeOptInfo nopt = new NodeOptInfo();
|
||||
@ -2081,7 +1290,7 @@ final class Analyser extends Parser {
|
||||
break;
|
||||
|
||||
case EncloseType.MEMORY:
|
||||
if (Config.USE_SUBEXP_CALL && ++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
|
||||
if (++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
|
||||
int min = 0;
|
||||
int max = MinMaxLen.INFINITE_DISTANCE;
|
||||
if (en.isMinFixed()) min = en.minLength;
|
||||
|
@ -28,8 +28,6 @@ import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepe
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
|
||||
@ -71,11 +69,6 @@ final class ArrayCompiler extends Compiler {
|
||||
regex.templates = templates;
|
||||
regex.templateNum = templateNum;
|
||||
regex.factory = MatcherFactory.DEFAULT;
|
||||
|
||||
if (Config.USE_SUBEXP_CALL && analyser.env.unsetAddrList != null) {
|
||||
analyser.env.unsetAddrList.fix(regex);
|
||||
analyser.env.unsetAddrList = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,7 +112,7 @@ final class ArrayCompiler extends Compiler {
|
||||
return isNeedStrLenOpExact(op);
|
||||
}
|
||||
|
||||
private int selectStrOpcode(int mbLength, int strLength, boolean ignoreCase) {
|
||||
private int selectStrOpcode(int strLength, boolean ignoreCase) {
|
||||
int op;
|
||||
|
||||
if (ignoreCase) {
|
||||
@ -128,31 +121,14 @@ final class ArrayCompiler extends Compiler {
|
||||
default:op = OPCode.EXACTN_IC; break;
|
||||
} // switch
|
||||
} else {
|
||||
switch (mbLength) {
|
||||
case 1:
|
||||
switch (strLength) {
|
||||
case 1: op = OPCode.EXACT1; break;
|
||||
case 2: op = OPCode.EXACT2; break;
|
||||
case 3: op = OPCode.EXACT3; break;
|
||||
case 4: op = OPCode.EXACT4; break;
|
||||
case 5: op = OPCode.EXACT5; break;
|
||||
default:op = OPCode.EXACTN; break;
|
||||
} // inner switch
|
||||
break;
|
||||
case 2:
|
||||
switch (strLength) {
|
||||
case 1: op = OPCode.EXACTMB2N1; break;
|
||||
case 2: op = OPCode.EXACTMB2N2; break;
|
||||
case 3: op = OPCode.EXACTMB2N3; break;
|
||||
default:op = OPCode.EXACTMB2N; break;
|
||||
} // inner switch
|
||||
break;
|
||||
case 3:
|
||||
op = OPCode.EXACTMB3N;
|
||||
break;
|
||||
default:
|
||||
op = OPCode.EXACTMBN;
|
||||
} // switch
|
||||
switch (strLength) {
|
||||
case 1: op = OPCode.EXACT1; break;
|
||||
case 2: op = OPCode.EXACT2; break;
|
||||
case 3: op = OPCode.EXACT3; break;
|
||||
case 4: op = OPCode.EXACT4; break;
|
||||
case 5: op = OPCode.EXACT5; break;
|
||||
default:op = OPCode.EXACTN; break;
|
||||
} // inner switch
|
||||
}
|
||||
return op;
|
||||
}
|
||||
@ -185,8 +161,8 @@ final class ArrayCompiler extends Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
private int addCompileStringlength(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
|
||||
int op = selectStrOpcode(mbLength, strLength, ignoreCase);
|
||||
private int addCompileStringlength(char[] chars, int p, int strLength, boolean ignoreCase) {
|
||||
int op = selectStrOpcode(strLength, ignoreCase);
|
||||
int len = OPSize.OPCODE;
|
||||
|
||||
if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
|
||||
@ -194,25 +170,21 @@ final class ArrayCompiler extends Compiler {
|
||||
len += OPSize.LENGTH + OPSize.INDEX + OPSize.INDEX;
|
||||
} else {
|
||||
if (isNeedStrLenOpExact(op)) len += OPSize.LENGTH;
|
||||
len += mbLength * strLength;
|
||||
len += strLength;
|
||||
}
|
||||
if (op == OPCode.EXACTMBN) len += OPSize.LENGTH;
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
|
||||
int op = selectStrOpcode(mbLength, strLength, ignoreCase);
|
||||
protected final void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase) {
|
||||
int op = selectStrOpcode(strLength, ignoreCase);
|
||||
addOpcode(op);
|
||||
|
||||
if (op == OPCode.EXACTMBN) addLength(mbLength);
|
||||
if (op == OPCode.EXACTMBN) addLength(1);
|
||||
|
||||
if (isNeedStrLenOpExact(op)) {
|
||||
if (op == OPCode.EXACTN_IC || op == OPCode.EXACTN_IC_SB) {
|
||||
addLength(mbLength * strLength);
|
||||
} else {
|
||||
addLength(strLength);
|
||||
}
|
||||
addLength(strLength);
|
||||
}
|
||||
|
||||
if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
|
||||
@ -220,7 +192,7 @@ final class ArrayCompiler extends Compiler {
|
||||
addInt(p);
|
||||
addTemplate(chars);
|
||||
} else {
|
||||
addChars(chars, p, mbLength * strLength);
|
||||
addChars(chars, p, strLength);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,14 +214,14 @@ final class ArrayCompiler extends Compiler {
|
||||
slen++;
|
||||
p++;
|
||||
}
|
||||
int r = addCompileStringlength(chars, prev, 1, slen, ambig);
|
||||
int r = addCompileStringlength(chars, prev, slen, ambig);
|
||||
rlen += r;
|
||||
return rlen;
|
||||
}
|
||||
|
||||
private int compileLengthStringRawNode(StringNode sn) {
|
||||
if (sn.length() <= 0) return 0;
|
||||
return addCompileStringlength(sn.chars, sn.p, 1 /*sb*/, sn.length(), false);
|
||||
return addCompileStringlength(sn.chars, sn.p, sn.length(), false);
|
||||
}
|
||||
|
||||
private void addMultiByteCClass(CodeRangeBuffer mbuf) {
|
||||
@ -311,26 +283,6 @@ final class ArrayCompiler extends Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCTypeNode(CTypeNode node) {
|
||||
CTypeNode cn = node;
|
||||
int op;
|
||||
switch (cn.ctype) {
|
||||
case CharacterType.WORD:
|
||||
if (cn.not) {
|
||||
op = OPCode.NOT_WORD;
|
||||
} else {
|
||||
op = OPCode.WORD;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
newInternalException(ERR_PARSER_BUG);
|
||||
return; // not reached
|
||||
} // inner switch
|
||||
addOpcode(op);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileAnyCharNode() {
|
||||
if (isMultiline(regex.options)) {
|
||||
@ -340,31 +292,16 @@ final class ArrayCompiler extends Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCallNode(CallNode node) {
|
||||
addOpcode(OPCode.CALL);
|
||||
node.unsetAddrList.add(codeLength, node.target);
|
||||
addAbsAddr(0); /*dummy addr.*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileBackrefNode(BackRefNode node) {
|
||||
BackRefNode br = node;
|
||||
if (Config.USE_BACKREF_WITH_LEVEL && br.isNestLevel()) {
|
||||
addOpcode(OPCode.BACKREF_WITH_LEVEL);
|
||||
addOption(regex.options & Option.IGNORECASE);
|
||||
addLength(br.nestLevel);
|
||||
// !goto add_bacref_mems;!
|
||||
addLength(br.backNum);
|
||||
for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
|
||||
return;
|
||||
} else { // USE_BACKREF_AT_LEVEL
|
||||
if (br.backNum == 1) {
|
||||
if (isIgnoreCase(regex.options)) {
|
||||
addOpcode(OPCode.BACKREFN_IC);
|
||||
addMemNum(br.back[0]);
|
||||
} else {
|
||||
switch (br.back[0]) {
|
||||
// USE_BACKREF_AT_LEVEL
|
||||
if (br.backNum == 1) {
|
||||
if (isIgnoreCase(regex.options)) {
|
||||
addOpcode(OPCode.BACKREFN_IC);
|
||||
addMemNum(br.back[0]);
|
||||
} else {
|
||||
switch (br.back[0]) {
|
||||
case 1:
|
||||
addOpcode(OPCode.BACKREF1);
|
||||
break;
|
||||
@ -375,18 +312,17 @@ final class ArrayCompiler extends Compiler {
|
||||
addOpcode(OPCode.BACKREFN);
|
||||
addOpcode(br.back[0]);
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
} else {
|
||||
if (isIgnoreCase(regex.options)) {
|
||||
addOpcode(OPCode.BACKREF_MULTI_IC);
|
||||
} else {
|
||||
addOpcode(OPCode.BACKREF_MULTI);
|
||||
}
|
||||
// !add_bacref_mems:!
|
||||
addLength(br.backNum);
|
||||
for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
|
||||
} // switch
|
||||
}
|
||||
} else {
|
||||
if (isIgnoreCase(regex.options)) {
|
||||
addOpcode(OPCode.BACKREF_MULTI_IC);
|
||||
} else {
|
||||
addOpcode(OPCode.BACKREF_MULTI);
|
||||
}
|
||||
// !add_bacref_mems:!
|
||||
addLength(br.backNum);
|
||||
for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +355,7 @@ final class ArrayCompiler extends Compiler {
|
||||
|
||||
compileTreeEmptyCheck(qn.target, emptyInfo);
|
||||
|
||||
if ((Config.USE_SUBEXP_CALL && regex.numCall > 0) || qn.isInRepeat()) {
|
||||
if (qn.isInRepeat()) {
|
||||
addOpcode(qn.greedy ? OPCode.REPEAT_INC_SG : OPCode.REPEAT_INC_NG_SG);
|
||||
} else {
|
||||
addOpcode(qn.greedy ? OPCode.REPEAT_INC : OPCode.REPEAT_INC_NG);
|
||||
@ -434,193 +370,6 @@ final class ArrayCompiler extends Compiler {
|
||||
return ckn > 0;
|
||||
}
|
||||
|
||||
private int compileCECLengthQuantifierNode(QuantifierNode qn) {
|
||||
boolean infinite = isRepeatInfinite(qn.upper);
|
||||
int emptyInfo = qn.targetEmptyInfo;
|
||||
|
||||
int tlen = compileLengthTree(qn.target);
|
||||
int ckn = regex.numCombExpCheck > 0 ? qn.combExpCheckNum : 0;
|
||||
int cklen = cknOn(ckn) ? OPSize.STATE_CHECK_NUM : 0;
|
||||
|
||||
/* anychar repeat */
|
||||
if (qn.target.getType() == NodeType.CANY) {
|
||||
if (qn.greedy && infinite) {
|
||||
if (qn.nextHeadExact != null && !cknOn(ckn)) {
|
||||
return OPSize.ANYCHAR_STAR_PEEK_NEXT + tlen * qn.lower + cklen;
|
||||
} else {
|
||||
return OPSize.ANYCHAR_STAR + tlen * qn.lower + cklen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int modTLen;
|
||||
if (emptyInfo != 0) {
|
||||
modTLen = tlen + (OPSize.NULL_CHECK_START + OPSize.NULL_CHECK_END);
|
||||
} else {
|
||||
modTLen = tlen;
|
||||
}
|
||||
|
||||
int len;
|
||||
if (infinite && qn.lower <= 1) {
|
||||
if (qn.greedy) {
|
||||
if (qn.lower == 1) {
|
||||
len = OPSize.JUMP;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
len += OPSize.PUSH + cklen + modTLen + OPSize.JUMP;
|
||||
} else {
|
||||
if (qn.lower == 0) {
|
||||
len = OPSize.JUMP;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
len += modTLen + OPSize.PUSH + cklen;
|
||||
}
|
||||
} else if (qn.upper == 0) {
|
||||
if (qn.isRefered) { /* /(?<n>..){0}/ */
|
||||
len = OPSize.JUMP + tlen;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
} else if (qn.upper == 1 && qn.greedy) {
|
||||
if (qn.lower == 0) {
|
||||
if (cknOn(ckn)) {
|
||||
len = OPSize.STATE_CHECK_PUSH + tlen;
|
||||
} else {
|
||||
len = OPSize.PUSH + tlen;
|
||||
}
|
||||
} else {
|
||||
len = tlen;
|
||||
}
|
||||
} else if (!qn.greedy && qn.upper == 1 && qn.lower == 0) { /* '??' */
|
||||
len = OPSize.PUSH + cklen + OPSize.JUMP + tlen;
|
||||
} else {
|
||||
len = OPSize.REPEAT_INC + modTLen + OPSize.OPCODE + OPSize.RELADDR + OPSize.MEMNUM;
|
||||
|
||||
if (cknOn(ckn)) {
|
||||
len += OPSize.STATE_CHECK;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCECQuantifierNode(QuantifierNode qn) {
|
||||
boolean infinite = isRepeatInfinite(qn.upper);
|
||||
int emptyInfo = qn.targetEmptyInfo;
|
||||
|
||||
int tlen = compileLengthTree(qn.target);
|
||||
|
||||
int ckn = regex.numCombExpCheck > 0 ? qn.combExpCheckNum : 0;
|
||||
|
||||
if (qn.isAnyCharStar()) {
|
||||
compileTreeNTimes(qn.target, qn.lower);
|
||||
if (qn.nextHeadExact != null && !cknOn(ckn)) {
|
||||
if (isMultiline(regex.options)) {
|
||||
addOpcode(OPCode.ANYCHAR_ML_STAR_PEEK_NEXT);
|
||||
} else {
|
||||
addOpcode(OPCode.ANYCHAR_STAR_PEEK_NEXT);
|
||||
}
|
||||
if (cknOn(ckn)) {
|
||||
addStateCheckNum(ckn);
|
||||
}
|
||||
StringNode sn = (StringNode)qn.nextHeadExact;
|
||||
addChars(sn.chars, sn.p, 1);
|
||||
return;
|
||||
} else {
|
||||
if (isMultiline(regex.options)) {
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK_ANYCHAR_ML_STAR);
|
||||
} else {
|
||||
addOpcode(OPCode.ANYCHAR_ML_STAR);
|
||||
}
|
||||
} else {
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK_ANYCHAR_STAR);
|
||||
} else {
|
||||
addOpcode(OPCode.ANYCHAR_STAR);
|
||||
}
|
||||
}
|
||||
if (cknOn(ckn)) {
|
||||
addStateCheckNum(ckn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int modTLen;
|
||||
if (emptyInfo != 0) {
|
||||
modTLen = tlen + (OPSize.NULL_CHECK_START + OPSize.NULL_CHECK_END);
|
||||
} else {
|
||||
modTLen = tlen;
|
||||
}
|
||||
if (infinite && qn.lower <= 1) {
|
||||
if (qn.greedy) {
|
||||
if (qn.lower == 1) {
|
||||
addOpcodeRelAddr(OPCode.JUMP, cknOn(ckn) ? OPSize.STATE_CHECK_PUSH :
|
||||
OPSize.PUSH);
|
||||
}
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK_PUSH);
|
||||
addStateCheckNum(ckn);
|
||||
addRelAddr(modTLen + OPSize.JUMP);
|
||||
} else {
|
||||
addOpcodeRelAddr(OPCode.PUSH, modTLen + OPSize.JUMP);
|
||||
}
|
||||
compileTreeEmptyCheck(qn.target, emptyInfo);
|
||||
addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + (cknOn(ckn) ?
|
||||
OPSize.STATE_CHECK_PUSH :
|
||||
OPSize.PUSH)));
|
||||
} else {
|
||||
if (qn.lower == 0) {
|
||||
addOpcodeRelAddr(OPCode.JUMP, modTLen);
|
||||
}
|
||||
compileTreeEmptyCheck(qn.target, emptyInfo);
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK_PUSH_OR_JUMP);
|
||||
addStateCheckNum(ckn);
|
||||
addRelAddr(-(modTLen + OPSize.STATE_CHECK_PUSH_OR_JUMP));
|
||||
} else {
|
||||
addOpcodeRelAddr(OPCode.PUSH, -(modTLen + OPSize.PUSH));
|
||||
}
|
||||
}
|
||||
} else if (qn.upper == 0) {
|
||||
if (qn.isRefered) { /* /(?<n>..){0}/ */
|
||||
addOpcodeRelAddr(OPCode.JUMP, tlen);
|
||||
compileTree(qn.target);
|
||||
} // else r=0 ???
|
||||
} else if (qn.upper == 1 && qn.greedy) {
|
||||
if (qn.lower == 0) {
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK_PUSH);
|
||||
addStateCheckNum(ckn);
|
||||
addRelAddr(tlen);
|
||||
} else {
|
||||
addOpcodeRelAddr(OPCode.PUSH, tlen);
|
||||
}
|
||||
}
|
||||
compileTree(qn.target);
|
||||
} else if (!qn.greedy && qn.upper == 1 && qn.lower == 0){ /* '??' */
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK_PUSH);
|
||||
addStateCheckNum(ckn);
|
||||
addRelAddr(OPSize.JUMP);
|
||||
} else {
|
||||
addOpcodeRelAddr(OPCode.PUSH, OPSize.JUMP);
|
||||
}
|
||||
|
||||
addOpcodeRelAddr(OPCode.JUMP, tlen);
|
||||
compileTree(qn.target);
|
||||
} else {
|
||||
compileRangeRepeatNode(qn, modTLen, emptyInfo);
|
||||
if (cknOn(ckn)) {
|
||||
addOpcode(OPCode.STATE_CHECK);
|
||||
addStateCheckNum(ckn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int compileNonCECLengthQuantifierNode(QuantifierNode qn) {
|
||||
boolean infinite = isRepeatInfinite(qn.upper);
|
||||
int emptyInfo = qn.targetEmptyInfo;
|
||||
@ -821,21 +570,12 @@ final class ArrayCompiler extends Compiler {
|
||||
int len;
|
||||
switch (node.type) {
|
||||
case EncloseType.MEMORY:
|
||||
if (Config.USE_SUBEXP_CALL && node.isCalled()) {
|
||||
len = OPSize.MEMORY_START_PUSH + tlen + OPSize.CALL + OPSize.JUMP + OPSize.RETURN;
|
||||
if (bsAt(regex.btMemEnd, node.regNum)) {
|
||||
len += node.isRecursion() ? OPSize.MEMORY_END_PUSH_REC : OPSize.MEMORY_END_PUSH;
|
||||
} else {
|
||||
len += node.isRecursion() ? OPSize.MEMORY_END_REC : OPSize.MEMORY_END;
|
||||
}
|
||||
} else { // USE_SUBEXP_CALL
|
||||
if (bsAt(regex.btMemStart, node.regNum)) {
|
||||
len = OPSize.MEMORY_START_PUSH;
|
||||
} else {
|
||||
len = OPSize.MEMORY_START;
|
||||
}
|
||||
len += tlen + (bsAt(regex.btMemEnd, node.regNum) ? OPSize.MEMORY_END_PUSH : OPSize.MEMORY_END);
|
||||
if (bsAt(regex.btMemStart, node.regNum)) {
|
||||
len = OPSize.MEMORY_START_PUSH;
|
||||
} else {
|
||||
len = OPSize.MEMORY_START;
|
||||
}
|
||||
len += tlen + (bsAt(regex.btMemEnd, node.regNum) ? OPSize.MEMORY_END_PUSH : OPSize.MEMORY_END);
|
||||
break;
|
||||
|
||||
case EncloseType.STOP_BACKTRACK:
|
||||
@ -860,23 +600,6 @@ final class ArrayCompiler extends Compiler {
|
||||
int len;
|
||||
switch (node.type) {
|
||||
case EncloseType.MEMORY:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
if (node.isCalled()) {
|
||||
addOpcode(OPCode.CALL);
|
||||
node.callAddr = codeLength + OPSize.ABSADDR + OPSize.JUMP;
|
||||
node.setAddrFixed();
|
||||
addAbsAddr(node.callAddr);
|
||||
len = compileLengthTree(node.target);
|
||||
len += OPSize.MEMORY_START_PUSH + OPSize.RETURN;
|
||||
if (bsAt(regex.btMemEnd, node.regNum)) {
|
||||
len += node.isRecursion() ? OPSize.MEMORY_END_PUSH_REC : OPSize.MEMORY_END_PUSH;
|
||||
} else {
|
||||
len += node.isRecursion() ? OPSize.MEMORY_END_REC : OPSize.MEMORY_END;
|
||||
}
|
||||
addOpcodeRelAddr(OPCode.JUMP, len);
|
||||
}
|
||||
} // USE_SUBEXP_CALL
|
||||
|
||||
if (bsAt(regex.btMemStart, node.regNum)) {
|
||||
addOpcode(OPCode.MEMORY_START_PUSH);
|
||||
} else {
|
||||
@ -886,22 +609,12 @@ final class ArrayCompiler extends Compiler {
|
||||
addMemNum(node.regNum);
|
||||
compileTree(node.target);
|
||||
|
||||
if (Config.USE_SUBEXP_CALL && node.isCalled()) {
|
||||
if (bsAt(regex.btMemEnd, node.regNum)) {
|
||||
addOpcode(node.isRecursion() ? OPCode.MEMORY_END_PUSH_REC : OPCode.MEMORY_END_PUSH);
|
||||
} else {
|
||||
addOpcode(node.isRecursion() ? OPCode.MEMORY_END_REC : OPCode.MEMORY_END);
|
||||
}
|
||||
addMemNum(node.regNum);
|
||||
addOpcode(OPCode.RETURN);
|
||||
} else { // USE_SUBEXP_CALL
|
||||
if (bsAt(regex.btMemEnd, node.regNum)) {
|
||||
addOpcode(OPCode.MEMORY_END_PUSH);
|
||||
} else {
|
||||
addOpcode(OPCode.MEMORY_END);
|
||||
}
|
||||
addMemNum(node.regNum);
|
||||
if (bsAt(regex.btMemEnd, node.regNum)) {
|
||||
addOpcode(OPCode.MEMORY_END_PUSH);
|
||||
} else {
|
||||
addOpcode(OPCode.MEMORY_END);
|
||||
}
|
||||
addMemNum(node.regNum);
|
||||
break;
|
||||
|
||||
case EncloseType.STOP_BACKTRACK:
|
||||
@ -1078,32 +791,17 @@ final class ArrayCompiler extends Compiler {
|
||||
case NodeType.BREF:
|
||||
BackRefNode br = (BackRefNode)node;
|
||||
|
||||
if (Config.USE_BACKREF_WITH_LEVEL && br.isNestLevel()) {
|
||||
len = OPSize.OPCODE + OPSize.OPTION + OPSize.LENGTH +
|
||||
OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
|
||||
} else { // USE_BACKREF_AT_LEVEL
|
||||
if (br.backNum == 1) {
|
||||
len = ((!isIgnoreCase(regex.options) && br.back[0] <= 2)
|
||||
? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
|
||||
} else {
|
||||
len = OPSize.OPCODE + OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
|
||||
}
|
||||
// USE_BACKREF_AT_LEVEL
|
||||
if (br.backNum == 1) {
|
||||
len = ((!isIgnoreCase(regex.options) && br.back[0] <= 2)
|
||||
? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
|
||||
} else {
|
||||
len = OPSize.OPCODE + OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
|
||||
}
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
len = OPSize.CALL;
|
||||
break;
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
len = compileCECLengthQuantifierNode((QuantifierNode)node);
|
||||
} else {
|
||||
len = compileNonCECLengthQuantifierNode((QuantifierNode)node);
|
||||
}
|
||||
len = compileNonCECLengthQuantifierNode((QuantifierNode)node);
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
|
||||
|
||||
final class AsmCompiler extends AsmCompilerSupport {
|
||||
|
||||
public AsmCompiler(Analyser analyser) {
|
||||
super(analyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepare() {
|
||||
REG_NUM++;
|
||||
prepareMachine();
|
||||
prepareMachineInit();
|
||||
prepareMachineMatch();
|
||||
|
||||
prepareFactory();
|
||||
prepareFactoryInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finish() {
|
||||
setupFactoryInit();
|
||||
|
||||
setupMachineInit();
|
||||
setupMachineMatch();
|
||||
|
||||
setupClasses();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileAltNode(ConsAltNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
|
||||
String template = installTemplate(chars, p, strLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCClassNode(CClassNode node) {
|
||||
if (node.bs != null) {
|
||||
String bitsetName = installBitSet(node.bs.bits);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCTypeNode(CTypeNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileAnyCharNode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileBackrefNode(BackRefNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCallNode(CallNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileCECQuantifierNode(QuantifierNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileNonCECQuantifierNode(QuantifierNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileOptionNode(EncloseNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileEncloseNode(EncloseNode node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compileAnchorNode(AnchorNode node) {
|
||||
}
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
abstract class AsmCompilerSupport extends Compiler implements Opcodes, AsmConstants {
|
||||
protected ClassWriter factory; // matcher allocator, also bit set, code rage and string template container
|
||||
protected MethodVisitor factoryInit;// factory constructor
|
||||
protected String factoryName;
|
||||
|
||||
protected ClassWriter machine; // matcher
|
||||
protected MethodVisitor machineInit;// matcher constructor
|
||||
protected MethodVisitor match; // actual matcher implementation (the matchAt method)
|
||||
protected String machineName;
|
||||
|
||||
// we will? try to manage visitMaxs ourselves for efficiency
|
||||
protected int maxStack = 1;
|
||||
protected int maxVars = LAST_INDEX;
|
||||
|
||||
// for field generation
|
||||
protected int bitsets, ranges, templates;
|
||||
|
||||
// simple class name postfix scheme for now
|
||||
static int REG_NUM = 0;
|
||||
|
||||
// dummy class loader for now
|
||||
private static final class DummyClassLoader extends ClassLoader {
|
||||
public Class<?> defineClass(String name, byte[] bytes) {
|
||||
return super.defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
};
|
||||
|
||||
private static final DummyClassLoader loader = new DummyClassLoader();
|
||||
|
||||
AsmCompilerSupport(Analyser analyser) {
|
||||
super(analyser);
|
||||
}
|
||||
|
||||
protected final void prepareFactory() {
|
||||
factory = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
factoryName = "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory" + REG_NUM;
|
||||
|
||||
factory.visit(V1_4, ACC_PUBLIC + ACC_FINAL, factoryName, null, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", null);
|
||||
|
||||
MethodVisitor create = factory.visitMethod(ACC_SYNTHETIC, "create", "(Lorg/joni/Regex;[BII)Lorg/joni/Matcher;", null, null);
|
||||
create.visitTypeInsn(NEW, machineName);
|
||||
create.visitInsn(DUP); // instance
|
||||
create.visitVarInsn(ALOAD, 1); // Regex
|
||||
create.visitVarInsn(ALOAD, 2); // bytes[]
|
||||
create.visitVarInsn(ILOAD, 3); // p
|
||||
create.visitVarInsn(ILOAD, 4); // end
|
||||
create.visitMethodInsn(INVOKESPECIAL, machineName, "<init>", "(Lorg/joni/Regex;[BII)V");
|
||||
create.visitInsn(ARETURN);
|
||||
create.visitMaxs(0, 0);
|
||||
//create.visitMaxs(6, 5);
|
||||
create.visitEnd();
|
||||
}
|
||||
|
||||
protected final void prepareFactoryInit() {
|
||||
factoryInit = factory.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||
factoryInit.visitVarInsn(ALOAD, 0);
|
||||
factoryInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", "<init>", "()V");
|
||||
}
|
||||
|
||||
protected final void setupFactoryInit() {
|
||||
factoryInit.visitInsn(RETURN);
|
||||
factoryInit.visitMaxs(0, 0);
|
||||
//init.visitMaxs(1, 1);
|
||||
factoryInit.visitEnd();
|
||||
}
|
||||
|
||||
protected final void prepareMachine() {
|
||||
machine = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
machineName = "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine" + REG_NUM;
|
||||
}
|
||||
|
||||
protected final void prepareMachineInit() {
|
||||
machine.visit(V1_4, ACC_PUBLIC + ACC_FINAL, machineName, null, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", null);
|
||||
machineInit = machine.visitMethod(ACC_PROTECTED, "<init>", "(Lorg/joni/Regex;[BII)V", null, null);
|
||||
machineInit.visitVarInsn(ALOAD, THIS); // this
|
||||
machineInit.visitVarInsn(ALOAD, 1); // Regex
|
||||
machineInit.visitVarInsn(ALOAD, 2); // bytes[]
|
||||
machineInit.visitVarInsn(ILOAD, 3); // p
|
||||
machineInit.visitVarInsn(ILOAD, 4); // end
|
||||
machineInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", "<init>", "(Lorg/joni/Regex;[BII)V");
|
||||
}
|
||||
|
||||
protected final void setupMachineInit() {
|
||||
if (bitsets + ranges + templates > 0) { // ok, some of these are in use, we'd like to cache the factory
|
||||
machine.visitField(ACC_PRIVATE + ACC_FINAL, "factory", "L" + factoryName + ";", null, null);
|
||||
machineInit.visitVarInsn(ALOAD, THIS); // this
|
||||
machineInit.visitVarInsn(ALOAD, 1); // this, Regex
|
||||
machineInit.visitFieldInsn(GETFIELD, "jdk/nashorn/internal/runtime/regexp/joni/Regex", "factory", "Lorg/joni/MatcherFactory;"); // this, factory
|
||||
machineInit.visitTypeInsn(CHECKCAST, factoryName);
|
||||
machineInit.visitFieldInsn(PUTFIELD, machineName, "factory", "L" + factoryName + ";"); // []
|
||||
}
|
||||
|
||||
machineInit.visitInsn(RETURN);
|
||||
machineInit.visitMaxs(0, 0);
|
||||
//init.visitMaxs(5, 5);
|
||||
machineInit.visitEnd();
|
||||
}
|
||||
|
||||
protected final void prepareMachineMatch() {
|
||||
match = machine.visitMethod(ACC_SYNTHETIC, "matchAt", "(III)I", null, null);
|
||||
move(S, SSTART); // s = sstart
|
||||
load("bytes", "[B"); //
|
||||
astore(BYTES); // byte[]bytes = this.bytes
|
||||
}
|
||||
|
||||
protected final void setupMachineMatch() {
|
||||
match.visitInsn(ICONST_M1);
|
||||
match.visitInsn(IRETURN);
|
||||
|
||||
match.visitMaxs(maxStack, maxVars);
|
||||
match.visitEnd();
|
||||
}
|
||||
|
||||
protected final void setupClasses() {
|
||||
byte[]factoryCode = factory.toByteArray();
|
||||
byte[]machineCode = machine.toByteArray();
|
||||
|
||||
if (Config.DEBUG_ASM) {
|
||||
try {
|
||||
FileOutputStream fos;
|
||||
fos = new FileOutputStream(factoryName.substring(factoryName.lastIndexOf('/') + 1) + ".class");
|
||||
fos.write(factoryCode);
|
||||
fos.close();
|
||||
fos = new FileOutputStream(machineName.substring(machineName.lastIndexOf('/') + 1) + ".class");
|
||||
fos.write(machineCode);
|
||||
fos.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace(Config.err);
|
||||
}
|
||||
}
|
||||
|
||||
loader.defineClass(machineName.replace('/', '.'), machineCode);
|
||||
Class<?> cls = loader.defineClass(factoryName.replace('/', '.'), factoryCode);
|
||||
try {
|
||||
regex.factory = (MatcherFactory)cls.newInstance();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace(Config.err);
|
||||
}
|
||||
}
|
||||
|
||||
protected final void aload(int var) {
|
||||
match.visitVarInsn(ALOAD, var);
|
||||
}
|
||||
|
||||
protected final void astore(int var) {
|
||||
match.visitVarInsn(ASTORE, var);
|
||||
}
|
||||
|
||||
protected final void loadThis() {
|
||||
match.visitVarInsn(ALOAD, THIS);
|
||||
}
|
||||
|
||||
protected final void load(int var) {
|
||||
match.visitVarInsn(ILOAD, var);
|
||||
}
|
||||
|
||||
protected final void store(int var) {
|
||||
match.visitVarInsn(ISTORE, var);
|
||||
}
|
||||
|
||||
protected final void move(int to, int from) {
|
||||
load(from);
|
||||
store(to);
|
||||
}
|
||||
|
||||
protected final void load(String field, String singature) {
|
||||
loadThis();
|
||||
match.visitFieldInsn(GETFIELD, machineName, field, singature);
|
||||
}
|
||||
|
||||
protected final void load(String field) {
|
||||
load(field, "I");
|
||||
}
|
||||
|
||||
protected final void store(String field, String singature) {
|
||||
loadThis();
|
||||
match.visitFieldInsn(PUTFIELD, machineName, field, singature);
|
||||
}
|
||||
|
||||
protected final void store(String field) {
|
||||
store(field, "I");
|
||||
}
|
||||
|
||||
protected final String installTemplate(char[] arr, int p, int length) {
|
||||
String templateName = TEMPLATE + ++templates;
|
||||
installArray(templateName, arr, p, length);
|
||||
return templateName;
|
||||
}
|
||||
|
||||
protected final String installCodeRange(int[]arr) {
|
||||
String coreRangeName = CODERANGE + ++ranges;
|
||||
installArray(coreRangeName, arr);
|
||||
return coreRangeName;
|
||||
}
|
||||
|
||||
protected final String installBitSet(int[]arr) {
|
||||
String bitsetName = BITSET + ++bitsets;
|
||||
installArray(bitsetName, arr);
|
||||
return bitsetName;
|
||||
}
|
||||
|
||||
private void installArray(String name, int[]arr) {
|
||||
factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[I", null, null);
|
||||
factoryInit.visitVarInsn(ALOAD, THIS); // this;
|
||||
loadInt(factoryInit, arr.length); // this, length
|
||||
factoryInit.visitIntInsn(NEWARRAY, T_INT); // this, arr
|
||||
for (int i=0;i < arr.length; i++) buildArray(i, arr[i], IASTORE);
|
||||
factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[I");
|
||||
}
|
||||
|
||||
private void installArray(String name, char[]arr, int p, int length) {
|
||||
factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[B", null, null);
|
||||
factoryInit.visitVarInsn(ALOAD, THIS); // this;
|
||||
loadInt(factoryInit, arr.length); // this, length
|
||||
factoryInit.visitIntInsn(NEWARRAY, T_BYTE); // this, arr
|
||||
for (int i=p, j=0; i < p + length; i++, j++) buildArray(j, arr[i] & 0xff, BASTORE);
|
||||
factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[B");
|
||||
}
|
||||
|
||||
private void buildArray(int index, int value, int type) {
|
||||
factoryInit.visitInsn(DUP); // ... arr, arr
|
||||
loadInt(factoryInit, index); // ... arr, arr, index
|
||||
loadInt(factoryInit, value); // ... arr, arr, index, value
|
||||
factoryInit.visitInsn(type); // ... arr
|
||||
}
|
||||
|
||||
private void loadInt(MethodVisitor mv, int value) {
|
||||
if (value >= -1 && value <= 5) {
|
||||
mv.visitInsn(value + ICONST_0); // ICONST_0 == 3
|
||||
} else if (value >= 6 && value <= 127 || value >= -128 && value <= -2) {
|
||||
mv.visitIntInsn(BIPUSH, value);
|
||||
} else if (value >= 128 && value <= 32767 || value >= -32768 && value <= -129) {
|
||||
mv.visitIntInsn(SIPUSH, value);
|
||||
} else {
|
||||
mv.visitLdcInsn(new Integer(value));
|
||||
}
|
||||
}
|
||||
}
|
@ -51,10 +51,6 @@ public final class BitSet {
|
||||
bits[pos >>> ROOM_SHIFT] &= ~bit(pos);
|
||||
}
|
||||
|
||||
public void invert(int pos) {
|
||||
bits[pos >>> ROOM_SHIFT] ^= bit(pos);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (int i=0; i<BITSET_SIZE; i++) bits[i]=0;
|
||||
}
|
||||
@ -70,10 +66,6 @@ public final class BitSet {
|
||||
for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) set(i);
|
||||
}
|
||||
|
||||
public void setAll() {
|
||||
for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~0;
|
||||
}
|
||||
|
||||
public void invert() {
|
||||
for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~bits[i];
|
||||
}
|
||||
|
@ -25,12 +25,15 @@ final class BitStatus {
|
||||
public static int bsClear() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int bsAll() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static boolean bsAt(int stats, int n) {
|
||||
return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0;
|
||||
}
|
||||
|
||||
public static int bsOnAt(int stats, int n) {
|
||||
if (n < BIT_STATUS_BITS_NUM) {
|
||||
stats |= (1 << n);
|
||||
@ -39,10 +42,6 @@ final class BitStatus {
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
public static int bsOnAtSimple(int stats, int n) {
|
||||
if (n < BIT_STATUS_BITS_NUM) stats |= (1 << n);
|
||||
return stats;
|
||||
}
|
||||
|
||||
public static int bsOnOff(int v, int f, boolean negative) {
|
||||
if (negative) {
|
||||
|
@ -53,56 +53,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
this.code = regex.code;
|
||||
}
|
||||
|
||||
protected int stkp; // a temporary
|
||||
private boolean makeCaptureHistoryTree(CaptureTreeNode node) {
|
||||
//CaptureTreeNode child;
|
||||
int k = stkp;
|
||||
//int k = kp;
|
||||
|
||||
while (k < stk) {
|
||||
StackEntry e = stack[k];
|
||||
if (e.type == MEM_START) {
|
||||
int n = e.getMemNum();
|
||||
if (n <= Config.MAX_CAPTURE_HISTORY_GROUP && bsAt(regex.captureHistory, n)) {
|
||||
CaptureTreeNode child = new CaptureTreeNode();
|
||||
child.group = n;
|
||||
child.beg = e.getMemPStr() - str;
|
||||
node.addChild(child);
|
||||
stkp = k + 1;
|
||||
if (makeCaptureHistoryTree(child)) return true;
|
||||
|
||||
k = stkp;
|
||||
child.end = e.getMemPStr() - str;
|
||||
}
|
||||
} else if (e.type == MEM_END) {
|
||||
if (e.getMemNum() == node.group) {
|
||||
node.end = e.getMemPStr() - str;
|
||||
stkp = k;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; /* 1: root node ending. */
|
||||
}
|
||||
|
||||
private void checkCaptureHistory(Region region) {
|
||||
CaptureTreeNode node;
|
||||
if (region.historyRoot == null) {
|
||||
node = region.historyRoot = new CaptureTreeNode();
|
||||
} else {
|
||||
node = region.historyRoot;
|
||||
node.clear();
|
||||
}
|
||||
|
||||
// was clear ???
|
||||
node.group = 0;
|
||||
node.beg = sstart - str;
|
||||
node.end = s - str;
|
||||
|
||||
stkp = 0;
|
||||
makeCaptureHistoryTree(region.historyRoot);
|
||||
}
|
||||
|
||||
private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) {
|
||||
|
||||
int s2 = ps2.value;
|
||||
@ -175,13 +125,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
case OPCode.EXACT5: opExact5(); continue;
|
||||
case OPCode.EXACTN: opExactN(); continue;
|
||||
|
||||
case OPCode.EXACTMB2N1: opExactMB2N1(); break;
|
||||
case OPCode.EXACTMB2N2: opExactMB2N2(); continue;
|
||||
case OPCode.EXACTMB2N3: opExactMB2N3(); continue;
|
||||
case OPCode.EXACTMB2N: opExactMB2N(); continue;
|
||||
case OPCode.EXACTMB3N: opExactMB3N(); continue;
|
||||
case OPCode.EXACTMBN: opExactMBN(); continue;
|
||||
|
||||
case OPCode.EXACT1_IC: opExact1IC(); break;
|
||||
case OPCode.EXACTN_IC: opExactNIC(); continue;
|
||||
|
||||
@ -199,8 +142,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
case OPCode.ANYCHAR_ML_STAR: opAnyCharMLStar(); break;
|
||||
case OPCode.ANYCHAR_STAR_PEEK_NEXT: opAnyCharStarPeekNext(); break;
|
||||
case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT: opAnyCharMLStarPeekNext(); break;
|
||||
case OPCode.STATE_CHECK_ANYCHAR_STAR: opStateCheckAnyCharStar(); break;
|
||||
case OPCode.STATE_CHECK_ANYCHAR_ML_STAR:opStateCheckAnyCharMLStar();break;
|
||||
|
||||
case OPCode.WORD: opWord(); break;
|
||||
case OPCode.NOT_WORD: opNotWord(); break;
|
||||
@ -239,11 +180,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
case OPCode.JUMP: opJump(); continue;
|
||||
case OPCode.PUSH: opPush(); continue;
|
||||
|
||||
// CEC
|
||||
case OPCode.STATE_CHECK_PUSH: opStateCheckPush(); continue;
|
||||
case OPCode.STATE_CHECK_PUSH_OR_JUMP: opStateCheckPushOrJump(); continue;
|
||||
case OPCode.STATE_CHECK: opStateCheck(); continue;
|
||||
|
||||
case OPCode.POP: opPop(); continue;
|
||||
case OPCode.PUSH_OR_JUMP_EXACT1: opPushOrJumpExact1(); continue;
|
||||
case OPCode.PUSH_IF_PEEK_NEXT: opPushIfPeekNext(); continue;
|
||||
@ -266,10 +202,6 @@ 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.CALL: opCall(); continue;
|
||||
case OPCode.RETURN: opReturn(); continue;
|
||||
|
||||
case OPCode.FINISH:
|
||||
return finish();
|
||||
|
||||
@ -322,9 +254,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
|
||||
}
|
||||
|
||||
if (Config.USE_CAPTURE_HISTORY) {
|
||||
if (regex.captureHistory != 0) checkCaptureHistory(region);
|
||||
}
|
||||
} else {
|
||||
msaBegin = sstart - str;
|
||||
msaEnd = s - str;
|
||||
@ -437,125 +366,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
sprev = s - 1;
|
||||
}
|
||||
|
||||
private void opExactMB2N1() {
|
||||
if (s + 2 > range) {opFail(); return;}
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
sprev = sbegin; // break;
|
||||
}
|
||||
|
||||
private void opExactMB2N2() {
|
||||
if (s + 4 > range) {opFail(); return;}
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
sprev = s;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
}
|
||||
|
||||
private void opExactMB2N3() {
|
||||
if (s + 6 > range) {opFail(); return;}
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
sprev = s;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
}
|
||||
|
||||
private void opExactMB2N() {
|
||||
int tlen = code[ip++];
|
||||
if (s + tlen * 2 > range) {opFail(); return;}
|
||||
|
||||
if (Config.USE_STRING_TEMPLATES) {
|
||||
char[] bs = regex.templates[code[ip++]];
|
||||
int ps = code[ip++];
|
||||
|
||||
while(tlen-- > 0) {
|
||||
if (bs[ps] != chars[s]) {opFail(); return;}
|
||||
ps++; s++;
|
||||
if (bs[ps] != chars[s]) {opFail(); return;}
|
||||
ps++; s++;
|
||||
}
|
||||
} else {
|
||||
while(tlen-- > 0) {
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
}
|
||||
}
|
||||
sprev = s - 2;
|
||||
}
|
||||
|
||||
private void opExactMB3N() {
|
||||
int tlen = code[ip++];
|
||||
if (s + tlen * 3 > range) {opFail(); return;}
|
||||
|
||||
if (Config.USE_STRING_TEMPLATES) {
|
||||
char[] bs = regex.templates[code[ip++]];
|
||||
int ps = code[ip++];
|
||||
|
||||
while (tlen-- > 0) {
|
||||
if (bs[ps] != chars[s]) {opFail(); return;}
|
||||
ps++; s++;
|
||||
if (bs[ps] != chars[s]) {opFail(); return;}
|
||||
ps++; s++;
|
||||
if (bs[ps] != chars[s]) {opFail(); return;}
|
||||
ps++; s++;
|
||||
}
|
||||
} else {
|
||||
while (tlen-- > 0) {
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
}
|
||||
}
|
||||
|
||||
sprev = s - 3;
|
||||
}
|
||||
|
||||
private void opExactMBN() {
|
||||
int tlen = code[ip++]; /* mb-len */
|
||||
int tlen2= code[ip++]; /* string len */
|
||||
|
||||
tlen2 *= tlen;
|
||||
if (s + tlen2 > range) {opFail(); return;}
|
||||
|
||||
if (Config.USE_STRING_TEMPLATES) {
|
||||
char[] bs = regex.templates[code[ip++]];
|
||||
int ps = code[ip++];
|
||||
|
||||
while (tlen2-- > 0) {
|
||||
if (bs[ps] != chars[s]) {opFail(); return;}
|
||||
ps++; s++;
|
||||
}
|
||||
} else {
|
||||
while (tlen2-- > 0) {
|
||||
if (code[ip] != chars[s]) {opFail(); return;}
|
||||
ip++; s++;
|
||||
}
|
||||
}
|
||||
|
||||
sprev = s - tlen;
|
||||
}
|
||||
|
||||
private void opExact1IC() {
|
||||
if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;}
|
||||
ip++;
|
||||
@ -748,34 +558,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
sprev = sbegin; // break;
|
||||
}
|
||||
|
||||
// CEC
|
||||
private void opStateCheckAnyCharStar() {
|
||||
int mem = code[ip++];
|
||||
final char[] chars = this.chars;
|
||||
|
||||
while (s < range) {
|
||||
if (stateCheckVal(s, mem)) {opFail(); return;}
|
||||
pushAltWithStateCheck(ip, s, sprev, mem);
|
||||
if (chars[s] == EncodingHelper.NEW_LINE) {opFail(); return;}
|
||||
sprev = s;
|
||||
s++;
|
||||
}
|
||||
sprev = sbegin; // break;
|
||||
}
|
||||
|
||||
// CEC
|
||||
private void opStateCheckAnyCharMLStar() {
|
||||
int mem = code[ip++];
|
||||
|
||||
while (s < range) {
|
||||
if (stateCheckVal(s, mem)) {opFail(); return;}
|
||||
pushAltWithStateCheck(ip, s, sprev, mem);
|
||||
sprev = s;
|
||||
s++;
|
||||
}
|
||||
sprev = sbegin; // break;
|
||||
}
|
||||
|
||||
private void opWord() {
|
||||
if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;}
|
||||
s++;
|
||||
@ -1223,33 +1005,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
pushAlt(ip + addr, s, sprev);
|
||||
}
|
||||
|
||||
// CEC
|
||||
private void opStateCheckPush() {
|
||||
int mem = code[ip++];
|
||||
if (stateCheckVal(s, mem)) {opFail(); return;}
|
||||
int addr = code[ip++];
|
||||
pushAltWithStateCheck(ip + addr, s, sprev, mem);
|
||||
}
|
||||
|
||||
// CEC
|
||||
private void opStateCheckPushOrJump() {
|
||||
int mem = code[ip++];
|
||||
int addr= code[ip++];
|
||||
|
||||
if (stateCheckVal(s, mem)) {
|
||||
ip += addr;
|
||||
} else {
|
||||
pushAltWithStateCheck(ip + addr, s, sprev, mem);
|
||||
}
|
||||
}
|
||||
|
||||
// CEC
|
||||
private void opStateCheck() {
|
||||
int mem = code[ip++];
|
||||
if (stateCheckVal(s, mem)) {opFail(); return;}
|
||||
pushStateCheck(s, mem);
|
||||
}
|
||||
|
||||
private void opPop() {
|
||||
popOne();
|
||||
}
|
||||
@ -1425,17 +1180,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
opFail();
|
||||
}
|
||||
|
||||
private void opCall() {
|
||||
int addr = code[ip++];
|
||||
pushCallFrame(ip);
|
||||
ip = addr; // absolute address
|
||||
}
|
||||
|
||||
private void opReturn() {
|
||||
ip = sreturn();
|
||||
pushReturn();
|
||||
}
|
||||
|
||||
private void opFail() {
|
||||
if (stack == null) {
|
||||
ip = regex.codeLength - 1;
|
||||
@ -1447,13 +1191,6 @@ class ByteCodeMachine extends StackMachine {
|
||||
ip = e.getStatePCode();
|
||||
s = e.getStatePStr();
|
||||
sprev = e.getStatePStrPrev();
|
||||
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
if (e.getStateCheck() != 0) {
|
||||
e.type = STATE_CHECK_MARK;
|
||||
stk++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int finish() {
|
||||
|
@ -34,6 +34,239 @@ class ByteCodePrinter {
|
||||
int operantCount;
|
||||
WarnCallback warnings;
|
||||
|
||||
private final static String OpCodeNames[] = new String[] {
|
||||
"finish", /*OP_FINISH*/
|
||||
"end", /*OP_END*/
|
||||
"exact1", /*OP_EXACT1*/
|
||||
"exact2", /*OP_EXACT2*/
|
||||
"exact3", /*OP_EXACT3*/
|
||||
"exact4", /*OP_EXACT4*/
|
||||
"exact5", /*OP_EXACT5*/
|
||||
"exactn", /*OP_EXACTN*/
|
||||
"exactmb2-n1", /*OP_EXACTMB2N1*/
|
||||
"exactmb2-n2", /*OP_EXACTMB2N2*/
|
||||
"exactmb2-n3", /*OP_EXACTMB2N3*/
|
||||
"exactmb2-n", /*OP_EXACTMB2N*/
|
||||
"exactmb3n", /*OP_EXACTMB3N*/
|
||||
"exactmbn", /*OP_EXACTMBN*/
|
||||
"exact1-ic", /*OP_EXACT1_IC*/
|
||||
"exactn-ic", /*OP_EXACTN_IC*/
|
||||
"cclass", /*OP_CCLASS*/
|
||||
"cclass-mb", /*OP_CCLASS_MB*/
|
||||
"cclass-mix", /*OP_CCLASS_MIX*/
|
||||
"cclass-not", /*OP_CCLASS_NOT*/
|
||||
"cclass-mb-not", /*OP_CCLASS_MB_NOT*/
|
||||
"cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
|
||||
"cclass-node", /*OP_CCLASS_NODE*/
|
||||
"anychar", /*OP_ANYCHAR*/
|
||||
"anychar-ml", /*OP_ANYCHAR_ML*/
|
||||
"anychar*", /*OP_ANYCHAR_STAR*/
|
||||
"anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
|
||||
"anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
"anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
"word", /*OP_WORD*/
|
||||
"not-word", /*OP_NOT_WORD*/
|
||||
"word-bound", /*OP_WORD_BOUND*/
|
||||
"not-word-bound", /*OP_NOT_WORD_BOUND*/
|
||||
"word-begin", /*OP_WORD_BEGIN*/
|
||||
"word-end", /*OP_WORD_END*/
|
||||
"begin-buf", /*OP_BEGIN_BUF*/
|
||||
"end-buf", /*OP_END_BUF*/
|
||||
"begin-line", /*OP_BEGIN_LINE*/
|
||||
"end-line", /*OP_END_LINE*/
|
||||
"semi-end-buf", /*OP_SEMI_END_BUF*/
|
||||
"begin-position", /*OP_BEGIN_POSITION*/
|
||||
"backref1", /*OP_BACKREF1*/
|
||||
"backref2", /*OP_BACKREF2*/
|
||||
"backrefn", /*OP_BACKREFN*/
|
||||
"backrefn-ic", /*OP_BACKREFN_IC*/
|
||||
"backref_multi", /*OP_BACKREF_MULTI*/
|
||||
"backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
|
||||
"backref_at_level", /*OP_BACKREF_AT_LEVEL*/
|
||||
"mem-start", /*OP_MEMORY_START*/
|
||||
"mem-start-push", /*OP_MEMORY_START_PUSH*/
|
||||
"mem-end-push", /*OP_MEMORY_END_PUSH*/
|
||||
"mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
|
||||
"mem-end", /*OP_MEMORY_END*/
|
||||
"mem-end-rec", /*OP_MEMORY_END_REC*/
|
||||
"fail", /*OP_FAIL*/
|
||||
"jump", /*OP_JUMP*/
|
||||
"push", /*OP_PUSH*/
|
||||
"pop", /*OP_POP*/
|
||||
"push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
|
||||
"push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
|
||||
"repeat", /*OP_REPEAT*/
|
||||
"repeat-ng", /*OP_REPEAT_NG*/
|
||||
"repeat-inc", /*OP_REPEAT_INC*/
|
||||
"repeat-inc-ng", /*OP_REPEAT_INC_NG*/
|
||||
"repeat-inc-sg", /*OP_REPEAT_INC_SG*/
|
||||
"repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
|
||||
"null-check-start", /*OP_NULL_CHECK_START*/
|
||||
"null-check-end", /*OP_NULL_CHECK_END*/
|
||||
"null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
|
||||
"null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
|
||||
"push-pos", /*OP_PUSH_POS*/
|
||||
"pop-pos", /*OP_POP_POS*/
|
||||
"push-pos-not", /*OP_PUSH_POS_NOT*/
|
||||
"fail-pos", /*OP_FAIL_POS*/
|
||||
"push-stop-bt", /*OP_PUSH_STOP_BT*/
|
||||
"pop-stop-bt", /*OP_POP_STOP_BT*/
|
||||
"look-behind", /*OP_LOOK_BEHIND*/
|
||||
"push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
|
||||
"fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
|
||||
"call", /*OP_CALL*/
|
||||
"return", /*OP_RETURN*/
|
||||
"state-check-push", /*OP_STATE_CHECK_PUSH*/
|
||||
"state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
|
||||
"state-check", /*OP_STATE_CHECK*/
|
||||
"state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
"state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
"set-option-push", /*OP_SET_OPTION_PUSH*/
|
||||
"set-option", /*OP_SET_OPTION*/
|
||||
|
||||
// single byte versions
|
||||
"anychar-sb", /*OP_ANYCHAR*/
|
||||
"anychar-ml-sb", /*OP_ANYCHAR_ML*/
|
||||
"anychar*-sb", /*OP_ANYCHAR_STAR*/
|
||||
"anychar-ml*-sb", /*OP_ANYCHAR_ML_STAR*/
|
||||
"anychar*-peek-next-sb", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
"anychar-ml*-peek-next-sb", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
"state-check-anychar*-sb", /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
"state-check-anychar-ml*-sb", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
|
||||
"cclass-sb", /*OP_CCLASS*/
|
||||
"cclass-not-sb", /*OP_CCLASS_NOT*/
|
||||
|
||||
"word-sb", /*OP_WORD*/
|
||||
"not-word-sb", /*OP_NOT_WORD*/
|
||||
"word-bound-sb", /*OP_WORD_BOUND*/
|
||||
"not-word-bound-sb", /*OP_NOT_WORD_BOUND*/
|
||||
"word-begin-sb", /*OP_WORD_BEGIN*/
|
||||
"word-end-sb", /*OP_WORD_END*/
|
||||
|
||||
"look-behind-sb", /*OP_LOOK_BEHIND*/
|
||||
|
||||
"exact1-ic-sb", /*OP_EXACT1_IC*/
|
||||
"exactn-ic-sb", /*OP_EXACTN_IC*/
|
||||
|
||||
};
|
||||
|
||||
private final static int OpCodeArgTypes[] = new int[] {
|
||||
Arguments.NON, /*OP_FINISH*/
|
||||
Arguments.NON, /*OP_END*/
|
||||
Arguments.SPECIAL, /*OP_EXACT1*/
|
||||
Arguments.SPECIAL, /*OP_EXACT2*/
|
||||
Arguments.SPECIAL, /*OP_EXACT3*/
|
||||
Arguments.SPECIAL, /*OP_EXACT4*/
|
||||
Arguments.SPECIAL, /*OP_EXACT5*/
|
||||
Arguments.SPECIAL, /*OP_EXACTN*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N1*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N2*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N3*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB3N*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMBN*/
|
||||
Arguments.SPECIAL, /*OP_EXACT1_IC*/
|
||||
Arguments.SPECIAL, /*OP_EXACTN_IC*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MB*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MIX*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_NOT*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_NODE*/
|
||||
Arguments.NON, /*OP_ANYCHAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML*/
|
||||
Arguments.NON, /*OP_ANYCHAR_STAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
Arguments.NON, /*OP_WORD*/
|
||||
Arguments.NON, /*OP_NOT_WORD*/
|
||||
Arguments.NON, /*OP_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_NOT_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_WORD_BEGIN*/
|
||||
Arguments.NON, /*OP_WORD_END*/
|
||||
Arguments.NON, /*OP_BEGIN_BUF*/
|
||||
Arguments.NON, /*OP_END_BUF*/
|
||||
Arguments.NON, /*OP_BEGIN_LINE*/
|
||||
Arguments.NON, /*OP_END_LINE*/
|
||||
Arguments.NON, /*OP_SEMI_END_BUF*/
|
||||
Arguments.NON, /*OP_BEGIN_POSITION*/
|
||||
Arguments.NON, /*OP_BACKREF1*/
|
||||
Arguments.NON, /*OP_BACKREF2*/
|
||||
Arguments.MEMNUM, /*OP_BACKREFN*/
|
||||
Arguments.SPECIAL, /*OP_BACKREFN_IC*/
|
||||
Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
|
||||
Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
|
||||
Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_START*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
|
||||
Arguments.NON, /*OP_FAIL*/
|
||||
Arguments.RELADDR, /*OP_JUMP*/
|
||||
Arguments.RELADDR, /*OP_PUSH*/
|
||||
Arguments.NON, /*OP_POP*/
|
||||
Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
|
||||
Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
|
||||
Arguments.SPECIAL, /*OP_REPEAT*/
|
||||
Arguments.SPECIAL, /*OP_REPEAT_NG*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
|
||||
Arguments.NON, /*OP_PUSH_POS*/
|
||||
Arguments.NON, /*OP_POP_POS*/
|
||||
Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
|
||||
Arguments.NON, /*OP_FAIL_POS*/
|
||||
Arguments.NON, /*OP_PUSH_STOP_BT*/
|
||||
Arguments.NON, /*OP_POP_STOP_BT*/
|
||||
Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
|
||||
Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
|
||||
Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
|
||||
Arguments.ABSADDR, /*OP_CALL*/
|
||||
Arguments.NON, /*OP_RETURN*/
|
||||
Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
|
||||
Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
|
||||
Arguments.OPTION, /*OP_SET_OPTION*/
|
||||
|
||||
// single byte versions
|
||||
Arguments.NON, /*OP_ANYCHAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML*/
|
||||
Arguments.NON, /*OP_ANYCHAR_STAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
|
||||
Arguments.SPECIAL, /*OP_CCLASS*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_NOT*/
|
||||
|
||||
Arguments.NON, /*OP_WORD*/
|
||||
Arguments.NON, /*OP_NOT_WORD*/
|
||||
Arguments.NON, /*OP_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_NOT_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_WORD_BEGIN*/
|
||||
Arguments.NON, /*OP_WORD_END*/
|
||||
|
||||
Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
|
||||
|
||||
Arguments.SPECIAL, /*OP_EXACT1_IC*/
|
||||
Arguments.SPECIAL, /*OP_EXACTN_IC*/
|
||||
};
|
||||
|
||||
public ByteCodePrinter(Regex regex) {
|
||||
code = regex.code;
|
||||
codeLength = regex.codeLength;
|
||||
@ -76,8 +309,8 @@ class ByteCodePrinter {
|
||||
CClassNode cc;
|
||||
int tm, idx;
|
||||
|
||||
sb.append("[" + OPCode.OpCodeNames[code[bp]]);
|
||||
int argType = OPCode.OpCodeArgTypes[code[bp]];
|
||||
sb.append("[" + OpCodeNames[code[bp]]);
|
||||
int argType = OpCodeArgTypes[code[bp]];
|
||||
int ip = bp;
|
||||
if (argType != Arguments.SPECIAL) {
|
||||
bp++;
|
||||
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
public class CaptureTreeNode {
|
||||
|
||||
|
||||
int group;
|
||||
int beg;
|
||||
int end;
|
||||
// int allocated;
|
||||
int numChildren;
|
||||
CaptureTreeNode[]children;
|
||||
|
||||
CaptureTreeNode() {
|
||||
beg = Region.REGION_NOTPOS;
|
||||
end = Region.REGION_NOTPOS;
|
||||
group = -1;
|
||||
}
|
||||
|
||||
static final int HISTORY_TREE_INIT_ALLOC_SIZE = 8;
|
||||
void addChild(CaptureTreeNode child) {
|
||||
if (children == null) {
|
||||
children = new CaptureTreeNode[HISTORY_TREE_INIT_ALLOC_SIZE];
|
||||
} else if (numChildren >= children.length) {
|
||||
CaptureTreeNode[]tmp = new CaptureTreeNode[children.length << 1];
|
||||
System.arraycopy(children, 0, tmp, 0, children.length);
|
||||
children = tmp;
|
||||
}
|
||||
|
||||
children[numChildren] = child;
|
||||
numChildren++;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (int i=0; i<numChildren; i++) {
|
||||
children[i] = null; // ???
|
||||
}
|
||||
numChildren = 0;
|
||||
beg = end = Region.REGION_NOTPOS;
|
||||
group = -1;
|
||||
}
|
||||
|
||||
CaptureTreeNode cloneTree() {
|
||||
CaptureTreeNode clone = new CaptureTreeNode();
|
||||
clone.beg = beg;
|
||||
clone.end = end;
|
||||
|
||||
for (int i=0; i<numChildren; i++) {
|
||||
CaptureTreeNode child = children[i].cloneTree();
|
||||
clone.addChild(child);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -22,8 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
|
||||
@ -56,7 +54,7 @@ abstract class Compiler implements ErrorMessages {
|
||||
|
||||
private void compileStringRawNode(StringNode sn) {
|
||||
if (sn.length() <= 0) return;
|
||||
addCompileString(sn.chars, sn.p, 1 /*sb*/, sn.length(), false);
|
||||
addCompileString(sn.chars, sn.p, sn.length(), false);
|
||||
}
|
||||
|
||||
private void compileStringNode(StringNode node) {
|
||||
@ -76,17 +74,14 @@ abstract class Compiler implements ErrorMessages {
|
||||
slen++;
|
||||
p++;
|
||||
}
|
||||
addCompileString(chars, prev, 1, slen, ambig);
|
||||
addCompileString(chars, prev, slen, ambig);
|
||||
}
|
||||
|
||||
protected abstract void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase);
|
||||
protected abstract void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase);
|
||||
|
||||
protected abstract void compileCClassNode(CClassNode node);
|
||||
protected abstract void compileCTypeNode(CTypeNode node);
|
||||
protected abstract void compileAnyCharNode();
|
||||
protected abstract void compileCallNode(CallNode node);
|
||||
protected abstract void compileBackrefNode(BackRefNode node);
|
||||
protected abstract void compileCECQuantifierNode(QuantifierNode node);
|
||||
protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
|
||||
protected abstract void compileOptionNode(EncloseNode node);
|
||||
protected abstract void compileEncloseNode(EncloseNode node);
|
||||
@ -118,10 +113,6 @@ abstract class Compiler implements ErrorMessages {
|
||||
compileCClassNode((CClassNode)node);
|
||||
break;
|
||||
|
||||
case NodeType.CTYPE:
|
||||
compileCTypeNode((CTypeNode)node);
|
||||
break;
|
||||
|
||||
case NodeType.CANY:
|
||||
compileAnyCharNode();
|
||||
break;
|
||||
@ -130,19 +121,8 @@ abstract class Compiler implements ErrorMessages {
|
||||
compileBackrefNode((BackRefNode)node);
|
||||
break;
|
||||
|
||||
case NodeType.CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
compileCallNode((CallNode)node);
|
||||
break;
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case NodeType.QTFR:
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
compileCECQuantifierNode((QuantifierNode)node);
|
||||
} else {
|
||||
compileNonCECQuantifierNode((QuantifierNode)node);
|
||||
}
|
||||
compileNonCECQuantifierNode((QuantifierNode)node);
|
||||
break;
|
||||
|
||||
case NodeType.ENCLOSE:
|
||||
|
@ -31,10 +31,6 @@ public interface Config {
|
||||
final int ENC_CASE_FOLD_DEFAULT = ENC_CASE_FOLD_MIN;
|
||||
final boolean USE_CRNL_AS_LINE_TERMINATOR = false;
|
||||
|
||||
final boolean USE_NAMED_GROUP = true;
|
||||
final boolean USE_SUBEXP_CALL = true;
|
||||
final boolean USE_BACKREF_WITH_LEVEL = true; /* \k<name+n>, \k<name-n> */
|
||||
|
||||
final boolean USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT = true; /* /(?:()|())*\2/ */
|
||||
final boolean USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE = true; /* /\n$/ =~ "\n" */
|
||||
final boolean USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR = false;
|
||||
@ -42,12 +38,10 @@ public interface Config {
|
||||
final boolean CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS = true;
|
||||
|
||||
final boolean USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE = false;
|
||||
final boolean USE_CAPTURE_HISTORY = false;
|
||||
final boolean USE_VARIABLE_META_CHARS = true;
|
||||
final boolean USE_WORD_BEGIN_END = true; /* "\<": word-begin, "\>": word-end */
|
||||
final boolean USE_POSIX_API_REGION_OPTION = true; /* needed for POSIX API support */
|
||||
final boolean USE_POSIX_API_REGION_OPTION = false; /* needed for POSIX API support */
|
||||
final boolean USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE = true;
|
||||
final boolean USE_COMBINATION_EXPLOSION_CHECK = false;
|
||||
|
||||
final int NREGION = 10;
|
||||
final int MAX_BACKREF_NUM = 1000;
|
||||
@ -73,13 +67,6 @@ public interface Config {
|
||||
|
||||
final boolean USE_STRING_TEMPLATES = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
|
||||
|
||||
|
||||
final int MAX_CAPTURE_HISTORY_GROUP = 31;
|
||||
|
||||
|
||||
final int CHECK_STRING_THRESHOLD_LEN = 7;
|
||||
final int CHECK_BUFF_MAX_SIZE = 0x4000;
|
||||
|
||||
final boolean NON_UNICODE_SDW = true;
|
||||
|
||||
|
||||
@ -95,6 +82,4 @@ public interface Config {
|
||||
final boolean DEBUG_COMPILE_BYTE_CODE_INFO = DEBUG_ALL;
|
||||
final boolean DEBUG_SEARCH = DEBUG_ALL;
|
||||
final boolean DEBUG_MATCH = DEBUG_ALL;
|
||||
final boolean DEBUG_ASM = true;
|
||||
final boolean DEBUG_ASM_EXEC = true;
|
||||
}
|
||||
|
@ -95,20 +95,6 @@ public class EncodingHelper {
|
||||
return s;
|
||||
}
|
||||
|
||||
/* onigenc_with_ascii_strncmp */
|
||||
public static int strNCmp(char[] chars1, int p1, int end, char[] chars2, int p2, int n) {
|
||||
while (n-- > 0) {
|
||||
if (p1 >= end) return chars2[p2];
|
||||
int c = chars1[p1];
|
||||
int x = chars2[p2] - c;
|
||||
if (x != 0) return x;
|
||||
|
||||
p2++;
|
||||
p1++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int mbcToCode(byte[] bytes, int p, int end) {
|
||||
int code = 0;
|
||||
for (int i = p; i < end; i++) {
|
||||
|
@ -27,10 +27,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.TokenType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
|
||||
|
||||
class Lexer extends ScannerSupport {
|
||||
protected final ScanEnvironment env;
|
||||
@ -215,198 +212,6 @@ class Lexer extends ScannerSupport {
|
||||
\k<-num+n>, \k<-num-n>
|
||||
*/
|
||||
|
||||
// value implicit (rnameEnd)
|
||||
private boolean fetchNameWithLevel(int startCode, Ptr rbackNum, Ptr rlevel) {
|
||||
int src = p;
|
||||
boolean existLevel = false;
|
||||
int isNum = 0;
|
||||
int sign = 1;
|
||||
|
||||
int endCode = nameEndCodePoint(startCode);
|
||||
int pnumHead = p;
|
||||
int nameEnd = stop;
|
||||
|
||||
String err = null;
|
||||
if (!left()) {
|
||||
newValueException(ERR_EMPTY_GROUP_NAME);
|
||||
} else {
|
||||
fetch();
|
||||
if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
|
||||
if (Character.isDigit(c)) {
|
||||
isNum = 1;
|
||||
} else if (c == '-') {
|
||||
isNum = 2;
|
||||
sign = -1;
|
||||
pnumHead = p;
|
||||
} else if (!EncodingHelper.isWord(c)) {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
while (left()) {
|
||||
nameEnd = p;
|
||||
fetch();
|
||||
if (c == endCode || c == ')' || c == '+' || c == '-') {
|
||||
if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isNum != 0) {
|
||||
if (EncodingHelper.isDigit(c)) {
|
||||
isNum = 1;
|
||||
} else {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
// isNum = 0;
|
||||
}
|
||||
} else if (!EncodingHelper.isWord(c)) {
|
||||
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isEndCode = false;
|
||||
if (err == null && c != endCode) {
|
||||
if (c == '+' || c == '-') {
|
||||
int flag = c == '-' ? -1 : 1;
|
||||
|
||||
fetch();
|
||||
if (!EncodingHelper.isDigit(c)) newValueException(ERR_INVALID_GROUP_NAME, src, stop);
|
||||
unfetch();
|
||||
int level = scanUnsignedNumber();
|
||||
if (level < 0) newValueException(ERR_TOO_BIG_NUMBER);
|
||||
rlevel.p = level * flag;
|
||||
existLevel = true;
|
||||
|
||||
fetch();
|
||||
isEndCode = c == endCode;
|
||||
}
|
||||
|
||||
if (!isEndCode) {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
nameEnd = stop;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == null) {
|
||||
if (isNum != 0) {
|
||||
mark();
|
||||
p = pnumHead;
|
||||
int backNum = scanUnsignedNumber();
|
||||
restore();
|
||||
if (backNum < 0) {
|
||||
newValueException(ERR_TOO_BIG_NUMBER);
|
||||
} else if (backNum == 0) {
|
||||
newValueException(ERR_INVALID_GROUP_NAME, src, stop);
|
||||
}
|
||||
rbackNum.p = backNum * sign;
|
||||
}
|
||||
value = nameEnd;
|
||||
return existLevel;
|
||||
} else {
|
||||
newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
|
||||
return false; // not reached
|
||||
}
|
||||
}
|
||||
|
||||
// USE_NAMED_GROUP
|
||||
// ref: 0 -> define name (don't allow number name)
|
||||
// 1 -> reference name (allow number name)
|
||||
private int fetchNameForNamedGroup(int startCode, boolean ref) {
|
||||
int src = p;
|
||||
value = 0;
|
||||
|
||||
int isNum = 0;
|
||||
int sign = 1;
|
||||
|
||||
int endCode = nameEndCodePoint(startCode);
|
||||
int pnumHead = p;
|
||||
int nameEnd = stop;
|
||||
|
||||
String err = null;
|
||||
if (!left()) {
|
||||
newValueException(ERR_EMPTY_GROUP_NAME);
|
||||
} else {
|
||||
fetch();
|
||||
if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
|
||||
if (EncodingHelper.isDigit(c)) {
|
||||
if (ref) {
|
||||
isNum = 1;
|
||||
} else {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
// isNum = 0;
|
||||
}
|
||||
} else if (c == '-') {
|
||||
if (ref) {
|
||||
isNum = 2;
|
||||
sign = -1;
|
||||
pnumHead = p;
|
||||
} else {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
// isNum = 0;
|
||||
}
|
||||
} else if (!EncodingHelper.isWord(c)) {
|
||||
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == null) {
|
||||
while (left()) {
|
||||
nameEnd = p;
|
||||
fetch();
|
||||
if (c == endCode || c == ')') {
|
||||
if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isNum != 0) {
|
||||
if (EncodingHelper.isDigit(c)) {
|
||||
isNum = 1;
|
||||
} else {
|
||||
if (!EncodingHelper.isWord(c)) {
|
||||
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
|
||||
} else {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
}
|
||||
// isNum = 0;
|
||||
}
|
||||
} else {
|
||||
if (!EncodingHelper.isWord(c)) {
|
||||
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c != endCode) {
|
||||
err = ERR_INVALID_GROUP_NAME;
|
||||
nameEnd = stop;
|
||||
}
|
||||
|
||||
int backNum = 0;
|
||||
if (isNum != 0) {
|
||||
mark();
|
||||
p = pnumHead;
|
||||
backNum = scanUnsignedNumber();
|
||||
restore();
|
||||
if (backNum < 0) {
|
||||
newValueException(ERR_TOO_BIG_NUMBER);
|
||||
} else if (backNum == 0) {
|
||||
newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
|
||||
}
|
||||
backNum *= sign;
|
||||
}
|
||||
value = nameEnd;
|
||||
return backNum;
|
||||
} else {
|
||||
while (left()) {
|
||||
nameEnd = p;
|
||||
fetch();
|
||||
if (c == endCode || c == ')') break;
|
||||
}
|
||||
if (!left()) nameEnd = stop;
|
||||
newValueException(err, src, nameEnd);
|
||||
return 0; // not reached
|
||||
}
|
||||
}
|
||||
|
||||
// #else USE_NAMED_GROUP
|
||||
// make it return nameEnd!
|
||||
private final int fetchNameForNoNamedGroup(int startCode, boolean ref) {
|
||||
@ -472,11 +277,7 @@ class Lexer extends ScannerSupport {
|
||||
}
|
||||
|
||||
protected final int fetchName(int startCode, boolean ref) {
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
return fetchNameForNamedGroup(startCode, ref);
|
||||
} else {
|
||||
return fetchNameForNoNamedGroup(startCode, ref);
|
||||
}
|
||||
return fetchNameForNoNamedGroup(startCode, ref);
|
||||
}
|
||||
|
||||
private boolean strExistCheckWithEsc(int[]s, int n, int bad) {
|
||||
@ -519,26 +320,6 @@ class Lexer extends ScannerSupport {
|
||||
token.setPropNot(flag);
|
||||
}
|
||||
|
||||
private void fetchTokenInCCFor_p() {
|
||||
int c2 = peek(); // !!! migrate to peekIs
|
||||
if (c2 == '{' && syntax.op2EscPBraceCharProperty()) {
|
||||
inc();
|
||||
token.type = TokenType.CHAR_PROPERTY;
|
||||
token.setPropNot(c == 'P');
|
||||
|
||||
if (syntax.op2EscPBraceCircumflexNot()) {
|
||||
c2 = fetchTo();
|
||||
if (c2 == '^') {
|
||||
token.setPropNot(!token.getPropNot());
|
||||
} else {
|
||||
unfetch();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenInCCFor_x() {
|
||||
if (!left()) return;
|
||||
int last = p;
|
||||
@ -604,30 +385,6 @@ class Lexer extends ScannerSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenInCCFor_posixBracket() {
|
||||
if (syntax.opPosixBracket() && peekIs(':')) {
|
||||
token.backP = p; /* point at '[' is readed */
|
||||
inc();
|
||||
if (strExistCheckWithEsc(send, send.length, ']')) {
|
||||
token.type = TokenType.POSIX_BRACKET_OPEN;
|
||||
} else {
|
||||
unfetch();
|
||||
// remove duplication, goto cc_in_cc;
|
||||
if (syntax.op2CClassSetOp()) {
|
||||
token.type = TokenType.CC_CC_OPEN;
|
||||
} else {
|
||||
env.ccEscWarn("[");
|
||||
}
|
||||
}
|
||||
} else { // cc_in_cc:
|
||||
if (syntax.op2CClassSetOp()) {
|
||||
token.type = TokenType.CC_CC_OPEN;
|
||||
} else {
|
||||
env.ccEscWarn("[");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenInCCFor_and() {
|
||||
if (syntax.op2CClassSetOp() && left() && peekIs('&')) {
|
||||
inc();
|
||||
@ -683,10 +440,6 @@ class Lexer extends ScannerSupport {
|
||||
case 'H':
|
||||
if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
fetchTokenInCCFor_p();
|
||||
break;
|
||||
case 'x':
|
||||
fetchTokenInCCFor_x();
|
||||
break;
|
||||
@ -714,18 +467,12 @@ class Lexer extends ScannerSupport {
|
||||
break;
|
||||
} // switch
|
||||
|
||||
} else if (c == '[') {
|
||||
fetchTokenInCCFor_posixBracket();
|
||||
} else if (c == '&') {
|
||||
fetchTokenInCCFor_and();
|
||||
}
|
||||
return token.type;
|
||||
}
|
||||
|
||||
protected final int backrefRelToAbs(int relNo) {
|
||||
return env.numMem + 1 + relNo;
|
||||
}
|
||||
|
||||
private void fetchTokenFor_repeat(int lower, int upper) {
|
||||
token.type = TokenType.OP_REPEAT;
|
||||
token.setRepeatLower(lower);
|
||||
@ -815,7 +562,6 @@ class Lexer extends ScannerSupport {
|
||||
token.setBackrefNum(1);
|
||||
token.setBackrefRef1(num);
|
||||
token.setBackrefByName(false);
|
||||
if (Config.USE_BACKREF_WITH_LEVEL) token.setBackrefExistLevel(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -845,76 +591,6 @@ class Lexer extends ScannerSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenFor_namedBackref() {
|
||||
if (syntax.op2EscKNamedBackref()) {
|
||||
if (left()) {
|
||||
fetch();
|
||||
if (c =='<' || c == '\'') {
|
||||
int last = p;
|
||||
int backNum;
|
||||
if (Config.USE_BACKREF_WITH_LEVEL) {
|
||||
Ptr rbackNum = new Ptr();
|
||||
Ptr rlevel = new Ptr();
|
||||
token.setBackrefExistLevel(fetchNameWithLevel(c, rbackNum, rlevel));
|
||||
token.setBackrefLevel(rlevel.p);
|
||||
backNum = rbackNum.p;
|
||||
} else {
|
||||
backNum = fetchName(c, true);
|
||||
} // USE_BACKREF_AT_LEVEL
|
||||
int nameEnd = value; // set by fetchNameWithLevel/fetchName
|
||||
|
||||
if (backNum != 0) {
|
||||
if (backNum < 0) {
|
||||
backNum = backrefRelToAbs(backNum);
|
||||
if (backNum <= 0) newValueException(ERR_INVALID_BACKREF);
|
||||
}
|
||||
|
||||
if (syntax.strictCheckBackref() && (backNum > env.numMem || env.memNodes == null)) {
|
||||
newValueException(ERR_INVALID_BACKREF);
|
||||
}
|
||||
token.type = TokenType.BACKREF;
|
||||
token.setBackrefByName(false);
|
||||
token.setBackrefNum(1);
|
||||
token.setBackrefRef1(backNum);
|
||||
} else {
|
||||
NameEntry e = env.reg.nameToGroupNumbers(chars, last, nameEnd);
|
||||
if (e == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, last, nameEnd);
|
||||
|
||||
if (syntax.strictCheckBackref()) {
|
||||
if (e.backNum == 1) {
|
||||
if (e.backRef1 > env.numMem ||
|
||||
env.memNodes == null ||
|
||||
env.memNodes[e.backRef1] == null) newValueException(ERR_INVALID_BACKREF);
|
||||
} else {
|
||||
for (int i=0; i<e.backNum; i++) {
|
||||
if (e.backRefs[i] > env.numMem ||
|
||||
env.memNodes == null ||
|
||||
env.memNodes[e.backRefs[i]] == null) newValueException(ERR_INVALID_BACKREF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
token.type = TokenType.BACKREF;
|
||||
token.setBackrefByName(true);
|
||||
|
||||
if (e.backNum == 1) {
|
||||
token.setBackrefNum(1);
|
||||
token.setBackrefRef1(e.backRef1);
|
||||
} else {
|
||||
token.setBackrefNum(e.backNum);
|
||||
token.setBackrefRefs(e.backRefs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unfetch();
|
||||
syntaxWarn(Warnings.INVALID_BACKREFERENCE);
|
||||
}
|
||||
} else {
|
||||
syntaxWarn(Warnings.INVALID_BACKREFERENCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenFor_subexpCall() {
|
||||
if (syntax.op2EscGSubexpCall()) {
|
||||
if (left()) {
|
||||
@ -937,25 +613,6 @@ class Lexer extends ScannerSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenFor_charProperty() {
|
||||
if (peekIs('{') && syntax.op2EscPBraceCharProperty()) {
|
||||
inc();
|
||||
token.type = TokenType.CHAR_PROPERTY;
|
||||
token.setPropNot(c == 'P');
|
||||
|
||||
if (syntax.op2EscPBraceCircumflexNot()) {
|
||||
fetch();
|
||||
if (c == '^') {
|
||||
token.setPropNot(!token.getPropNot());
|
||||
} else {
|
||||
unfetch();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTokenFor_metaChars() {
|
||||
if (c == syntax.metaCharTable.anyChar) {
|
||||
token.type = TokenType.ANYCHAR;
|
||||
@ -1091,19 +748,6 @@ class Lexer extends ScannerSupport {
|
||||
case '0':
|
||||
fetchTokenFor_zero();
|
||||
break;
|
||||
case 'k':
|
||||
if (Config.USE_NAMED_GROUP) fetchTokenFor_namedBackref();
|
||||
break;
|
||||
case 'g':
|
||||
if (Config.USE_SUBEXP_CALL) fetchTokenFor_subexpCall();
|
||||
break;
|
||||
case 'Q':
|
||||
if (syntax.op2EscCapitalQQuote()) token.type = TokenType.QUOTE_OPEN;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
fetchTokenFor_charProperty();
|
||||
break;
|
||||
|
||||
default:
|
||||
unfetch();
|
||||
@ -1244,24 +888,6 @@ class Lexer extends ScannerSupport {
|
||||
}
|
||||
}
|
||||
|
||||
protected final int fetchCharPropertyToCType() {
|
||||
mark();
|
||||
|
||||
while (left()) {
|
||||
int last = p;
|
||||
fetch();
|
||||
if (c == '}') {
|
||||
String name = new String(chars, _p, last - _p);
|
||||
return PosixBracket.propertyNameToCType(name);
|
||||
} else if (c == '(' || c == ')' || c == '{' || c == '|') {
|
||||
String name = new String(chars, _p, last - _p);
|
||||
throw new JOniException(ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
|
||||
}
|
||||
}
|
||||
newInternalException(ERR_PARSER_BUG);
|
||||
return 0; // not reached
|
||||
}
|
||||
|
||||
protected final void syntaxWarn(String message, char c) {
|
||||
syntaxWarn(message.replace("<%n>", Character.toString(c)));
|
||||
}
|
||||
|
@ -58,17 +58,10 @@ public abstract class Matcher extends IntHolder {
|
||||
// main matching method
|
||||
protected abstract int matchAt(int range, int sstart, int sprev);
|
||||
|
||||
protected abstract void stateCheckBuffInit(int strLength, int offset, int stateNum);
|
||||
protected abstract void stateCheckBuffClear();
|
||||
|
||||
public final Region getRegion() {
|
||||
return msaRegion;
|
||||
}
|
||||
|
||||
public final Region getEagerRegion() {
|
||||
return msaRegion != null ? msaRegion : new Region(msaBegin, msaEnd);
|
||||
}
|
||||
|
||||
public final int getBegin() {
|
||||
return msaBegin;
|
||||
}
|
||||
@ -86,11 +79,6 @@ public abstract class Matcher extends IntHolder {
|
||||
public final int match(int at, int range, int option) {
|
||||
msaInit(option, at);
|
||||
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
int offset = at = str;
|
||||
stateCheckBuffInit(end - str, offset, regex.numCombExpCheck); // move it to construction?
|
||||
} // USE_COMBINATION_EXPLOSION_CHECK
|
||||
|
||||
int prev = EncodingHelper.prevCharHead(str, at);
|
||||
|
||||
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
|
||||
@ -377,8 +365,6 @@ public abstract class Matcher extends IntHolder {
|
||||
prev = -1;
|
||||
msaInit(option, start);
|
||||
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) stateCheckBuffClear();
|
||||
|
||||
if (matchCheck(end, s, prev)) return match(s);
|
||||
return mismatch();
|
||||
}
|
||||
@ -393,10 +379,6 @@ public abstract class Matcher extends IntHolder {
|
||||
}
|
||||
|
||||
msaInit(option, origStart);
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
int offset = Math.min(start, range) - str;
|
||||
stateCheckBuffInit(end - str, offset, regex.numCombExpCheck);
|
||||
}
|
||||
|
||||
s = start;
|
||||
if (range > start) { /* forward search */
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
public final class NameEntry {
|
||||
static final int INIT_NAME_BACKREFS_ALLOC_NUM = 8;
|
||||
|
||||
public final char[] name;
|
||||
public final int nameP;
|
||||
public final int nameEnd;
|
||||
|
||||
int backNum;
|
||||
int backRef1;
|
||||
int backRefs[];
|
||||
|
||||
public NameEntry(char[] chars, int p, int end) {
|
||||
name = chars;
|
||||
nameP = p;
|
||||
nameEnd = end;
|
||||
}
|
||||
|
||||
public int[] getBackRefs() {
|
||||
switch (backNum) {
|
||||
case 0:
|
||||
return new int[]{};
|
||||
case 1:
|
||||
return new int[]{backRef1};
|
||||
default:
|
||||
int[]result = new int[backNum];
|
||||
System.arraycopy(backRefs, 0, result, 0, backNum);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void alloc() {
|
||||
backRefs = new int[INIT_NAME_BACKREFS_ALLOC_NUM];
|
||||
}
|
||||
|
||||
private void ensureSize() {
|
||||
if (backNum > backRefs.length) {
|
||||
int[]tmp = new int[backRefs.length << 1];
|
||||
System.arraycopy(backRefs, 0, tmp, 0, backRefs.length);
|
||||
backRefs = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
public void addBackref(int backRef) {
|
||||
backNum++;
|
||||
|
||||
switch (backNum) {
|
||||
case 1:
|
||||
backRef1 = backRef;
|
||||
break;
|
||||
case 2:
|
||||
alloc();
|
||||
backRefs[0] = backRef1;
|
||||
backRefs[1] = backRef;
|
||||
break;
|
||||
default:
|
||||
ensureSize();
|
||||
backRefs[backNum - 1] = backRef;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder buff = new StringBuilder(new String(name, nameP, nameEnd - nameP) + " ");
|
||||
if (backNum == 0) {
|
||||
buff.append("-");
|
||||
} else if (backNum == 1){
|
||||
buff.append(backRef1);
|
||||
} else {
|
||||
for (int i=0; i<backNum; i++){
|
||||
if (i > 0) buff.append(", ");
|
||||
buff.append(backRefs[i]);
|
||||
}
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
public abstract class NativeMachine extends Matcher {
|
||||
|
||||
protected NativeMachine(Regex regex, char[] chars, int p, int end) {
|
||||
super(regex, chars, p, end);
|
||||
}
|
||||
}
|
@ -19,20 +19,15 @@
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnOff;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnyCharNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
|
||||
@ -66,65 +61,6 @@ class Parser extends Lexer {
|
||||
return root;
|
||||
}
|
||||
|
||||
private static final int POSIX_BRACKET_NAME_MIN_LEN = 4;
|
||||
private static final int POSIX_BRACKET_CHECK_LIMIT_LENGTH = 20;
|
||||
private static final char BRACKET_END[] = ":]".toCharArray();
|
||||
private boolean parsePosixBracket(CClassNode cc) {
|
||||
mark();
|
||||
|
||||
boolean not;
|
||||
if (peekIs('^')) {
|
||||
inc();
|
||||
not = true;
|
||||
} else {
|
||||
not = false;
|
||||
}
|
||||
if (stop - p >= POSIX_BRACKET_NAME_MIN_LEN + 3) { // else goto not_posix_bracket
|
||||
char[][] pbs = PosixBracket.PBSNamesLower;
|
||||
for (int i=0; i<pbs.length; i++) {
|
||||
char[] name = pbs[i];
|
||||
// hash lookup here ?
|
||||
if (EncodingHelper.strNCmp(chars, p, stop, name, 0, name.length) == 0) {
|
||||
p += name.length;
|
||||
if (EncodingHelper.strNCmp(chars, p, stop, BRACKET_END, 0, BRACKET_END.length) != 0) {
|
||||
newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
|
||||
}
|
||||
cc.addCType(PosixBracket.PBSValues[i], not, env, this);
|
||||
inc();
|
||||
inc();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// not_posix_bracket:
|
||||
c = 0;
|
||||
int i= 0;
|
||||
while (left() && ((c=peek()) != ':') && c != ']') {
|
||||
inc();
|
||||
if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break;
|
||||
}
|
||||
|
||||
if (c == ':' && left()) {
|
||||
inc();
|
||||
if (left()) {
|
||||
fetch();
|
||||
if (c == ']') newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
|
||||
}
|
||||
}
|
||||
restore();
|
||||
return true; /* 1: is not POSIX bracket, but no error. */
|
||||
}
|
||||
|
||||
private CClassNode parseCharProperty() {
|
||||
int ctype = fetchCharPropertyToCType();
|
||||
CClassNode n = new CClassNode();
|
||||
n.addCType(ctype, false, env, this);
|
||||
if (token.getPropNot()) n.setNot();
|
||||
return n;
|
||||
}
|
||||
|
||||
private boolean codeExistCheck(int code, boolean ignoreEscaped) {
|
||||
mark();
|
||||
|
||||
@ -225,29 +161,11 @@ class Parser extends Lexer {
|
||||
parseCharClassValEntry(cc, arg); // val_entry:, val_entry2
|
||||
break;
|
||||
|
||||
case POSIX_BRACKET_OPEN:
|
||||
if (parsePosixBracket(cc)) { /* true: is not POSIX bracket */
|
||||
env.ccEscWarn("[");
|
||||
p = token.backP;
|
||||
arg.v = token.getC();
|
||||
arg.vIsRaw = false;
|
||||
parseCharClassValEntry(cc, arg); // goto val_entry
|
||||
break;
|
||||
}
|
||||
cc.nextStateClass(arg, env); // goto next_class
|
||||
break;
|
||||
|
||||
case CHAR_TYPE:
|
||||
cc.addCType(token.getPropCType(), token.getPropNot(), env, this);
|
||||
cc.nextStateClass(arg, env); // next_class:
|
||||
break;
|
||||
|
||||
case CHAR_PROPERTY:
|
||||
int ctype = fetchCharPropertyToCType();
|
||||
cc.addCType(ctype, token.getPropNot(), env, this);
|
||||
cc.nextStateClass(arg, env); // goto next_class
|
||||
break;
|
||||
|
||||
case CC_RANGE:
|
||||
if (arg.state == CCSTATE.VALUE) {
|
||||
fetchTokenInCC();
|
||||
@ -413,15 +331,6 @@ class Parser extends Lexer {
|
||||
node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
|
||||
break;
|
||||
case '\'':
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
if (syntax.op2QMarkLtNamedGroup()) {
|
||||
listCapture = false; // goto named_group1
|
||||
node = parseEncloseNamedGroup2(listCapture);
|
||||
break;
|
||||
} else {
|
||||
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
|
||||
}
|
||||
} // USE_NAMED_GROUP
|
||||
break;
|
||||
case '<': /* look behind (?<=...), (?<!...) */
|
||||
fetch();
|
||||
@ -430,36 +339,12 @@ class Parser extends Lexer {
|
||||
} else if (c == '!') {
|
||||
node = new AnchorNode(AnchorType.LOOK_BEHIND_NOT);
|
||||
} else {
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
if (syntax.op2QMarkLtNamedGroup()) {
|
||||
unfetch();
|
||||
c = '<';
|
||||
|
||||
listCapture = false; // named_group1:
|
||||
node = parseEncloseNamedGroup2(listCapture); // named_group2:
|
||||
break;
|
||||
} else {
|
||||
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
|
||||
}
|
||||
|
||||
} else { // USE_NAMED_GROUP
|
||||
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
|
||||
} // USE_NAMED_GROUP
|
||||
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
if (syntax.op2AtMarkCaptureHistory()) {
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
if (syntax.op2QMarkLtNamedGroup()) {
|
||||
fetch();
|
||||
if (c == '<' || c == '\'') {
|
||||
listCapture = true;
|
||||
node = parseEncloseNamedGroup2(listCapture); // goto named_group2 /* (?@<name>...) */
|
||||
}
|
||||
unfetch();
|
||||
}
|
||||
} // USE_NAMED_GROUP
|
||||
EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
|
||||
EncloseNode en = new EncloseNode(); // node_new_enclose_memory
|
||||
int num = env.addMemEntry();
|
||||
if (num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
|
||||
en.regNum = num;
|
||||
@ -546,7 +431,7 @@ class Parser extends Lexer {
|
||||
returnCode = 1; /* group */
|
||||
return node;
|
||||
}
|
||||
EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
|
||||
EncloseNode en = new EncloseNode(); // node_new_enclose_memory
|
||||
int num = env.addMemEntry();
|
||||
en.regNum = num;
|
||||
node = en;
|
||||
@ -570,48 +455,6 @@ class Parser extends Lexer {
|
||||
return node; // ??
|
||||
}
|
||||
|
||||
private Node parseEncloseNamedGroup2(boolean listCapture) {
|
||||
int nm = p;
|
||||
int num = fetchName(c, false);
|
||||
int nameEnd = value;
|
||||
num = env.addMemEntry();
|
||||
if (listCapture && num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
|
||||
|
||||
regex.nameAdd(chars, nm, nameEnd, num, syntax);
|
||||
EncloseNode en = new EncloseNode(env.option, true); // node_new_enclose_memory
|
||||
en.regNum = num;
|
||||
|
||||
Node node = en;
|
||||
|
||||
if (listCapture) env.captureHistory = bsOnAtSimple(env.captureHistory, num);
|
||||
env.numNamed++;
|
||||
return node;
|
||||
}
|
||||
|
||||
private int findStrPosition(int[]s, int n, int from, int to, Ptr nextChar) {
|
||||
int x;
|
||||
int q;
|
||||
int p = from;
|
||||
int i = 0;
|
||||
while (p < to) {
|
||||
x = chars[p];
|
||||
q = p + 1;
|
||||
if (x == s[0]) {
|
||||
for (i=1; i<n && q<to; i++) {
|
||||
x = chars[q];
|
||||
if (x != s[i]) break;
|
||||
q++;
|
||||
}
|
||||
if (i >= n) {
|
||||
if (chars[nextChar.p] != 0) nextChar.p = q; // we may need zero term semantics...
|
||||
return p;
|
||||
}
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Node parseExp(TokenType term) {
|
||||
if (token.type == term) return StringNode.EMPTY; // goto end_of_token
|
||||
|
||||
@ -656,16 +499,6 @@ class Parser extends Lexer {
|
||||
node = new StringNode(buf, 0, 1);
|
||||
break;
|
||||
|
||||
case QUOTE_OPEN:
|
||||
int[] endOp = new int[] {syntax.metaCharTable.esc, 'E'};
|
||||
int qstart = p;
|
||||
Ptr nextChar = new Ptr();
|
||||
int qend = findStrPosition(endOp, endOp.length, qstart, stop, nextChar);
|
||||
if (qend == -1) nextChar.p = qend = stop;
|
||||
node = new StringNode(chars, qstart, qend);
|
||||
p = nextChar.p;
|
||||
break;
|
||||
|
||||
case CHAR_TYPE:
|
||||
switch(token.getPropCType()) {
|
||||
case CharacterType.D:
|
||||
@ -679,10 +512,6 @@ class Parser extends Lexer {
|
||||
}
|
||||
break;
|
||||
|
||||
case CharacterType.WORD:
|
||||
node = new CTypeNode(token.getPropCType(), token.getPropNot());
|
||||
break;
|
||||
|
||||
case CharacterType.SPACE:
|
||||
case CharacterType.DIGIT:
|
||||
case CharacterType.XDIGIT:
|
||||
@ -699,10 +528,6 @@ class Parser extends Lexer {
|
||||
} // inner switch
|
||||
break;
|
||||
|
||||
case CHAR_PROPERTY:
|
||||
node = parseCharProperty();
|
||||
break;
|
||||
|
||||
case CC_CC_OPEN:
|
||||
CClassNode cc = parseCharClass();
|
||||
node = cc;
|
||||
@ -735,20 +560,6 @@ class Parser extends Lexer {
|
||||
token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
|
||||
token.getBackrefLevel(), // ...
|
||||
env);
|
||||
|
||||
break;
|
||||
|
||||
case CALL:
|
||||
if (Config.USE_SUBEXP_CALL) {
|
||||
int gNum = token.getCallGNum();
|
||||
|
||||
if (gNum < 0) {
|
||||
gNum = backrefRelToAbs(gNum);
|
||||
if (gNum <= 0) newValueException(ERR_INVALID_BACKREF);
|
||||
}
|
||||
node = new CallNode(chars, token.getCallNameP(), token.getCallNameEnd(), gNum);
|
||||
env.numCall++;
|
||||
} // USE_SUBEXP_CALL
|
||||
break;
|
||||
|
||||
case ANCHOR:
|
||||
|
@ -23,9 +23,11 @@ import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
|
||||
@ -44,7 +46,6 @@ public final class Regex implements RegexState {
|
||||
int numMem; /* used memory(...) num counted from 1 */
|
||||
int numRepeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */
|
||||
int numNullCheck; /* OP_NULL_CHECK_START/END id counter */
|
||||
int numCombExpCheck; /* combination explosion check */
|
||||
int numCall; /* number of subexp call */
|
||||
int captureHistory; /* (?@...) flag (1-31) */
|
||||
int btMemStart; /* need backtrack flag */
|
||||
@ -57,7 +58,7 @@ public final class Regex implements RegexState {
|
||||
|
||||
WarnCallback warnings;
|
||||
MatcherFactory factory;
|
||||
private Analyser analyser;
|
||||
protected Analyser analyser;
|
||||
|
||||
int options;
|
||||
int userOptions;
|
||||
@ -65,8 +66,6 @@ public final class Regex implements RegexState {
|
||||
//final Syntax syntax;
|
||||
final int caseFoldFlag;
|
||||
|
||||
HashMap<String,NameEntry> nameTable; // named entries
|
||||
|
||||
/* optimization info (string search, char-map and anchors) */
|
||||
SearchAlgorithm searchAlgorithm; /* optimize flag */
|
||||
int thresholdLength; /* search str-length for apply optimize */
|
||||
@ -172,112 +171,6 @@ public final class Regex implements RegexState {
|
||||
return numMem;
|
||||
}
|
||||
|
||||
public int numberOfCaptureHistories() {
|
||||
if (Config.USE_CAPTURE_HISTORY) {
|
||||
int n = 0;
|
||||
for (int i=0; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
|
||||
if (bsAt(captureHistory, i)) n++;
|
||||
}
|
||||
return n;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
String nameTableToString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (nameTable != null) {
|
||||
sb.append("name table\n");
|
||||
for (NameEntry ne : nameTable.values()) {
|
||||
sb.append(" " + ne + "\n");
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
NameEntry nameFind(char[] name, int nameP, int nameEnd) {
|
||||
if (nameTable != null) return nameTable.get(new String(name, nameP, nameEnd - nameP));
|
||||
return null;
|
||||
}
|
||||
|
||||
void renumberNameTable(int[]map) {
|
||||
if (nameTable != null) {
|
||||
for (NameEntry e : nameTable.values()) {
|
||||
if (e.backNum > 1) {
|
||||
for (int i=0; i<e.backNum; i++) {
|
||||
e.backRefs[i] = map[e.backRefs[i]];
|
||||
}
|
||||
} else if (e.backNum == 1) {
|
||||
e.backRef1 = map[e.backRef1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int numberOfNames() {
|
||||
return nameTable == null ? 0 : nameTable.size();
|
||||
}
|
||||
|
||||
void nameAdd(char[] name, int nameP, int nameEnd, int backRef, Syntax syntax) {
|
||||
if (nameEnd - nameP <= 0) throw new ValueException(ErrorMessages.ERR_EMPTY_GROUP_NAME);
|
||||
|
||||
NameEntry e = null;
|
||||
if (nameTable == null) {
|
||||
nameTable = new HashMap<String,NameEntry>(); // 13, oni defaults to 5
|
||||
} else {
|
||||
e = nameFind(name, nameP, nameEnd);
|
||||
}
|
||||
|
||||
if (e == null) {
|
||||
// dup the name here as oni does ?, what for ? (it has to manage it, we don't)
|
||||
e = new NameEntry(name, nameP, nameEnd);
|
||||
nameTable.put(new String(name, nameP, nameEnd - nameP), e);
|
||||
} else if (e.backNum >= 1 && !syntax.allowMultiplexDefinitionName()) {
|
||||
throw new ValueException(ErrorMessages.ERR_MULTIPLEX_DEFINED_NAME, new String(name, nameP, nameEnd - nameP));
|
||||
}
|
||||
|
||||
e.addBackref(backRef);
|
||||
}
|
||||
|
||||
NameEntry nameToGroupNumbers(char[] name, int nameP, int nameEnd) {
|
||||
return nameFind(name, nameP, nameEnd);
|
||||
}
|
||||
|
||||
public int nameToBackrefNumber(char[] name, int nameP, int nameEnd, Region region) {
|
||||
NameEntry e = nameToGroupNumbers(name, nameP, nameEnd);
|
||||
if (e == null) throw new ValueException(ErrorMessages.ERR_UNDEFINED_NAME_REFERENCE,
|
||||
new String(name, nameP, nameEnd - nameP));
|
||||
|
||||
switch(e.backNum) {
|
||||
case 0:
|
||||
throw new InternalException(ErrorMessages.ERR_PARSER_BUG);
|
||||
case 1:
|
||||
return e.backRef1;
|
||||
default:
|
||||
if (region != null) {
|
||||
for (int i = e.backNum - 1; i >= 0; i--) {
|
||||
if (region.beg[e.backRefs[i]] != Region.REGION_NOTPOS) return e.backRefs[i];
|
||||
}
|
||||
}
|
||||
return e.backRefs[e.backNum - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<NameEntry> namedBackrefIterator() {
|
||||
return nameTable.values().iterator();
|
||||
}
|
||||
|
||||
public boolean noNameGroupIsActive(Syntax syntax) {
|
||||
if (isDontCaptureGroup(options)) return false;
|
||||
|
||||
if (Config.USE_NAMED_GROUP) {
|
||||
if (numberOfNames() > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(options)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* set skip map for Boyer-Moor search */
|
||||
void setupBMSkipMap() {
|
||||
char[] chars = exact;
|
||||
@ -353,16 +246,6 @@ public final class Regex implements RegexState {
|
||||
exactP = exactEnd = 0;
|
||||
}
|
||||
|
||||
public String encStringToString(byte[]bytes, int p, int end) {
|
||||
StringBuilder sb = new StringBuilder("\nPATTERN: /");
|
||||
|
||||
while (p < end) {
|
||||
sb.append(new String(new byte[]{bytes[p]}));
|
||||
p++;
|
||||
}
|
||||
return sb.append("/").toString();
|
||||
}
|
||||
|
||||
public String optimizeInfoToString() {
|
||||
String s = "";
|
||||
s += "optimize: " + searchAlgorithm.getName() + "\n";
|
||||
@ -410,19 +293,13 @@ public final class Regex implements RegexState {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setUserOptions(int options) {
|
||||
this.userOptions = options;
|
||||
public String dumpTree() {
|
||||
return analyser == null ? null : analyser.root.toString();
|
||||
}
|
||||
|
||||
public int getUserOptions() {
|
||||
return userOptions;
|
||||
public String dumpByteCode() {
|
||||
compile();
|
||||
return new ByteCodePrinter(this).byteCodeListToString();
|
||||
}
|
||||
|
||||
public void setUserObject(Object object) {
|
||||
this.userObject = object;
|
||||
}
|
||||
|
||||
public Object getUserObject() {
|
||||
return userObject;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ public final class Region {
|
||||
public final int numRegs;
|
||||
public final int[]beg;
|
||||
public final int[]end;
|
||||
public CaptureTreeNode historyRoot;
|
||||
|
||||
public Region(int num) {
|
||||
this.numRegs = num;
|
||||
@ -33,20 +32,6 @@ public final class Region {
|
||||
this.end = new int[num];
|
||||
}
|
||||
|
||||
public Region(int begin, int end) {
|
||||
this.numRegs = 1;
|
||||
this.beg = new int[]{begin};
|
||||
this.end = new int[]{end};
|
||||
}
|
||||
|
||||
public Region clone() {
|
||||
Region region = new Region(numRegs);
|
||||
System.arraycopy(beg, 0, region.beg, 0, beg.length);
|
||||
System.arraycopy(end, 0, region.end, 0, end.length);
|
||||
if (historyRoot != null) region.historyRoot = historyRoot.cloneTree();
|
||||
return region;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Region: \n");
|
||||
@ -54,10 +39,6 @@ public final class Region {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
CaptureTreeNode getCaptureTree() {
|
||||
return historyRoot;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (int i=0; i<beg.length; i++) {
|
||||
beg[i] = end[i] = REGION_NOTPOS;
|
||||
|
@ -40,16 +40,10 @@ public final class ScanEnvironment {
|
||||
final public Regex reg;
|
||||
|
||||
int numCall;
|
||||
UnsetAddrList unsetAddrList; // USE_SUBEXP_CALL
|
||||
public int numMem;
|
||||
|
||||
int numNamed; // USE_NAMED_GROUP
|
||||
|
||||
public Node memNodes[];
|
||||
|
||||
// USE_COMBINATION_EXPLOSION_CHECK
|
||||
int numCombExpCheck;
|
||||
int combExpMaxRegNum;
|
||||
int currMaxRegNum;
|
||||
boolean hasRecursion;
|
||||
|
||||
@ -69,12 +63,8 @@ public final class ScanEnvironment {
|
||||
numCall = 0;
|
||||
numMem = 0;
|
||||
|
||||
numNamed = 0;
|
||||
|
||||
memNodes = null;
|
||||
|
||||
numCombExpCheck = 0;
|
||||
combExpMaxRegNum = 0;
|
||||
currMaxRegNum = 0;
|
||||
hasRecursion = false;
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
|
||||
private final int end; // pattern end position for reset() support
|
||||
protected int _p; // used by mark()/restore() to mark positions
|
||||
|
||||
private final static int INT_SIGN_BIT = 1 << 31;
|
||||
|
||||
protected ScannerSupport(char[] chars, int p, int end) {
|
||||
this.chars = chars;
|
||||
this.begin = p;
|
||||
@ -53,8 +55,6 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
|
||||
return end;
|
||||
}
|
||||
|
||||
private final int INT_SIGN_BIT = 1 << 31;
|
||||
|
||||
protected final int scanUnsignedNumber() {
|
||||
int last = c;
|
||||
int num = 0; // long ???
|
||||
|
@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
|
||||
@ -36,10 +35,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
protected final int[]repeatStk;
|
||||
protected final int memStartStk, memEndStk;
|
||||
|
||||
// CEC
|
||||
protected byte[] stateCheckBuff; // move to int[] ?
|
||||
int stateCheckBuffSize;
|
||||
|
||||
protected StackMachine(Regex regex, char[] chars, int p , int end) {
|
||||
super(regex, chars, p, end);
|
||||
|
||||
@ -104,67 +99,12 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
stk++;
|
||||
}
|
||||
|
||||
// CEC
|
||||
|
||||
// STATE_CHECK_POS
|
||||
private int stateCheckPos(int s, int snum) {
|
||||
return (s - str) * regex.numCombExpCheck + (snum - 1);
|
||||
}
|
||||
|
||||
// STATE_CHECK_VAL
|
||||
protected final boolean stateCheckVal(int s, int snum) {
|
||||
if (stateCheckBuff != null) {
|
||||
int x = stateCheckPos(s, snum);
|
||||
return (stateCheckBuff[x / 8] & (1 << (x % 8))) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ELSE_IF_STATE_CHECK_MARK
|
||||
private void stateCheckMark() {
|
||||
StackEntry e = stack[stk];
|
||||
int x = stateCheckPos(e.getStatePStr(), e.getStateCheck());
|
||||
stateCheckBuff[x / 8] |= (1 << (x % 8));
|
||||
}
|
||||
|
||||
// STATE_CHECK_BUFF_INIT
|
||||
private static final int STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE = 16;
|
||||
protected final void stateCheckBuffInit(int strLength, int offset, int stateNum) {
|
||||
if (stateNum > 0 && strLength >= Config.CHECK_STRING_THRESHOLD_LEN) {
|
||||
int size = ((strLength + 1) * stateNum + 7) >>> 3;
|
||||
offset = (offset * stateNum) >>> 3;
|
||||
|
||||
if (size > 0 && offset < size && size < Config.CHECK_BUFF_MAX_SIZE) {
|
||||
if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) {
|
||||
stateCheckBuff = new byte[size];
|
||||
} else {
|
||||
// same impl, reduce...
|
||||
stateCheckBuff = new byte[size];
|
||||
}
|
||||
Arrays.fill(stateCheckBuff, offset, (size - offset), (byte)0);
|
||||
stateCheckBuffSize = size;
|
||||
} else {
|
||||
stateCheckBuff = null; // reduce
|
||||
stateCheckBuffSize = 0;
|
||||
}
|
||||
} else {
|
||||
stateCheckBuff = null; // reduce
|
||||
stateCheckBuffSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void stateCheckBuffClear() {
|
||||
stateCheckBuff = null;
|
||||
stateCheckBuffSize = 0;
|
||||
}
|
||||
|
||||
private void push(int type, int pat, int s, int prev) {
|
||||
StackEntry e = ensure1();
|
||||
e.type = type;
|
||||
e.setStatePCode(pat);
|
||||
e.setStatePStr(s);
|
||||
e.setStatePStrPrev(prev);
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
|
||||
stk++;
|
||||
}
|
||||
|
||||
@ -172,30 +112,9 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
StackEntry e = stack[stk];
|
||||
e.type = type;
|
||||
e.setStatePCode(pat);
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
|
||||
stk++;
|
||||
}
|
||||
|
||||
protected final void pushAltWithStateCheck(int pat, int s, int sprev, int snum) {
|
||||
StackEntry e = ensure1();
|
||||
e.type = ALT;
|
||||
e.setStatePCode(pat);
|
||||
e.setStatePStr(s);
|
||||
e.setStatePStrPrev(sprev);
|
||||
if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(stateCheckBuff != null ? snum : 0);
|
||||
stk++;
|
||||
}
|
||||
|
||||
protected final void pushStateCheck(int s, int snum) {
|
||||
if (stateCheckBuff != null) {
|
||||
StackEntry e = ensure1();
|
||||
e.type = STATE_CHECK_MARK;
|
||||
e.setStatePStr(s);
|
||||
e.setStateCheck(snum);
|
||||
stk++;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void pushAlt(int pat, int s, int prev) {
|
||||
push(ALT, pat, s, prev);
|
||||
}
|
||||
@ -294,19 +213,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
stk++;
|
||||
}
|
||||
|
||||
protected final void pushCallFrame(int pat) {
|
||||
StackEntry e = ensure1();
|
||||
e.type = CALL_FRAME;
|
||||
e.setCallFrameRetAddr(pat);
|
||||
stk++;
|
||||
}
|
||||
|
||||
protected final void pushReturn() {
|
||||
StackEntry e = ensure1();
|
||||
e.type = RETURN;
|
||||
stk++;
|
||||
}
|
||||
|
||||
// stack debug routines here
|
||||
// ...
|
||||
|
||||
@ -331,8 +237,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
|
||||
if ((e.type & MASK_POP_USED) != 0) {
|
||||
return e;
|
||||
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
if (e.type == STATE_CHECK_MARK) stateCheckMark();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -346,8 +250,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
} else if (e.type == MEM_START) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -368,8 +270,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -391,8 +291,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
} else if (e.type == MEM_END){
|
||||
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
|
||||
repeatStk[memEndStk + e.getMemNum()] = e.getMemStart();
|
||||
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
|
||||
if (e.type == STATE_CHECK_MARK) stateCheckMark();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,8 +312,6 @@ abstract class StackMachine extends Matcher implements StackType {
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +609,7 @@ public final class Syntax implements SyntaxProperties{
|
||||
OP_ESC_CONTROL_CHARS | OP_ESC_C_CONTROL | OP_ESC_X_HEX2)
|
||||
& ~OP_ESC_LTGT_WORD_BEGIN_END ),
|
||||
|
||||
( OP2_QMARK_GROUP_EFFECT | OP2_CCLASS_SET_OP |
|
||||
( OP2_QMARK_GROUP_EFFECT |
|
||||
OP2_ESC_V_VTAB | OP2_ESC_U_HEX4 ),
|
||||
|
||||
( GNU_REGEX_BV | DIFFERENT_LEN_ALT_LOOK_BEHIND ),
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
|
||||
|
||||
public final class UnsetAddrList {
|
||||
int num;
|
||||
Node[]targets;
|
||||
int[]offsets;
|
||||
|
||||
public UnsetAddrList(int size) {
|
||||
targets = new Node[size];
|
||||
offsets = new int[size];
|
||||
}
|
||||
|
||||
public void add(int offset, Node node) {
|
||||
if (num >= offsets.length) {
|
||||
Node []ttmp = new Node[targets.length << 1];
|
||||
System.arraycopy(targets, 0, ttmp, 0, num);
|
||||
targets = ttmp;
|
||||
int[]otmp = new int[offsets.length << 1];
|
||||
System.arraycopy(offsets, 0, otmp, 0, num);
|
||||
offsets = otmp;
|
||||
}
|
||||
targets[num] = node;
|
||||
offsets[num] = offset;
|
||||
|
||||
num++;
|
||||
}
|
||||
|
||||
public void fix(Regex regex) {
|
||||
for (int i=0; i<num; i++) {
|
||||
EncloseNode en = (EncloseNode)targets[i];
|
||||
if (!en.isAddrFixed()) new InternalException(ErrorMessages.ERR_PARSER_BUG);
|
||||
regex.code[offsets[i]] = en.callAddr; // is this safe ?
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder value = new StringBuilder();
|
||||
if (num > 0) {
|
||||
for (int i=0; i<num; i++) {
|
||||
value.append("offset + " + offsets[i] + " target: " + targets[i].getAddressName());
|
||||
}
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.*;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.CCSTATE;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.CCVALTYPE;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.AsciiTables;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
|
||||
@ -40,6 +39,41 @@ public final class CClassNode extends Node {
|
||||
|
||||
private int ctype; // for hashing purposes
|
||||
|
||||
private final static short AsciiCtypeTable[] = {
|
||||
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
|
||||
0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008,
|
||||
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
|
||||
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
|
||||
0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
|
||||
0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
|
||||
0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0,
|
||||
0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
|
||||
0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2,
|
||||
0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
|
||||
0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
|
||||
0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0,
|
||||
0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2,
|
||||
0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
|
||||
0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
|
||||
0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
// node_new_cclass
|
||||
public CClassNode() {}
|
||||
|
||||
@ -330,13 +364,13 @@ public final class CClassNode extends Node {
|
||||
if (not) {
|
||||
for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
|
||||
// if (!ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
|
||||
if ((AsciiTables.AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c);
|
||||
if ((AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c);
|
||||
}
|
||||
addAllMultiByteRange();
|
||||
} else {
|
||||
for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
|
||||
// if (ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
|
||||
if ((AsciiTables.AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c);
|
||||
if ((AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.ast;
|
||||
|
||||
public final class CTypeNode extends Node {
|
||||
public int ctype;
|
||||
public boolean not;
|
||||
|
||||
public CTypeNode(int type, boolean not) {
|
||||
this.ctype= type;
|
||||
this.not = not;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return CTYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Character Type";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int level) {
|
||||
StringBuilder value = new StringBuilder();
|
||||
value.append("\n ctype: " + ctype);
|
||||
value.append("\n not: " + not);
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.ast;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.UnsetAddrList;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
|
||||
|
||||
public final class CallNode extends StateNode {
|
||||
public char[] name;
|
||||
public int nameP;
|
||||
public int nameEnd;
|
||||
|
||||
public int groupNum;
|
||||
public Node target; // is it an EncloseNode always ?
|
||||
public UnsetAddrList unsetAddrList;
|
||||
|
||||
public CallNode(char[] name, int nameP, int nameEnd, int gnum) {
|
||||
this.name = name;
|
||||
this.nameP = nameP;
|
||||
this.nameEnd = nameEnd;
|
||||
this.groupNum = gnum; /* call by number if gnum != 0 */
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return CALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setChild(Node newChild) {
|
||||
target = newChild;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getChild() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void setTarget(Node tgt) {
|
||||
target = tgt;
|
||||
tgt.parent = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Call";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyTree(Set<Node> set, WarnCallback warnings) {
|
||||
if (target == null || target.parent == this)
|
||||
warnings.warn(this.getAddressName() + " doesn't point to a target or the target has been stolen");
|
||||
// do not recurse here
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int level) {
|
||||
StringBuilder value = new StringBuilder(super.toString(level));
|
||||
value.append("\n name: " + new String(name, nameP, nameEnd - nameP));
|
||||
value.append("\n groupNum: " + groupNum);
|
||||
value.append("\n target: " + pad(target.getAddressName(), level + 1));
|
||||
value.append("\n unsetAddrList: " + pad(unsetAddrList, level + 1));
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType;
|
||||
|
||||
public final class EncloseNode extends StateNode implements EncloseType {
|
||||
|
||||
public int type; // enclose type
|
||||
public final int type; // enclose type
|
||||
public int regNum;
|
||||
public int option;
|
||||
public Node target; /* EncloseNode : ENCLOSE_MEMORY */
|
||||
@ -42,10 +42,8 @@ public final class EncloseNode extends StateNode implements EncloseType {
|
||||
}
|
||||
|
||||
// node_new_enclose_memory
|
||||
public EncloseNode(int option, boolean isNamed) {
|
||||
public EncloseNode() {
|
||||
this(MEMORY);
|
||||
if (isNamed) setNamedGroup();
|
||||
if (Config.USE_SUBEXP_CALL) this.option = option;
|
||||
}
|
||||
|
||||
// node_new_option
|
||||
@ -104,46 +102,14 @@ public final class EncloseNode extends StateNode implements EncloseType {
|
||||
return types.toString();
|
||||
}
|
||||
|
||||
public void setEncloseStatus(int flag) {
|
||||
state |= flag;
|
||||
}
|
||||
|
||||
public void clearEncloseStatus(int flag) {
|
||||
state &= ~flag;
|
||||
}
|
||||
|
||||
public void clearMemory() {
|
||||
type &= ~MEMORY;
|
||||
}
|
||||
|
||||
public void setMemory() {
|
||||
type |= MEMORY;
|
||||
}
|
||||
|
||||
public boolean isMemory() {
|
||||
return (type & MEMORY) != 0;
|
||||
}
|
||||
|
||||
public void clearOption() {
|
||||
type &= ~OPTION;
|
||||
}
|
||||
|
||||
public void setOption() {
|
||||
type |= OPTION;
|
||||
}
|
||||
|
||||
public boolean isOption() {
|
||||
return (type & OPTION) != 0;
|
||||
}
|
||||
|
||||
public void clearStopBacktrack() {
|
||||
type &= ~STOP_BACKTRACK;
|
||||
}
|
||||
|
||||
public void setStopBacktrack() {
|
||||
type |= STOP_BACKTRACK;
|
||||
}
|
||||
|
||||
public boolean isStopBacktrack() {
|
||||
return (type & STOP_BACKTRACK) != 0;
|
||||
}
|
||||
|
@ -21,9 +21,10 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.Config;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.*;
|
||||
|
||||
public final class QuantifierNode extends StateNode {
|
||||
|
||||
public Node target;
|
||||
@ -37,8 +38,33 @@ public final class QuantifierNode extends StateNode {
|
||||
public Node nextHeadExact;
|
||||
public boolean isRefered; /* include called node. don't eliminate even if {0} */
|
||||
|
||||
// USE_COMBINATION_EXPLOSION_CHECK
|
||||
public int combExpCheckNum; /* 1,2,3...: check, 0: no check */
|
||||
enum ReduceType {
|
||||
ASIS, /* as is */
|
||||
DEL, /* delete parent */
|
||||
A, /* to '*' */
|
||||
AQ, /* to '*?' */
|
||||
QQ, /* to '??' */
|
||||
P_QQ, /* to '+)??' */
|
||||
PQ_Q, /* to '+?)?' */
|
||||
}
|
||||
|
||||
private final static ReduceType[][] REDUCE_TABLE = {
|
||||
{DEL, A, A, QQ, AQ, ASIS}, /* '?' */
|
||||
{DEL, DEL, DEL, P_QQ, P_QQ, DEL}, /* '*' */
|
||||
{A, A, DEL, ASIS, P_QQ, DEL}, /* '+' */
|
||||
{DEL, AQ, AQ, DEL, AQ, AQ}, /* '??' */
|
||||
{DEL, DEL, DEL, DEL, DEL, DEL}, /* '*?' */
|
||||
{ASIS, PQ_Q, DEL, AQ, AQ, DEL} /* '+?' */
|
||||
};
|
||||
|
||||
private final static String PopularQStr[] = new String[] {
|
||||
"?", "*", "+", "??", "*?", "+?"
|
||||
};
|
||||
|
||||
private final static String ReduceQStr[]= new String[] {
|
||||
"", "", "*", "*?", "??", "+ and ??", "+? and ?"
|
||||
};
|
||||
|
||||
|
||||
public QuantifierNode(int lower, int upper, boolean byNumber) {
|
||||
this.lower = lower;
|
||||
@ -92,7 +118,6 @@ public final class QuantifierNode extends StateNode {
|
||||
value.append("\n headExact: " + pad(headExact, level + 1));
|
||||
value.append("\n nextHeadExact: " + pad(nextHeadExact, level + 1));
|
||||
value.append("\n isRefered: " + isRefered);
|
||||
value.append("\n combExpCheckNum: " + combExpCheckNum);
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
@ -134,7 +159,6 @@ public final class QuantifierNode extends StateNode {
|
||||
headExact = other.headExact;
|
||||
nextHeadExact = other.nextHeadExact;
|
||||
isRefered = other.isRefered;
|
||||
combExpCheckNum = other.combExpCheckNum;
|
||||
}
|
||||
|
||||
public void reduceNestedQuantifier(QuantifierNode other) {
|
||||
@ -143,7 +167,7 @@ public final class QuantifierNode extends StateNode {
|
||||
|
||||
if (pnum < 0 || cnum < 0) return;
|
||||
|
||||
switch(Reduce.REDUCE_TABLE[cnum][pnum]) {
|
||||
switch(REDUCE_TABLE[cnum][pnum]) {
|
||||
case DEL:
|
||||
// no need to set the parent here...
|
||||
// swap ?
|
||||
@ -226,7 +250,7 @@ public final class QuantifierNode extends StateNode {
|
||||
|
||||
if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) {
|
||||
if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) {
|
||||
switch(Reduce.REDUCE_TABLE[targetQNum][nestQNum]) {
|
||||
switch(REDUCE_TABLE[targetQNum][nestQNum]) {
|
||||
case ASIS:
|
||||
break;
|
||||
|
||||
@ -237,9 +261,9 @@ public final class QuantifierNode extends StateNode {
|
||||
|
||||
default:
|
||||
env.reg.getWarnings().warn(new String(chars, p, end) +
|
||||
" nested repeat operator " + Reduce.PopularQStr[targetQNum] +
|
||||
" and " + Reduce.PopularQStr[nestQNum] + " was replaced with '" +
|
||||
Reduce.ReduceQStr[Reduce.REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
|
||||
" nested repeat operator " + PopularQStr[targetQNum] +
|
||||
" and " + PopularQStr[nestQNum] + " was replaced with '" +
|
||||
ReduceQStr[REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
|
||||
}
|
||||
}
|
||||
} // USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
|
||||
|
@ -40,7 +40,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
if (isRecursion()) states.append("RECURSION ");
|
||||
if (isCalled()) states.append("CALLED ");
|
||||
if (isAddrFixed()) states.append("ADDR_FIXED ");
|
||||
if (isNamedGroup()) states.append("NAMED_GROUP ");
|
||||
if (isNameRef()) states.append("NAME_REF ");
|
||||
if (isInRepeat()) states.append("IN_REPEAT ");
|
||||
if (isNestLevel()) states.append("NEST_LEVEL ");
|
||||
@ -57,10 +56,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_MIN_FIXED;
|
||||
}
|
||||
|
||||
public void clearMinFixed() {
|
||||
state &= ~NST_MIN_FIXED;
|
||||
}
|
||||
|
||||
public boolean isMaxFixed() {
|
||||
return (state & NST_MAX_FIXED) != 0;
|
||||
}
|
||||
@ -69,10 +64,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_MAX_FIXED;
|
||||
}
|
||||
|
||||
public void clearMaxFixed() {
|
||||
state &= ~NST_MAX_FIXED;
|
||||
}
|
||||
|
||||
public boolean isCLenFixed() {
|
||||
return (state & NST_CLEN_FIXED) != 0;
|
||||
}
|
||||
@ -81,10 +72,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_CLEN_FIXED;
|
||||
}
|
||||
|
||||
public void clearCLenFixed() {
|
||||
state &= ~NST_CLEN_FIXED;
|
||||
}
|
||||
|
||||
public boolean isMark1() {
|
||||
return (state & NST_MARK1) != 0;
|
||||
}
|
||||
@ -93,10 +80,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_MARK1;
|
||||
}
|
||||
|
||||
public void clearMark1() {
|
||||
state &= ~NST_MARK1;
|
||||
}
|
||||
|
||||
public boolean isMark2() {
|
||||
return (state & NST_MARK2) != 0;
|
||||
}
|
||||
@ -117,10 +100,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_MEM_BACKREFED;
|
||||
}
|
||||
|
||||
public void clearMemBackrefed() {
|
||||
state &= ~NST_MEM_BACKREFED;
|
||||
}
|
||||
|
||||
public boolean isStopBtSimpleRepeat() {
|
||||
return (state & NST_STOP_BT_SIMPLE_REPEAT) != 0;
|
||||
}
|
||||
@ -129,10 +108,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_STOP_BT_SIMPLE_REPEAT;
|
||||
}
|
||||
|
||||
public void clearStopBtSimpleRepeat() {
|
||||
state &= ~NST_STOP_BT_SIMPLE_REPEAT;
|
||||
}
|
||||
|
||||
public boolean isRecursion() {
|
||||
return (state & NST_RECURSION) != 0;
|
||||
}
|
||||
@ -141,10 +116,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_RECURSION;
|
||||
}
|
||||
|
||||
public void clearRecursion() {
|
||||
state &= ~NST_RECURSION;
|
||||
}
|
||||
|
||||
public boolean isCalled() {
|
||||
return (state & NST_CALLED) != 0;
|
||||
}
|
||||
@ -153,10 +124,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_CALLED;
|
||||
}
|
||||
|
||||
public void clearCAlled() {
|
||||
state &= ~NST_CALLED;
|
||||
}
|
||||
|
||||
public boolean isAddrFixed() {
|
||||
return (state & NST_ADDR_FIXED) != 0;
|
||||
}
|
||||
@ -165,22 +132,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_ADDR_FIXED;
|
||||
}
|
||||
|
||||
public void clearAddrFixed() {
|
||||
state &= ~NST_ADDR_FIXED;
|
||||
}
|
||||
|
||||
public boolean isNamedGroup() {
|
||||
return (state & NST_NAMED_GROUP) != 0;
|
||||
}
|
||||
|
||||
public void setNamedGroup() {
|
||||
state |= NST_NAMED_GROUP;
|
||||
}
|
||||
|
||||
public void clearNamedGroup() {
|
||||
state &= ~NST_NAMED_GROUP;
|
||||
}
|
||||
|
||||
public boolean isNameRef() {
|
||||
return (state & NST_NAME_REF) != 0;
|
||||
}
|
||||
@ -189,10 +140,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_NAME_REF;
|
||||
}
|
||||
|
||||
public void clearNameRef() {
|
||||
state &= ~NST_NAME_REF;
|
||||
}
|
||||
|
||||
public boolean isInRepeat() {
|
||||
return (state & NST_IN_REPEAT) != 0;
|
||||
}
|
||||
@ -201,10 +148,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_IN_REPEAT;
|
||||
}
|
||||
|
||||
public void clearInRepeat() {
|
||||
state &= ~NST_IN_REPEAT;
|
||||
}
|
||||
|
||||
public boolean isNestLevel() {
|
||||
return (state & NST_NEST_LEVEL) != 0;
|
||||
}
|
||||
@ -213,10 +156,6 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_NEST_LEVEL;
|
||||
}
|
||||
|
||||
public void clearNestLevel() {
|
||||
state &= ~NST_NEST_LEVEL;
|
||||
}
|
||||
|
||||
public boolean isByNumber() {
|
||||
return (state & NST_BY_NUMBER) != 0;
|
||||
}
|
||||
@ -225,8 +164,4 @@ public abstract class StateNode extends Node implements NodeStatus {
|
||||
state |= NST_BY_NUMBER;
|
||||
}
|
||||
|
||||
public void clearByNumber() {
|
||||
state &= ~NST_BY_NUMBER;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.bench;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.Option;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.Regex;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
|
||||
|
||||
public abstract class AbstractBench {
|
||||
protected void bench(String _reg, String _str, int warmup, int times) throws Exception {
|
||||
char[] reg = _reg.toCharArray();
|
||||
char[] str = _str.toCharArray();
|
||||
|
||||
Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
|
||||
|
||||
System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
|
||||
|
||||
for(int j=0;j<warmup;j++) {
|
||||
long before = System.currentTimeMillis();
|
||||
for(int i = 0; i < times; i++) {
|
||||
p.matcher(str, 0, str.length).search(0, str.length, Option.NONE);
|
||||
}
|
||||
long time = System.currentTimeMillis() - before;
|
||||
System.err.println(": " + time + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
protected void benchBestOf(String _reg, String _str, int warmup, int times) throws Exception {
|
||||
char[] reg = _reg.toCharArray();
|
||||
char[] str = _str.toCharArray();
|
||||
|
||||
Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
|
||||
|
||||
System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
|
||||
|
||||
long best = Long.MAX_VALUE;
|
||||
|
||||
for(int j=0;j<warmup;j++) {
|
||||
long before = System.currentTimeMillis();
|
||||
for(int i = 0; i < times; i++) {
|
||||
p.matcher(str, 0, str.length).search(0, str.length, Option.NONE);
|
||||
}
|
||||
long time = System.currentTimeMillis() - before;
|
||||
if(time < best) {
|
||||
best = time;
|
||||
}
|
||||
System.err.print(".");
|
||||
}
|
||||
System.err.println(": " + best + "ms");
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.bench;
|
||||
|
||||
public class BenchGreedyBacktrack extends AbstractBench {
|
||||
public static void main(String[] args) throws Exception {
|
||||
new BenchGreedyBacktrack().bench(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,1000000);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.bench;
|
||||
|
||||
public class BenchRailsRegs extends AbstractBench {
|
||||
public static void main(String[] args) throws Exception {
|
||||
final String[][] regexps = {{"a.*?[b-z]{2,4}aaaaaa","afdgdsgderaabxxaaaaaaaaaaaaaaaaaaaaaaaa"},
|
||||
{"://","/shop/viewCategory.shtml?category=DOGS"},
|
||||
{"^\\w+\\://[^/]+(/.*|$)$","/shop/viewCategory.shtml?category=DOGS"},
|
||||
{"\\A/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A/shop/signonForm\\.shtml/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A/shop/newAccountForm\\.shtml/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A/shop/newAccount\\.shtml/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A/shop/viewCart\\.shtml/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A/shop/index\\.shtml/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A/shop/viewCategory\\.shtml/?\\Z","/shop/viewCategory.shtml"},
|
||||
{"\\A(?:::)?([A-Z]\\w*(?:::[A-Z]\\w*)*)\\z","CategoriesController"},
|
||||
{"\\Ainsert","SELECT * FROM sessions WHERE (session_id = '1b341ffe23b5298676d535fcabd3d0d7') LIMIT 1"},
|
||||
{"\\A\\(?\\s*(select|show)","SELECT * FROM sessions WHERE (session_id = '1b341ffe23b5298676d535fcabd3d0d7') LIMIT 1"},
|
||||
{".*?\n","1b341ffe23b5298676d535fcabd3d0d7"},
|
||||
{"^find_(all_by|by)_([_a-zA-Z]\\w*)$","find_by_string_id"},
|
||||
{"\\.rjs$","categories/show.rhtml"},
|
||||
{"^[-a-z]+://","petstore.css"},
|
||||
{"^get$",""},
|
||||
{"^post$",""},
|
||||
{"^[^:]+","www.example.com"},
|
||||
{"(=|\\?|_before_type_cast)$", "updated_on"},
|
||||
{"^(.*?)=(.*?);","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/"}};
|
||||
for(String[] reg : regexps) {
|
||||
new BenchRailsRegs().benchBestOf(reg[0],reg[1],10,1000000);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.bench;
|
||||
|
||||
public class BenchSeveralRegexps extends AbstractBench {
|
||||
public static void main(String[] args) throws Exception {
|
||||
int BASE = 1000000;
|
||||
|
||||
new BenchSeveralRegexps().benchBestOf("a"," a",10,4*BASE);
|
||||
|
||||
new BenchSeveralRegexps().benchBestOf(".*?=","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,BASE);
|
||||
|
||||
new BenchSeveralRegexps().benchBestOf("^(.*?)=(.*?);","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,BASE);
|
||||
|
||||
new BenchSeveralRegexps().benchBestOf(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,4*BASE);
|
||||
|
||||
new BenchSeveralRegexps().benchBestOf(".*=","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,4*BASE);
|
||||
}
|
||||
}
|
@ -19,8 +19,6 @@
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.constants;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.Config;
|
||||
|
||||
public interface OPCode {
|
||||
final int FINISH = 0; /* matching process terminator (no more alternative) */
|
||||
final int END = 1; /* pattern code terminator (success end) */
|
||||
@ -151,237 +149,4 @@ public interface OPCode {
|
||||
final int EXACT1_IC_SB = 105; /* single byte, N = 1, ignore case */
|
||||
final int EXACTN_IC_SB = 106; /* single byte, ignore case */
|
||||
|
||||
|
||||
public final String OpCodeNames[] = Config.DEBUG_COMPILE ? new String[] {
|
||||
"finish", /*OP_FINISH*/
|
||||
"end", /*OP_END*/
|
||||
"exact1", /*OP_EXACT1*/
|
||||
"exact2", /*OP_EXACT2*/
|
||||
"exact3", /*OP_EXACT3*/
|
||||
"exact4", /*OP_EXACT4*/
|
||||
"exact5", /*OP_EXACT5*/
|
||||
"exactn", /*OP_EXACTN*/
|
||||
"exactmb2-n1", /*OP_EXACTMB2N1*/
|
||||
"exactmb2-n2", /*OP_EXACTMB2N2*/
|
||||
"exactmb2-n3", /*OP_EXACTMB2N3*/
|
||||
"exactmb2-n", /*OP_EXACTMB2N*/
|
||||
"exactmb3n", /*OP_EXACTMB3N*/
|
||||
"exactmbn", /*OP_EXACTMBN*/
|
||||
"exact1-ic", /*OP_EXACT1_IC*/
|
||||
"exactn-ic", /*OP_EXACTN_IC*/
|
||||
"cclass", /*OP_CCLASS*/
|
||||
"cclass-mb", /*OP_CCLASS_MB*/
|
||||
"cclass-mix", /*OP_CCLASS_MIX*/
|
||||
"cclass-not", /*OP_CCLASS_NOT*/
|
||||
"cclass-mb-not", /*OP_CCLASS_MB_NOT*/
|
||||
"cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
|
||||
"cclass-node", /*OP_CCLASS_NODE*/
|
||||
"anychar", /*OP_ANYCHAR*/
|
||||
"anychar-ml", /*OP_ANYCHAR_ML*/
|
||||
"anychar*", /*OP_ANYCHAR_STAR*/
|
||||
"anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
|
||||
"anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
"anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
"word", /*OP_WORD*/
|
||||
"not-word", /*OP_NOT_WORD*/
|
||||
"word-bound", /*OP_WORD_BOUND*/
|
||||
"not-word-bound", /*OP_NOT_WORD_BOUND*/
|
||||
"word-begin", /*OP_WORD_BEGIN*/
|
||||
"word-end", /*OP_WORD_END*/
|
||||
"begin-buf", /*OP_BEGIN_BUF*/
|
||||
"end-buf", /*OP_END_BUF*/
|
||||
"begin-line", /*OP_BEGIN_LINE*/
|
||||
"end-line", /*OP_END_LINE*/
|
||||
"semi-end-buf", /*OP_SEMI_END_BUF*/
|
||||
"begin-position", /*OP_BEGIN_POSITION*/
|
||||
"backref1", /*OP_BACKREF1*/
|
||||
"backref2", /*OP_BACKREF2*/
|
||||
"backrefn", /*OP_BACKREFN*/
|
||||
"backrefn-ic", /*OP_BACKREFN_IC*/
|
||||
"backref_multi", /*OP_BACKREF_MULTI*/
|
||||
"backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
|
||||
"backref_at_level", /*OP_BACKREF_AT_LEVEL*/
|
||||
"mem-start", /*OP_MEMORY_START*/
|
||||
"mem-start-push", /*OP_MEMORY_START_PUSH*/
|
||||
"mem-end-push", /*OP_MEMORY_END_PUSH*/
|
||||
"mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
|
||||
"mem-end", /*OP_MEMORY_END*/
|
||||
"mem-end-rec", /*OP_MEMORY_END_REC*/
|
||||
"fail", /*OP_FAIL*/
|
||||
"jump", /*OP_JUMP*/
|
||||
"push", /*OP_PUSH*/
|
||||
"pop", /*OP_POP*/
|
||||
"push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
|
||||
"push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
|
||||
"repeat", /*OP_REPEAT*/
|
||||
"repeat-ng", /*OP_REPEAT_NG*/
|
||||
"repeat-inc", /*OP_REPEAT_INC*/
|
||||
"repeat-inc-ng", /*OP_REPEAT_INC_NG*/
|
||||
"repeat-inc-sg", /*OP_REPEAT_INC_SG*/
|
||||
"repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
|
||||
"null-check-start", /*OP_NULL_CHECK_START*/
|
||||
"null-check-end", /*OP_NULL_CHECK_END*/
|
||||
"null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
|
||||
"null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
|
||||
"push-pos", /*OP_PUSH_POS*/
|
||||
"pop-pos", /*OP_POP_POS*/
|
||||
"push-pos-not", /*OP_PUSH_POS_NOT*/
|
||||
"fail-pos", /*OP_FAIL_POS*/
|
||||
"push-stop-bt", /*OP_PUSH_STOP_BT*/
|
||||
"pop-stop-bt", /*OP_POP_STOP_BT*/
|
||||
"look-behind", /*OP_LOOK_BEHIND*/
|
||||
"push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
|
||||
"fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
|
||||
"call", /*OP_CALL*/
|
||||
"return", /*OP_RETURN*/
|
||||
"state-check-push", /*OP_STATE_CHECK_PUSH*/
|
||||
"state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
|
||||
"state-check", /*OP_STATE_CHECK*/
|
||||
"state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
"state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
"set-option-push", /*OP_SET_OPTION_PUSH*/
|
||||
"set-option", /*OP_SET_OPTION*/
|
||||
|
||||
// single byte versions
|
||||
"anychar-sb", /*OP_ANYCHAR*/
|
||||
"anychar-ml-sb", /*OP_ANYCHAR_ML*/
|
||||
"anychar*-sb", /*OP_ANYCHAR_STAR*/
|
||||
"anychar-ml*-sb", /*OP_ANYCHAR_ML_STAR*/
|
||||
"anychar*-peek-next-sb", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
"anychar-ml*-peek-next-sb", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
"state-check-anychar*-sb", /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
"state-check-anychar-ml*-sb", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
|
||||
"cclass-sb", /*OP_CCLASS*/
|
||||
"cclass-not-sb", /*OP_CCLASS_NOT*/
|
||||
|
||||
"word-sb", /*OP_WORD*/
|
||||
"not-word-sb", /*OP_NOT_WORD*/
|
||||
"word-bound-sb", /*OP_WORD_BOUND*/
|
||||
"not-word-bound-sb", /*OP_NOT_WORD_BOUND*/
|
||||
"word-begin-sb", /*OP_WORD_BEGIN*/
|
||||
"word-end-sb", /*OP_WORD_END*/
|
||||
|
||||
"look-behind-sb", /*OP_LOOK_BEHIND*/
|
||||
|
||||
"exact1-ic-sb", /*OP_EXACT1_IC*/
|
||||
"exactn-ic-sb", /*OP_EXACTN_IC*/
|
||||
|
||||
} : null;
|
||||
|
||||
public final int OpCodeArgTypes[] = Config.DEBUG_COMPILE ? new int[] {
|
||||
Arguments.NON, /*OP_FINISH*/
|
||||
Arguments.NON, /*OP_END*/
|
||||
Arguments.SPECIAL, /*OP_EXACT1*/
|
||||
Arguments.SPECIAL, /*OP_EXACT2*/
|
||||
Arguments.SPECIAL, /*OP_EXACT3*/
|
||||
Arguments.SPECIAL, /*OP_EXACT4*/
|
||||
Arguments.SPECIAL, /*OP_EXACT5*/
|
||||
Arguments.SPECIAL, /*OP_EXACTN*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N1*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N2*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N3*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB2N*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMB3N*/
|
||||
Arguments.SPECIAL, /*OP_EXACTMBN*/
|
||||
Arguments.SPECIAL, /*OP_EXACT1_IC*/
|
||||
Arguments.SPECIAL, /*OP_EXACTN_IC*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MB*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MIX*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_NOT*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_NODE*/
|
||||
Arguments.NON, /*OP_ANYCHAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML*/
|
||||
Arguments.NON, /*OP_ANYCHAR_STAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
Arguments.NON, /*OP_WORD*/
|
||||
Arguments.NON, /*OP_NOT_WORD*/
|
||||
Arguments.NON, /*OP_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_NOT_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_WORD_BEGIN*/
|
||||
Arguments.NON, /*OP_WORD_END*/
|
||||
Arguments.NON, /*OP_BEGIN_BUF*/
|
||||
Arguments.NON, /*OP_END_BUF*/
|
||||
Arguments.NON, /*OP_BEGIN_LINE*/
|
||||
Arguments.NON, /*OP_END_LINE*/
|
||||
Arguments.NON, /*OP_SEMI_END_BUF*/
|
||||
Arguments.NON, /*OP_BEGIN_POSITION*/
|
||||
Arguments.NON, /*OP_BACKREF1*/
|
||||
Arguments.NON, /*OP_BACKREF2*/
|
||||
Arguments.MEMNUM, /*OP_BACKREFN*/
|
||||
Arguments.SPECIAL, /*OP_BACKREFN_IC*/
|
||||
Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
|
||||
Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
|
||||
Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_START*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END*/
|
||||
Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
|
||||
Arguments.NON, /*OP_FAIL*/
|
||||
Arguments.RELADDR, /*OP_JUMP*/
|
||||
Arguments.RELADDR, /*OP_PUSH*/
|
||||
Arguments.NON, /*OP_POP*/
|
||||
Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
|
||||
Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
|
||||
Arguments.SPECIAL, /*OP_REPEAT*/
|
||||
Arguments.SPECIAL, /*OP_REPEAT_NG*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
|
||||
Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
|
||||
Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
|
||||
Arguments.NON, /*OP_PUSH_POS*/
|
||||
Arguments.NON, /*OP_POP_POS*/
|
||||
Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
|
||||
Arguments.NON, /*OP_FAIL_POS*/
|
||||
Arguments.NON, /*OP_PUSH_STOP_BT*/
|
||||
Arguments.NON, /*OP_POP_STOP_BT*/
|
||||
Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
|
||||
Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
|
||||
Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
|
||||
Arguments.ABSADDR, /*OP_CALL*/
|
||||
Arguments.NON, /*OP_RETURN*/
|
||||
Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
|
||||
Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
|
||||
Arguments.OPTION, /*OP_SET_OPTION*/
|
||||
|
||||
// single byte versions
|
||||
Arguments.NON, /*OP_ANYCHAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML*/
|
||||
Arguments.NON, /*OP_ANYCHAR_STAR*/
|
||||
Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
|
||||
Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
|
||||
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
|
||||
|
||||
Arguments.SPECIAL, /*OP_CCLASS*/
|
||||
Arguments.SPECIAL, /*OP_CCLASS_NOT*/
|
||||
|
||||
Arguments.NON, /*OP_WORD*/
|
||||
Arguments.NON, /*OP_NOT_WORD*/
|
||||
Arguments.NON, /*OP_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_NOT_WORD_BOUND*/
|
||||
Arguments.NON, /*OP_WORD_BEGIN*/
|
||||
Arguments.NON, /*OP_WORD_END*/
|
||||
|
||||
Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
|
||||
|
||||
Arguments.SPECIAL, /*OP_EXACT1_IC*/
|
||||
Arguments.SPECIAL, /*OP_EXACTN_IC*/
|
||||
} : null;
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.constants;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.A;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.AQ;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.ASIS;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.DEL;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.PQ_Q;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.P_QQ;
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.QQ;
|
||||
|
||||
public interface Reduce {
|
||||
|
||||
enum ReduceType {
|
||||
ASIS, /* as is */
|
||||
DEL, /* delete parent */
|
||||
A, /* to '*' */
|
||||
AQ, /* to '*?' */
|
||||
QQ, /* to '??' */
|
||||
P_QQ, /* to '+)??' */
|
||||
PQ_Q, /* to '+?)?' */
|
||||
}
|
||||
|
||||
final ReduceType[][]REDUCE_TABLE = {
|
||||
{DEL, A, A, QQ, AQ, ASIS}, /* '?' */
|
||||
{DEL, DEL, DEL, P_QQ, P_QQ, DEL}, /* '*' */
|
||||
{A, A, DEL, ASIS, P_QQ, DEL}, /* '+' */
|
||||
{DEL, AQ, AQ, DEL, AQ, AQ}, /* '??' */
|
||||
{DEL, DEL, DEL, DEL, DEL, DEL}, /* '*?' */
|
||||
{ASIS, PQ_Q, DEL, AQ, AQ, DEL} /* '+?' */
|
||||
};
|
||||
|
||||
|
||||
final String PopularQStr[] = new String[] {
|
||||
"?", "*", "+", "??", "*?", "+?"
|
||||
};
|
||||
|
||||
String ReduceQStr[]= new String[] {
|
||||
"", "", "*", "*?", "??", "+ and ??", "+? and ?"
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
|
||||
|
||||
public class AsciiTables {
|
||||
|
||||
public static final short AsciiCtypeTable[] = {
|
||||
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
|
||||
0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008,
|
||||
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
|
||||
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
|
||||
0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
|
||||
0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
|
||||
0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0,
|
||||
0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
|
||||
0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2,
|
||||
0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
|
||||
0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
|
||||
0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0,
|
||||
0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2,
|
||||
0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
|
||||
0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
|
||||
0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
public static final byte ToLowerCaseTable[] = {
|
||||
(byte)'\000', (byte)'\001', (byte)'\002', (byte)'\003', (byte)'\004', (byte)'\005', (byte)'\006', (byte)'\007',
|
||||
(byte)'\010', (byte)'\011', (byte)'\012', (byte)'\013', (byte)'\014', (byte)'\015', (byte)'\016', (byte)'\017',
|
||||
(byte)'\020', (byte)'\021', (byte)'\022', (byte)'\023', (byte)'\024', (byte)'\025', (byte)'\026', (byte)'\027',
|
||||
(byte)'\030', (byte)'\031', (byte)'\032', (byte)'\033', (byte)'\034', (byte)'\035', (byte)'\036', (byte)'\037',
|
||||
(byte)'\040', (byte)'\041', (byte)'\042', (byte)'\043', (byte)'\044', (byte)'\045', (byte)'\046', (byte)'\047',
|
||||
(byte)'\050', (byte)'\051', (byte)'\052', (byte)'\053', (byte)'\054', (byte)'\055', (byte)'\056', (byte)'\057',
|
||||
(byte)'\060', (byte)'\061', (byte)'\062', (byte)'\063', (byte)'\064', (byte)'\065', (byte)'\066', (byte)'\067',
|
||||
(byte)'\070', (byte)'\071', (byte)'\072', (byte)'\073', (byte)'\074', (byte)'\075', (byte)'\076', (byte)'\077',
|
||||
(byte)'\100', (byte)'\141', (byte)'\142', (byte)'\143', (byte)'\144', (byte)'\145', (byte)'\146', (byte)'\147',
|
||||
(byte)'\150', (byte)'\151', (byte)'\152', (byte)'\153', (byte)'\154', (byte)'\155', (byte)'\156', (byte)'\157',
|
||||
(byte)'\160', (byte)'\161', (byte)'\162', (byte)'\163', (byte)'\164', (byte)'\165', (byte)'\166', (byte)'\167',
|
||||
(byte)'\170', (byte)'\171', (byte)'\172', (byte)'\133', (byte)'\134', (byte)'\135', (byte)'\136', (byte)'\137',
|
||||
(byte)'\140', (byte)'\141', (byte)'\142', (byte)'\143', (byte)'\144', (byte)'\145', (byte)'\146', (byte)'\147',
|
||||
(byte)'\150', (byte)'\151', (byte)'\152', (byte)'\153', (byte)'\154', (byte)'\155', (byte)'\156', (byte)'\157',
|
||||
(byte)'\160', (byte)'\161', (byte)'\162', (byte)'\163', (byte)'\164', (byte)'\165', (byte)'\166', (byte)'\167',
|
||||
(byte)'\170', (byte)'\171', (byte)'\172', (byte)'\173', (byte)'\174', (byte)'\175', (byte)'\176', (byte)'\177',
|
||||
(byte)'\200', (byte)'\201', (byte)'\202', (byte)'\203', (byte)'\204', (byte)'\205', (byte)'\206', (byte)'\207',
|
||||
(byte)'\210', (byte)'\211', (byte)'\212', (byte)'\213', (byte)'\214', (byte)'\215', (byte)'\216', (byte)'\217',
|
||||
(byte)'\220', (byte)'\221', (byte)'\222', (byte)'\223', (byte)'\224', (byte)'\225', (byte)'\226', (byte)'\227',
|
||||
(byte)'\230', (byte)'\231', (byte)'\232', (byte)'\233', (byte)'\234', (byte)'\235', (byte)'\236', (byte)'\237',
|
||||
(byte)'\240', (byte)'\241', (byte)'\242', (byte)'\243', (byte)'\244', (byte)'\245', (byte)'\246', (byte)'\247',
|
||||
(byte)'\250', (byte)'\251', (byte)'\252', (byte)'\253', (byte)'\254', (byte)'\255', (byte)'\256', (byte)'\257',
|
||||
(byte)'\260', (byte)'\261', (byte)'\262', (byte)'\263', (byte)'\264', (byte)'\265', (byte)'\266', (byte)'\267',
|
||||
(byte)'\270', (byte)'\271', (byte)'\272', (byte)'\273', (byte)'\274', (byte)'\275', (byte)'\276', (byte)'\277',
|
||||
(byte)'\300', (byte)'\301', (byte)'\302', (byte)'\303', (byte)'\304', (byte)'\305', (byte)'\306', (byte)'\307',
|
||||
(byte)'\310', (byte)'\311', (byte)'\312', (byte)'\313', (byte)'\314', (byte)'\315', (byte)'\316', (byte)'\317',
|
||||
(byte)'\320', (byte)'\321', (byte)'\322', (byte)'\323', (byte)'\324', (byte)'\325', (byte)'\326', (byte)'\327',
|
||||
(byte)'\330', (byte)'\331', (byte)'\332', (byte)'\333', (byte)'\334', (byte)'\335', (byte)'\336', (byte)'\337',
|
||||
(byte)'\340', (byte)'\341', (byte)'\342', (byte)'\343', (byte)'\344', (byte)'\345', (byte)'\346', (byte)'\347',
|
||||
(byte)'\350', (byte)'\351', (byte)'\352', (byte)'\353', (byte)'\354', (byte)'\355', (byte)'\356', (byte)'\357',
|
||||
(byte)'\360', (byte)'\361', (byte)'\362', (byte)'\363', (byte)'\364', (byte)'\365', (byte)'\366', (byte)'\367',
|
||||
(byte)'\370', (byte)'\371', (byte)'\372', (byte)'\373', (byte)'\374', (byte)'\375', (byte)'\376', (byte)'\377',
|
||||
};
|
||||
|
||||
public static final byte ToUpperCaseTable[] = {
|
||||
(byte)'\000', (byte)'\001', (byte)'\002', (byte)'\003', (byte)'\004', (byte)'\005', (byte)'\006', (byte)'\007',
|
||||
(byte)'\010', (byte)'\011', (byte)'\012', (byte)'\013', (byte)'\014', (byte)'\015', (byte)'\016', (byte)'\017',
|
||||
(byte)'\020', (byte)'\021', (byte)'\022', (byte)'\023', (byte)'\024', (byte)'\025', (byte)'\026', (byte)'\027',
|
||||
(byte)'\030', (byte)'\031', (byte)'\032', (byte)'\033', (byte)'\034', (byte)'\035', (byte)'\036', (byte)'\037',
|
||||
(byte)'\040', (byte)'\041', (byte)'\042', (byte)'\043', (byte)'\044', (byte)'\045', (byte)'\046', (byte)'\047',
|
||||
(byte)'\050', (byte)'\051', (byte)'\052', (byte)'\053', (byte)'\054', (byte)'\055', (byte)'\056', (byte)'\057',
|
||||
(byte)'\060', (byte)'\061', (byte)'\062', (byte)'\063', (byte)'\064', (byte)'\065', (byte)'\066', (byte)'\067',
|
||||
(byte)'\070', (byte)'\071', (byte)'\072', (byte)'\073', (byte)'\074', (byte)'\075', (byte)'\076', (byte)'\077',
|
||||
(byte)'\100', (byte)'\101', (byte)'\102', (byte)'\103', (byte)'\104', (byte)'\105', (byte)'\106', (byte)'\107',
|
||||
(byte)'\110', (byte)'\111', (byte)'\112', (byte)'\113', (byte)'\114', (byte)'\115', (byte)'\116', (byte)'\117',
|
||||
(byte)'\120', (byte)'\121', (byte)'\122', (byte)'\123', (byte)'\124', (byte)'\125', (byte)'\126', (byte)'\127',
|
||||
(byte)'\130', (byte)'\131', (byte)'\132', (byte)'\133', (byte)'\134', (byte)'\135', (byte)'\136', (byte)'\137',
|
||||
(byte)'\140', (byte)'\101', (byte)'\102', (byte)'\103', (byte)'\104', (byte)'\105', (byte)'\106', (byte)'\107',
|
||||
(byte)'\110', (byte)'\111', (byte)'\112', (byte)'\113', (byte)'\114', (byte)'\115', (byte)'\116', (byte)'\117',
|
||||
(byte)'\120', (byte)'\121', (byte)'\122', (byte)'\123', (byte)'\124', (byte)'\125', (byte)'\126', (byte)'\127',
|
||||
(byte)'\130', (byte)'\131', (byte)'\132', (byte)'\173', (byte)'\174', (byte)'\175', (byte)'\176', (byte)'\177',
|
||||
(byte)'\200', (byte)'\201', (byte)'\202', (byte)'\203', (byte)'\204', (byte)'\205', (byte)'\206', (byte)'\207',
|
||||
(byte)'\210', (byte)'\211', (byte)'\212', (byte)'\213', (byte)'\214', (byte)'\215', (byte)'\216', (byte)'\217',
|
||||
(byte)'\220', (byte)'\221', (byte)'\222', (byte)'\223', (byte)'\224', (byte)'\225', (byte)'\226', (byte)'\227',
|
||||
(byte)'\230', (byte)'\231', (byte)'\232', (byte)'\233', (byte)'\234', (byte)'\235', (byte)'\236', (byte)'\237',
|
||||
(byte)'\240', (byte)'\241', (byte)'\242', (byte)'\243', (byte)'\244', (byte)'\245', (byte)'\246', (byte)'\247',
|
||||
(byte)'\250', (byte)'\251', (byte)'\252', (byte)'\253', (byte)'\254', (byte)'\255', (byte)'\256', (byte)'\257',
|
||||
(byte)'\260', (byte)'\261', (byte)'\262', (byte)'\263', (byte)'\264', (byte)'\265', (byte)'\266', (byte)'\267',
|
||||
(byte)'\270', (byte)'\271', (byte)'\272', (byte)'\273', (byte)'\274', (byte)'\275', (byte)'\276', (byte)'\277',
|
||||
(byte)'\300', (byte)'\301', (byte)'\302', (byte)'\303', (byte)'\304', (byte)'\305', (byte)'\306', (byte)'\307',
|
||||
(byte)'\310', (byte)'\311', (byte)'\312', (byte)'\313', (byte)'\314', (byte)'\315', (byte)'\316', (byte)'\317',
|
||||
(byte)'\320', (byte)'\321', (byte)'\322', (byte)'\323', (byte)'\324', (byte)'\325', (byte)'\326', (byte)'\327',
|
||||
(byte)'\330', (byte)'\331', (byte)'\332', (byte)'\333', (byte)'\334', (byte)'\335', (byte)'\336', (byte)'\337',
|
||||
(byte)'\340', (byte)'\341', (byte)'\342', (byte)'\343', (byte)'\344', (byte)'\345', (byte)'\346', (byte)'\347',
|
||||
(byte)'\350', (byte)'\351', (byte)'\352', (byte)'\353', (byte)'\354', (byte)'\355', (byte)'\356', (byte)'\357',
|
||||
(byte)'\360', (byte)'\361', (byte)'\362', (byte)'\363', (byte)'\364', (byte)'\365', (byte)'\366', (byte)'\367',
|
||||
(byte)'\370', (byte)'\371', (byte)'\372', (byte)'\373', (byte)'\374', (byte)'\375', (byte)'\376', (byte)'\377',
|
||||
};
|
||||
|
||||
public static final int LowerMap[][] = {
|
||||
{0x41, 0x61},
|
||||
{0x42, 0x62},
|
||||
{0x43, 0x63},
|
||||
{0x44, 0x64},
|
||||
{0x45, 0x65},
|
||||
{0x46, 0x66},
|
||||
{0x47, 0x67},
|
||||
{0x48, 0x68},
|
||||
{0x49, 0x69},
|
||||
{0x4a, 0x6a},
|
||||
{0x4b, 0x6b},
|
||||
{0x4c, 0x6c},
|
||||
{0x4d, 0x6d},
|
||||
{0x4e, 0x6e},
|
||||
{0x4f, 0x6f},
|
||||
{0x50, 0x70},
|
||||
{0x51, 0x71},
|
||||
{0x52, 0x72},
|
||||
{0x53, 0x73},
|
||||
{0x54, 0x74},
|
||||
{0x55, 0x75},
|
||||
{0x56, 0x76},
|
||||
{0x57, 0x77},
|
||||
{0x58, 0x78},
|
||||
{0x59, 0x79},
|
||||
{0x5a, 0x7a}
|
||||
};
|
||||
}
|
@ -30,6 +30,5 @@ public final class ObjPtr<T> {
|
||||
|
||||
public T p;
|
||||
|
||||
static final ObjPtr<Void> NULL = new ObjPtr<Void>();
|
||||
}
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS".toCharArray(), WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
|
||||
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class PosixBracket {
|
||||
|
||||
public static final char[][] PBSNamesLower = {
|
||||
"alnum".toCharArray(),
|
||||
"alpha".toCharArray(),
|
||||
"blank".toCharArray(),
|
||||
"cntrl".toCharArray(),
|
||||
"digit".toCharArray(),
|
||||
"graph".toCharArray(),
|
||||
"lower".toCharArray(),
|
||||
"print".toCharArray(),
|
||||
"punct".toCharArray(),
|
||||
"space".toCharArray(),
|
||||
"upper".toCharArray(),
|
||||
"xdigit".toCharArray(),
|
||||
"ascii".toCharArray(),
|
||||
"word".toCharArray()
|
||||
};
|
||||
|
||||
public static final int PBSValues[] = {
|
||||
CharacterType.ALNUM,
|
||||
CharacterType.ALPHA,
|
||||
CharacterType.BLANK,
|
||||
CharacterType.CNTRL,
|
||||
CharacterType.DIGIT,
|
||||
CharacterType.GRAPH,
|
||||
CharacterType.LOWER,
|
||||
CharacterType.PRINT,
|
||||
CharacterType.PUNCT,
|
||||
CharacterType.SPACE,
|
||||
CharacterType.UPPER,
|
||||
CharacterType.XDIGIT,
|
||||
CharacterType.ASCII,
|
||||
CharacterType.WORD,
|
||||
};
|
||||
|
||||
public static int propertyNameToCType(String name) {
|
||||
name = name.toLowerCase();
|
||||
if (!PBSTableUpper.containsKey(name)) {
|
||||
throw new JOniException(ErrorMessages.ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
|
||||
}
|
||||
return PBSTableUpper.get(name);
|
||||
}
|
||||
|
||||
private static final HashMap<String,Integer> PBSTableUpper = new HashMap<String,Integer>();
|
||||
|
||||
static {
|
||||
for (int i=0; i<PBSValues.length; i++) PBSTableUpper.put(new String(PBSNamesLower[i]), PBSValues[i]);
|
||||
}
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
|
||||
|
||||
public final class Ptr {
|
||||
public Ptr() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public Ptr(int p) {
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
public int p;
|
||||
|
||||
public static final Ptr NULL = new Ptr(0);
|
||||
}
|
||||
|
@ -22,28 +22,16 @@ package jdk.nashorn.internal.runtime.regexp.joni.exception;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.Config;
|
||||
|
||||
public interface ErrorMessages {
|
||||
final String MISMATCH = "mismatch";
|
||||
final String NO_SUPPORT_CONFIG = "no support in this configuration";
|
||||
|
||||
/* from jcodings */
|
||||
final String ERR_INVALID_CHAR_PROPERTY_NAME = "invalid character property name <%n>";
|
||||
final String ERR_INVALID_CODE_POINT_VALUE = "invalid code point value";
|
||||
final String ERR_TOO_BIG_WIDE_CHAR_VALUE = "too big wide-char value";
|
||||
final String ERR_TOO_LONG_WIDE_CHAR_VALUE = "too long wide-char value";
|
||||
|
||||
/* internal error */
|
||||
final String ERR_MEMORY = "fail to memory allocation";
|
||||
final String ERR_MATCH_STACK_LIMIT_OVER = "match-stack limit over";
|
||||
final String ERR_TYPE_BUG = "undefined type (bug)";
|
||||
final String ERR_PARSER_BUG = "internal parser error (bug)";
|
||||
final String ERR_STACK_BUG = "stack error (bug)";
|
||||
final String ERR_UNDEFINED_BYTECODE = "undefined bytecode (bug)";
|
||||
final String ERR_UNEXPECTED_BYTECODE = "unexpected bytecode (bug)";
|
||||
final String ERR_DEFAULT_ENCODING_IS_NOT_SETTED = "default multibyte-encoding is not setted";
|
||||
final String ERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR = "can't convert to wide-char on specified multibyte-encoding";
|
||||
|
||||
/* general error */
|
||||
final String ERR_INVALID_ARGUMENT = "invalid argument";
|
||||
|
||||
/* syntax error */
|
||||
final String ERR_END_PATTERN_AT_LEFT_BRACE = "end pattern at left brace";
|
||||
@ -56,11 +44,9 @@ public interface ErrorMessages {
|
||||
final String ERR_META_CODE_SYNTAX = "invalid meta-code syntax";
|
||||
final String ERR_CONTROL_CODE_SYNTAX = "invalid control-code syntax";
|
||||
final String ERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE = "char-class value at end of range";
|
||||
final String ERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE = "char-class value at start of range";
|
||||
final String ERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS = "unmatched range specifier in char-class";
|
||||
final String ERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED = "target of repeat operator is not specified";
|
||||
final String ERR_TARGET_OF_REPEAT_OPERATOR_INVALID = "target of repeat operator is invalid";
|
||||
final String ERR_NESTED_REPEAT_OPERATOR = "nested repeat operator";
|
||||
final String ERR_UNMATCHED_CLOSE_PARENTHESIS = "unmatched close parenthesis";
|
||||
final String ERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS = "end pattern with unmatched parenthesis";
|
||||
final String ERR_END_PATTERN_IN_GROUP = "end pattern in group";
|
||||
@ -74,25 +60,14 @@ public interface ErrorMessages {
|
||||
final String ERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE = "too big number for repeat range";
|
||||
final String ERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE = "upper is smaller than lower in repeat range";
|
||||
final String ERR_EMPTY_RANGE_IN_CHAR_CLASS = "empty range in char class";
|
||||
final String ERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE = "mismatch multibyte code length in char-class range";
|
||||
final String ERR_TOO_MANY_MULTI_BYTE_RANGES = "too many multibyte code ranges are specified";
|
||||
final String ERR_TOO_SHORT_MULTI_BYTE_STRING = "too short multibyte code string";
|
||||
final String ERR_TOO_BIG_BACKREF_NUMBER = "too big backref number";
|
||||
final String ERR_INVALID_BACKREF = Config.USE_NAMED_GROUP ? "invalid backref number/name" : "invalid backref number";
|
||||
final String ERR_INVALID_BACKREF = "invalid backref number";
|
||||
final String ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED = "numbered backref/call is not allowed. (use name)";
|
||||
final String ERR_INVALID_WIDE_CHAR_VALUE = "invalid wide-char value";
|
||||
final String ERR_EMPTY_GROUP_NAME = "group name is empty";
|
||||
final String ERR_INVALID_GROUP_NAME = "invalid group name <%n>";
|
||||
final String ERR_INVALID_CHAR_IN_GROUP_NAME = Config.USE_NAMED_GROUP ? "invalid char in group name <%n>" : "invalid char in group number <%n>";
|
||||
final String ERR_UNDEFINED_NAME_REFERENCE = "undefined name <%n> reference";
|
||||
final String ERR_UNDEFINED_GROUP_REFERENCE = "undefined group <%n> reference";
|
||||
final String ERR_MULTIPLEX_DEFINED_NAME = "multiplex defined name <%n>";
|
||||
final String ERR_MULTIPLEX_DEFINITION_NAME_CALL = "multiplex definition name <%n> call";
|
||||
final String ERR_NEVER_ENDING_RECURSION = "never ending recursion";
|
||||
final String ERR_INVALID_CHAR_IN_GROUP_NAME = "invalid char in group number <%n>";
|
||||
final String ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY = "group number is too big for capture history";
|
||||
final String ERR_NOT_SUPPORTED_ENCODING_COMBINATION = "not supported encoding combination";
|
||||
final String ERR_INVALID_COMBINATION_OF_OPTIONS = "invalid combination of options";
|
||||
final String ERR_OVER_THREAD_PASS_LIMIT_COUNT = "over thread pass limit count";
|
||||
final String ERR_TOO_BIG_SB_CHAR_VALUE = "too big singlebyte char value";
|
||||
|
||||
}
|
||||
|
@ -30,8 +30,4 @@ public class ValueException extends SyntaxException{
|
||||
super(message.replaceAll("%n", str));
|
||||
}
|
||||
|
||||
public ValueException(String message, byte[]bytes, int p, int end) {
|
||||
this(message, new String(bytes, p, end - p));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.regexp;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import jdk.nashorn.internal.runtime.ParserException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Basic tests for the JDK based RegExp implementation.
|
||||
*
|
||||
* @test
|
||||
* @run testng jdk.nashorn.internal.runtime.regexp.JdkRegExpTest
|
||||
*/
|
||||
public class JdkRegExpTest {
|
||||
|
||||
/**
|
||||
* Compile a regular expression using the JDK implementation
|
||||
*/
|
||||
@Test
|
||||
public void testMatcher() {
|
||||
RegExp regexp = new RegExpFactory().compile("f(o)o", "");
|
||||
RegExpMatcher matcher = regexp.match("foo");
|
||||
assertNotNull(matcher);
|
||||
assertTrue(matcher.search(0));
|
||||
assertEquals(matcher.getInput(), "foo");
|
||||
assertEquals(matcher.groupCount(), 1);
|
||||
assertEquals(matcher.group(), "foo");
|
||||
assertEquals(matcher.start(), 0);
|
||||
assertEquals(matcher.end(), 3);
|
||||
assertEquals(matcher.group(1), "o");
|
||||
assertEquals(matcher.start(1), 1);
|
||||
assertEquals(matcher.end(1), 2);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.regexp.joni;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Joni coverage tests
|
||||
*
|
||||
* @test
|
||||
* @run testng jdk.nashorn.internal.runtime.regexp.joni.JoniTest
|
||||
*/
|
||||
public class JoniTest {
|
||||
|
||||
@Test
|
||||
public void testDump() {
|
||||
new Regex("^a{3,}(.*)[z]++\\s\\1x$").dumpTree();
|
||||
new Regex("^a{3,}(.*)[z]++\\s\\1x$").dumpByteCode();
|
||||
new Regex("(abc){4,}{2,5}").dumpTree();
|
||||
new Regex("(abc){4,}{2,5}").dumpByteCode();
|
||||
new Regex("aaa|aa|bbbb|ccc").dumpTree();
|
||||
new Regex("aaa|aa|bbbb|ccc").dumpByteCode();
|
||||
new Regex("(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))").dumpTree();
|
||||
new Regex("(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))").dumpByteCode();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user