private Op compile()

in src/main/java/org/apache/xmlbeans/impl/regex/RegularExpression.java [489:639]


    private Op compile(Token tok, Op next, boolean reverse) {
        Op ret;
        switch (tok.type) {
            case Token.DOT:
                ret = Op.createDot();
                ret.next = next;
                break;

            case Token.CHAR:
                ret = Op.createChar(tok.getChar());
                ret.next = next;
                break;

            case Token.ANCHOR:
                ret = Op.createAnchor(tok.getChar());
                ret.next = next;
                break;

            case Token.RANGE:
            case Token.NRANGE:
                ret = Op.createRange(tok);
                ret.next = next;
                break;

            case Token.CONCAT:
                ret = next;
                if (!reverse) {
                    for (int i = tok.size()-1;  i >= 0;  i --) {
                        ret = compile(tok.getChild(i), ret, false);
                    }
                } else {
                    for (int i = 0;  i < tok.size();  i ++) {
                        ret = compile(tok.getChild(i), ret, true);
                    }
                }
                break;

            case Token.UNION:
                Op.UnionOp uni = Op.createUnion(tok.size());
                for (int i = 0;  i < tok.size();  i ++) {
                    uni.addElement(compile(tok.getChild(i), next, reverse));
                }
                ret = uni;                          // ret.next is null.
                break;

            case Token.CLOSURE:
            case Token.NONGREEDYCLOSURE:
                Token child = tok.getChild(0);
                int min = tok.getMin();
                int max = tok.getMax();
                if (min >= 0 && min == max) { // {n}
                    ret = next;
                    for (int i = 0; i < min;  i ++) {
                        ret = compile(child, ret, reverse);
                    }
                    break;
                }
                if (min > 0 && max > 0)
                    max -= min;
                if (max > 0) {
                    // X{2,6} -> XX(X(X(XX?)?)?)?
                    ret = next;
                    for (int i = 0;  i < max;  i ++) {
                        Op.ChildOp q = Op.createQuestion(tok.type == Token.NONGREEDYCLOSURE);
                        q.next = next;
                        q.setChild(compile(child, ret, reverse));
                        ret = q;
                    }
                } else {
                    Op.ChildOp op;
                    if (tok.type == Token.NONGREEDYCLOSURE) {
                        op = Op.createNonGreedyClosure();
                    } else {                        // Token.CLOSURE
                        op = Op.createClosure(this.numberOfClosures++);
                    }
                    op.next = next;
                    op.setChild(compile(child, op, reverse));
                    ret = op;
                }
                if (min > 0) {
                    for (int i = 0;  i < min;  i ++) {
                        ret = compile(child, ret, reverse);
                    }
                }
                break;

            case Token.EMPTY:
                ret = next;
                break;

            case Token.STRING:
                ret = Op.createString(tok.getString());
                ret.next = next;
                break;

            case Token.BACKREFERENCE:
                ret = Op.createBackReference(tok.getReferenceNumber());
                ret.next = next;
                break;

            case Token.PAREN:
                if (tok.getParenNumber() == 0) {
                    ret = compile(tok.getChild(0), next, reverse);
                } else if (reverse) {
                    next = Op.createCapture(tok.getParenNumber(), next);
                    next = compile(tok.getChild(0), next, reverse);
                    ret = Op.createCapture(-tok.getParenNumber(), next);
                } else {
                    next = Op.createCapture(-tok.getParenNumber(), next);
                    next = compile(tok.getChild(0), next, reverse);
                    ret = Op.createCapture(tok.getParenNumber(), next);
                }
                break;

            case Token.LOOKAHEAD:
                ret = Op.createLook(Op.LOOKAHEAD, next, compile(tok.getChild(0), null, false));
                break;
            case Token.NEGATIVELOOKAHEAD:
                ret = Op.createLook(Op.NEGATIVELOOKAHEAD, next, compile(tok.getChild(0), null, false));
                break;
            case Token.LOOKBEHIND:
                ret = Op.createLook(Op.LOOKBEHIND, next, compile(tok.getChild(0), null, true));
                break;
            case Token.NEGATIVELOOKBEHIND:
                ret = Op.createLook(Op.NEGATIVELOOKBEHIND, next, compile(tok.getChild(0), null, true));
                break;

            case Token.INDEPENDENT:
                ret = Op.createIndependent(next, compile(tok.getChild(0), null, reverse));
                break;

            case Token.MODIFIERGROUP:
                ret = Op.createModifier(next, compile(tok.getChild(0), null, reverse),
                        ((Token.ModifierToken)tok).getOptions(),
                        ((Token.ModifierToken)tok).getOptionsMask());
                break;

            case Token.CONDITION:
                Token.ConditionToken ctok = (Token.ConditionToken)tok;
                int ref = ctok.refNumber;
                Op condition = ctok.condition == null ? null : compile(ctok.condition, null, reverse);
                Op yes = compile(ctok.yes, next, reverse);
                Op no = ctok.no == null ? null : compile(ctok.no, next, reverse);
                ret = Op.createCondition(next, ref, condition, yes, no);
                break;

            default:
                throw new RuntimeException("Unknown token type: "+tok.type);
        } // switch (tok.type)
        return ret;
    }