|
Java example source code file (Analyser.java)
The Analyser.java Java example source code/* * 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 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.bsOnAt; 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; import static jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode.newAltNode; import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite; 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.ConsAltNode; 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.ast.QuantifierNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode; import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType; import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType; import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType; 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.ObjPtr; import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException; import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException; import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException; final class Analyser extends Parser { protected Analyser(ScanEnvironment env, char[] chars, int p, int end) { super(env, chars, p, end); } protected final void compile() { if (Config.DEBUG) { Config.log.println(new String(chars, getBegin(), getEnd())); } reset(); regex.numMem = 0; regex.numRepeat = 0; regex.numNullCheck = 0; //regex.repeatRangeAlloc = 0; regex.repeatRangeLo = null; regex.repeatRangeHi = null; parse(); if (Config.DEBUG_PARSE_TREE_RAW && Config.DEBUG_PARSE_TREE) { Config.log.println("<RAW TREE>"); Config.log.println(root + "\n"); } root = setupTree(root, 0); if (Config.DEBUG_PARSE_TREE) { if (Config.DEBUG_PARSE_TREE_RAW) Config.log.println("<TREE>"); root.verifyTree(new HashSet<Node>(), env.reg.warnings); Config.log.println(root + "\n"); } regex.captureHistory = env.captureHistory; regex.btMemStart = env.btMemStart; regex.btMemEnd = env.btMemEnd; if (isFindCondition(regex.options)) { regex.btMemEnd = bsAll(); } else { regex.btMemEnd = env.btMemEnd; regex.btMemEnd |= regex.captureHistory; } regex.clearOptimizeInfo(); if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root); env.memNodes = null; if (regex.numRepeat != 0 || regex.btMemEnd != 0) { regex.stackPopLevel = StackPopLevel.ALL; } else { if (regex.btMemStart != 0) { regex.stackPopLevel = StackPopLevel.MEM_START; } else { regex.stackPopLevel = StackPopLevel.FREE; } } if (Config.DEBUG_COMPILE) { 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()); } // DEBUG_COMPILE } private void swap(Node a, Node b) { a.swap(b); if (root == b) { root = a; } else if (root == a) { root = b; } } // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK private int quantifiersMemoryInfo(Node node) { int info = 0; switch(node.getType()) { case NodeType.LIST: case NodeType.ALT: ConsAltNode can = (ConsAltNode)node; do { int v = quantifiersMemoryInfo(can.car); if (v > info) info = v; } while ((can = can.cdr) != null); break; case NodeType.QTFR: QuantifierNode qn = (QuantifierNode)node; if (qn.upper != 0) { info = quantifiersMemoryInfo(qn.target); } break; case NodeType.ENCLOSE: EncloseNode en = (EncloseNode)node; switch (en.type) { case EncloseType.MEMORY: return TargetInfo.IS_EMPTY_MEM; case EncloseType.OPTION: case EncloseNode.STOP_BACKTRACK: info = quantifiersMemoryInfo(en.target); break; default: break; } // inner switch break; case NodeType.BREF: case NodeType.STR: case NodeType.CTYPE: case NodeType.CCLASS: case NodeType.CANY: case NodeType.ANCHOR: default: break; } // switch return info; } private int getMinMatchLength(Node node) { int min = 0; switch (node.getType()) { case NodeType.BREF: BackRefNode br = (BackRefNode)node; if (br.isRecursion()) break; if (br.backRef > env.numMem) { throw new ValueException(ERR_INVALID_BACKREF); } min = getMinMatchLength(env.memNodes[br.backRef]); break; case NodeType.LIST: ConsAltNode can = (ConsAltNode)node; do { min += getMinMatchLength(can.car); } while ((can = can.cdr) != null); break; case NodeType.ALT: ConsAltNode y = (ConsAltNode)node; do { Node x = y.car; int tmin = getMinMatchLength(x); if (y == node) { min = tmin; } else if (min > tmin) { min = tmin; } } while ((y = y.cdr) != null); break; case NodeType.STR: min = ((StringNode)node).length(); break; case NodeType.CTYPE: min = 1; break; case NodeType.CCLASS: case NodeType.CANY: min = 1; break; case NodeType.QTFR: QuantifierNode qn = (QuantifierNode)node; if (qn.lower > 0) { min = getMinMatchLength(qn.target); min = MinMaxLen.distanceMultiply(min, qn.lower); } break; case NodeType.ENCLOSE: EncloseNode en = (EncloseNode)node; switch (en.type) { case EncloseType.MEMORY: if (en.isMinFixed()) { min = en.minLength; } else { min = getMinMatchLength(en.target); en.minLength = min; en.setMinFixed(); } break; case EncloseType.OPTION: case EncloseType.STOP_BACKTRACK: min = getMinMatchLength(en.target); break; } // inner switch break; case NodeType.ANCHOR: default: break; } // switch return min; } private int getMaxMatchLength(Node node) { int max = 0; switch (node.getType()) { case NodeType.LIST: ConsAltNode ln = (ConsAltNode)node; do { int tmax = getMaxMatchLength(ln.car); max = MinMaxLen.distanceAdd(max, tmax); } while ((ln = ln.cdr) != null); break; case NodeType.ALT: ConsAltNode an = (ConsAltNode)node; do { int tmax = getMaxMatchLength(an.car); if (max < tmax) max = tmax; } while ((an = an.cdr) != null); break; case NodeType.STR: max = ((StringNode)node).length(); break; case NodeType.CTYPE: max = 1; break; case NodeType.CCLASS: case NodeType.CANY: max = 1; break; case NodeType.BREF: BackRefNode br = (BackRefNode)node; if (br.isRecursion()) { max = MinMaxLen.INFINITE_DISTANCE; break; } if (br.backRef > env.numMem) { throw new ValueException(ERR_INVALID_BACKREF); } int tmax = getMaxMatchLength(env.memNodes[br.backRef]); if (max < tmax) max = tmax; break; case NodeType.QTFR: QuantifierNode qn = (QuantifierNode)node; if (qn.upper != 0) { max = getMaxMatchLength(qn.target); if (max != 0) { if (!isRepeatInfinite(qn.upper)) { max = MinMaxLen.distanceMultiply(max, qn.upper); } else { max = MinMaxLen.INFINITE_DISTANCE; } } } break; case NodeType.ENCLOSE: EncloseNode en = (EncloseNode)node; switch (en.type) { case EncloseType.MEMORY: if (en.isMaxFixed()) { max = en.maxLength; } else { max = getMaxMatchLength(en.target); en.maxLength = max; en.setMaxFixed(); } break; case EncloseType.OPTION: case EncloseType.STOP_BACKTRACK: max = getMaxMatchLength(en.target); break; } // inner switch break; case NodeType.ANCHOR: default: break; } // switch return max; } private static final int GET_CHAR_LEN_VARLEN = -1; private static final int GET_CHAR_LEN_TOP_ALT_VARLEN = -2; protected final int getCharLengthTree(Node node) { return getCharLengthTree(node, 0); } private int getCharLengthTree(Node node, int level) { level++; int len = 0; returnCode = 0; switch(node.getType()) { case NodeType.LIST: ConsAltNode ln = (ConsAltNode)node; do { int tlen = getCharLengthTree(ln.car, level); if (returnCode == 0) len = MinMaxLen.distanceAdd(len, tlen); } while (returnCode == 0 && (ln = ln.cdr) != null); break; case NodeType.ALT: ConsAltNode an = (ConsAltNode)node; boolean varLen = false; int tlen = getCharLengthTree(an.car, level); while (returnCode == 0 && (an = an.cdr) != null) { int tlen2 = getCharLengthTree(an.car, level); if (returnCode == 0) { if (tlen != tlen2) varLen = true; } } if (returnCode == 0) { if (varLen) { if (level == 1) { returnCode = GET_CHAR_LEN_TOP_ALT_VARLEN; } else { returnCode = GET_CHAR_LEN_VARLEN; } } else { len = tlen; } } break; case NodeType.STR: StringNode sn = (StringNode)node; len = sn.length(); break; case NodeType.QTFR: QuantifierNode qn = (QuantifierNode)node; if (qn.lower == qn.upper) { tlen = getCharLengthTree(qn.target, level); if (returnCode == 0) len = MinMaxLen.distanceMultiply(tlen, qn.lower); } else { returnCode = GET_CHAR_LEN_VARLEN; } break; case NodeType.CTYPE: case NodeType.CCLASS: case NodeType.CANY: len = 1; break; case NodeType.ENCLOSE: EncloseNode en = (EncloseNode)node; switch(en.type) { case EncloseType.MEMORY: if (en.isCLenFixed()) { len = en.charLength; } else { len = getCharLengthTree(en.target, level); if (returnCode == 0) { en.charLength = len; en.setCLenFixed(); } } break; case EncloseType.OPTION: case EncloseType.STOP_BACKTRACK: len = getCharLengthTree(en.target, level); break; } // inner switch break; case NodeType.ANCHOR: break; default: returnCode = GET_CHAR_LEN_VARLEN; } // switch return len; } /* x is not included y ==> 1 : 0 */ private boolean isNotIncluded(Node x, Node y) { Node tmp; // !retry:! retry: while(true) { int yType = y.getType(); switch(x.getType()) { case NodeType.CTYPE: switch(yType) { case NodeType.CCLASS: // !swap:! tmp = x; x = y; y = tmp; // !goto retry;! continue retry; case NodeType.STR: // !goto swap;! tmp = x; x = y; y = tmp; continue retry; default: break; } // inner switch break; case NodeType.CCLASS: CClassNode xc = (CClassNode)x; switch(yType) { case NodeType.CCLASS: CClassNode yc = (CClassNode)y; for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) { boolean v = xc.bs.at(i); if ((v && !xc.isNot()) || (!v && xc.isNot())) { v = yc.bs.at(i); if ((v && !yc.isNot()) || (!v && yc.isNot())) return false; } } if ((xc.mbuf == null && !xc.isNot()) || yc.mbuf == null && !yc.isNot()) return true; return false; // break; not reached case NodeType.STR: // !goto swap;! tmp = x; x = y; y = tmp; continue retry; default: break; } // inner switch break; // case NodeType.CCLASS case NodeType.STR: StringNode xs = (StringNode)x; if (xs.length() == 0) break; switch (yType) { case NodeType.CCLASS: CClassNode cc = (CClassNode)y; int code = xs.chars[xs.p]; return !cc.isCodeInCC(code); case NodeType.STR: StringNode ys = (StringNode)y; int len = xs.length(); if (len > ys.length()) len = ys.length(); if (xs.isAmbig() || ys.isAmbig()) { /* tiny version */ return false; } else { for (int i=0, p=ys.p, q=xs.p; i<len; i++, p++, q++) { if (ys.chars[p] != xs.chars[q]) return true; } } break; default: break; } // inner switch break; // case NodeType.STR } // switch break; } // retry: while return false; } private Node getHeadValueNode(Node node, boolean exact) { Node n = null; switch(node.getType()) { case NodeType.BREF: case NodeType.ALT: case NodeType.CANY: break; case NodeType.CTYPE: case NodeType.CCLASS: if (!exact) n = node; break; case NodeType.LIST: n = getHeadValueNode(((ConsAltNode)node).car, exact); break; case NodeType.STR: StringNode sn = (StringNode)node; if (sn.end <= sn.p) break; // ??? if (exact && !sn.isRaw() && isIgnoreCase(regex.options)){ // nothing } else { n = node; } break; case NodeType.QTFR: QuantifierNode qn = (QuantifierNode)node; if (qn.lower > 0) { if (qn.headExact != null) { n = qn.headExact; } else { n = getHeadValueNode(qn.target, exact); } } break; case NodeType.ENCLOSE: EncloseNode en = (EncloseNode)node; switch (en.type) { case EncloseType.OPTION: int options = regex.options; regex.options = en.option; n = getHeadValueNode(en.target, exact); regex.options = options; break; case EncloseType.MEMORY: case EncloseType.STOP_BACKTRACK: n = getHeadValueNode(en.target, exact); break; } // inner switch break; case NodeType.ANCHOR: AnchorNode an = (AnchorNode)node; if (an.type == AnchorType.PREC_READ) n = getHeadValueNode(an.target, exact); break; default: break; } // switch return n; } // true: invalid private boolean checkTypeTree(Node node, int typeMask, int encloseMask, int anchorMask) { if ((node.getType2Bit() & typeMask) == 0) return true; boolean invalid = false; switch(node.getType()) { case NodeType.LIST: case NodeType.ALT: ConsAltNode can = (ConsAltNode)node; do { invalid = checkTypeTree(can.car, typeMask, encloseMask, anchorMask); } while (!invalid && (can = can.cdr) != null); break; case NodeType.QTFR: invalid = checkTypeTree(((QuantifierNode)node).target, typeMask, encloseMask, anchorMask); break; case NodeType.ENCLOSE: EncloseNode en = (EncloseNode)node; if ((en.type & encloseMask) == 0) return true; invalid = checkTypeTree(en.target, typeMask, encloseMask, anchorMask); break; case NodeType.ANCHOR: AnchorNode an = (AnchorNode)node; if ((an.type & anchorMask) == 0) return true; if (an.target != null) invalid = checkTypeTree(an.target, typeMask, encloseMask, anchorMask); break; default: break; } // switch return invalid; } /* divide different length alternatives in look-behind. (?<=A|B) ==> (?<=A)|(?<=B) (?<!A|B) ==> (?a*)b */ if (qn.lower <= 1) { if (qn.target.isSimple()) { Node x = getHeadValueNode(qn.target, false); if (x != null) { Node y = getHeadValueNode(nextNode, false); if (y != null && isNotIncluded(x, y)) { EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); //onig_node_new_enclose en.setStopBtSimpleRepeat(); //en.setTarget(qn.target); // optimize it ?? swap(node, en); en.setTarget(node); } } } } } } else if (type == NodeType.ENCLOSE) { EncloseNode en = (EncloseNode)node; if (en.isMemory()) { node = en.target; // !goto retry;! continue retry; } } break; } // while } private void updateStringNodeCaseFoldMultiByte(StringNode sn) { char[] chars = sn.chars; int end = sn.end; value = sn.p; int sp = 0; char buf; while (value < end) { int ovalue = value; buf = Character.toLowerCase(chars[value++]); if (chars[ovalue] != buf) { char[] sbuf = new char[sn.length() << 1]; System.arraycopy(chars, sn.p, sbuf, 0, ovalue - sn.p); value = ovalue; while (value < end) { buf = Character.toLowerCase(chars[value++]); if (sp >= sbuf.length) { char[]tmp = new char[sbuf.length << 1]; System.arraycopy(sbuf, 0, tmp, 0, sbuf.length); sbuf = tmp; } sbuf[sp++] = buf; } sn.set(sbuf, 0, sp); return; } sp++; } } private void updateStringNodeCaseFold(Node node) { StringNode sn = (StringNode)node; updateStringNodeCaseFoldMultiByte(sn); } private Node expandCaseFoldMakeRemString(char[] chars, int p, int end) { StringNode node = new StringNode(chars, p, end); updateStringNodeCaseFold(node); node.setAmbig(); node.setDontGetOptInfo(); return node; } private boolean expandCaseFoldStringAlt(int itemNum, char[] items, char[] chars, int p, int slen, int end, ObjPtr<Node> node) { ConsAltNode altNode; node.p = altNode = newAltNode(null, null); StringNode snode = new StringNode(chars, p, p + slen); altNode.setCar(snode); for (int i=0; i<itemNum; i++) { snode = new StringNode(); snode.catCode(items[i]); ConsAltNode an = newAltNode(null, null); an.setCar(snode); altNode.setCdr(an); altNode = an; } return false; } private static final int THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION = 8; private Node expandCaseFoldString(Node node) { StringNode sn = (StringNode)node; if (sn.isAmbig() || sn.length() <= 0) return node; char[] chars = sn.chars; int p = sn.p; int end = sn.end; int altNum = 1; ConsAltNode topRoot = null, root = null; ObjPtr<Node> prevNode = new ObjPtr Other Java examples (source code examples)Here is a short list of links related to this Java Analyser.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.