private static int emitREBytecode()

in rhino/src/main/java/org/mozilla/javascript/regexp/NativeRegExp.java [1702:1839]


    private static int emitREBytecode(CompilerState state, RECompiled re, int pc, RENode t) {
        RENode nextAlt;
        int nextAltFixup, nextTermFixup;
        byte[] program = re.program;

        while (t != null) {
            program[pc++] = t.op;
            switch (t.op) {
                case REOP_EMPTY:
                    --pc;
                    break;
                case REOP_ALTPREREQ:
                case REOP_ALTPREREQi:
                case REOP_ALTPREREQ2:
                    boolean ignoreCase = t.op == REOP_ALTPREREQi;
                    addIndex(program, pc, ignoreCase ? upcase(t.chr) : t.chr);
                    pc += INDEX_LEN;
                    addIndex(program, pc, ignoreCase ? upcase((char) t.index) : t.index);
                    pc += INDEX_LEN;
                // fall through to REOP_ALT
                case REOP_ALT:
                    nextAlt = t.kid2;
                    nextAltFixup = pc; /* address of next alternate */
                    pc += INDEX_LEN;
                    pc = emitREBytecode(state, re, pc, t.kid);
                    program[pc++] = REOP_JUMP;
                    nextTermFixup = pc; /* address of following term */
                    pc += INDEX_LEN;
                    resolveForwardJump(program, nextAltFixup, pc);
                    pc = emitREBytecode(state, re, pc, nextAlt);

                    program[pc++] = REOP_JUMP;
                    nextAltFixup = pc;
                    pc += INDEX_LEN;

                    resolveForwardJump(program, nextTermFixup, pc);
                    resolveForwardJump(program, nextAltFixup, pc);
                    break;
                case REOP_FLAT:
                    if ((t.flatIndex != -1) && (t.length > 1)) {
                        if ((state.flags & JSREG_FOLD) != 0) program[pc - 1] = REOP_FLATi;
                        else program[pc - 1] = REOP_FLAT;
                        pc = addIndex(program, pc, t.flatIndex);
                        pc = addIndex(program, pc, t.length);
                    } else {
                        if (t.chr < 256) {
                            if ((state.flags & JSREG_FOLD) != 0) program[pc - 1] = REOP_FLAT1i;
                            else program[pc - 1] = REOP_FLAT1;
                            program[pc++] = (byte) t.chr;
                        } else {
                            if ((state.flags & JSREG_FOLD) != 0) program[pc - 1] = REOP_UCFLAT1i;
                            else program[pc - 1] = REOP_UCFLAT1;
                            pc = addIndex(program, pc, t.chr);
                        }
                    }
                    break;
                case REOP_LPAREN:
                    pc = addIndex(program, pc, t.parenIndex);
                    pc = emitREBytecode(state, re, pc, t.kid);
                    program[pc++] = REOP_RPAREN;
                    pc = addIndex(program, pc, t.parenIndex);
                    break;
                case REOP_BACKREF:
                    pc = addIndex(program, pc, t.parenIndex);
                    break;
                case REOP_NAMED_BACKREF:
                    {
                        String backRefName =
                                new String(
                                        re.source,
                                        t.captureGroupNameIndex,
                                        t.captureGroupNameLength);
                        List<Integer> indices = re.namedCaptureGroups.get(backRefName);
                        if (indices == null) {
                            reportError("msg.invalid.named.backref", "");
                            return pc;
                        }

                        if (indices.size() == 1) { // optimization for unique backrefs
                            program[pc - 1] = REOP_BACKREF;
                            pc = addIndex(program, pc, indices.get(0));
                        } else {
                            // backref doesn't have a unique parenIndex
                            pc = addIndex(program, pc, t.captureGroupNameIndex);
                            pc = addIndex(program, pc, t.captureGroupNameLength);
                        }
                    }
                    break;
                case REOP_ASSERT:
                case REOP_ASSERTBACK:
                    nextTermFixup = pc;
                    pc += INDEX_LEN;
                    pc = emitREBytecode(state, re, pc, t.kid);
                    program[pc++] = t.op == REOP_ASSERT ? REOP_ASSERTTEST : REOP_ASSERTBACKTEST;
                    resolveForwardJump(program, nextTermFixup, pc);
                    break;
                case REOP_ASSERT_NOT:
                case REOP_ASSERTBACK_NOT:
                    nextTermFixup = pc;
                    pc += INDEX_LEN;
                    pc = emitREBytecode(state, re, pc, t.kid);
                    program[pc++] =
                            t.op == REOP_ASSERT_NOT ? REOP_ASSERTNOTTEST : REOP_ASSERTBACKNOTTEST;
                    resolveForwardJump(program, nextTermFixup, pc);
                    break;
                case REOP_QUANT:
                    if ((t.min == 0) && (t.max == -1))
                        program[pc - 1] = t.greedy ? REOP_STAR : REOP_MINIMALSTAR;
                    else if ((t.min == 0) && (t.max == 1))
                        program[pc - 1] = t.greedy ? REOP_OPT : REOP_MINIMALOPT;
                    else if ((t.min == 1) && (t.max == -1))
                        program[pc - 1] = t.greedy ? REOP_PLUS : REOP_MINIMALPLUS;
                    else {
                        if (!t.greedy) program[pc - 1] = REOP_MINIMALQUANT;
                        pc = addIndex(program, pc, t.min);
                        // max can be -1 which addIndex does not accept
                        pc = addIndex(program, pc, t.max + 1);
                    }
                    pc = addIndex(program, pc, t.parenCount);
                    pc = addIndex(program, pc, t.parenIndex);
                    nextTermFixup = pc;
                    pc += INDEX_LEN;
                    pc = emitREBytecode(state, re, pc, t.kid);
                    program[pc++] = REOP_ENDCHILD;
                    resolveForwardJump(program, nextTermFixup, pc);
                    break;
                case REOP_CLASS:
                    if (!t.classContents.sense) program[pc - 1] = REOP_NCLASS;
                    pc = addIndex(program, pc, t.index);
                    re.classList[t.index] = new RECharSet(t.classContents, t.bmsize);
                    break;
                default:
                    break;
            }
            t = t.next;
        }
        return pc;
    }