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;
}