📄 nativeregexp.java
字号:
/* <OPT>, <parencount>, <parenindex>, <next> ... <ENDCHILD> */ state.progLength += 8; hasQ = true; break; case '{': /* balance '}' */ { int min = 0; int max = -1; int leftCurl = state.cp; /* For Perl etc. compatibility, if quntifier does not match * \{\d+(,\d*)?\} exactly back off from it * being a quantifier, and chew it up as a literal * atom next time instead. */ c = src[++state.cp]; if (isDigit(c)) { ++state.cp; min = getDecimalValue(c, state, 0xFFFF, "msg.overlarge.min"); c = src[state.cp]; if (c == ',') { c = src[++state.cp]; if (isDigit(c)) { ++state.cp; max = getDecimalValue(c, state, 0xFFFF, "msg.overlarge.max"); c = src[state.cp]; if (min > max) { reportError("msg.max.lt.min", String.valueOf(src[state.cp])); return false; } } } else { max = min; } /* balance '{' */ if (c == '}') { state.result = new RENode(REOP_QUANT); state.result.min = min; state.result.max = max; // QUANT, <min>, <max>, <parencount>, // <parenindex>, <next> ... <ENDCHILD> state.progLength += 12; hasQ = true; } } if (!hasQ) { state.cp = leftCurl; } break; } } if (!hasQ) return true; ++state.cp; state.result.kid = term; state.result.parenIndex = parenBaseCount; state.result.parenCount = state.parenCount - parenBaseCount; if ((state.cp < state.cpend) && (src[state.cp] == '?')) { ++state.cp; state.result.greedy = false; } else state.result.greedy = true; return true; } private static void resolveForwardJump(byte[] array, int from, int pc) { if (from > pc) throw Kit.codeBug(); addIndex(array, from, pc - from); } private static int getOffset(byte[] array, int pc) { return getIndex(array, pc); } private static int addIndex(byte[] array, int pc, int index) { if (index < 0) throw Kit.codeBug(); if (index > 0xFFFF) throw Context.reportRuntimeError("Too complex regexp"); array[pc] = (byte)(index >> 8); array[pc + 1] = (byte)(index); return pc + 2; } private static int getIndex(byte[] array, int pc) { return ((array[pc] & 0xFF) << 8) | (array[pc + 1] & 0xFF); } private static final int OFFSET_LEN = 2; private static final int INDEX_LEN = 2; 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_ALT: nextAlt = t.kid2; nextAltFixup = pc; /* address of next alternate */ pc += OFFSET_LEN; pc = emitREBytecode(state, re, pc, t.kid); program[pc++] = REOP_JUMP; nextTermFixup = pc; /* address of following term */ pc += OFFSET_LEN; resolveForwardJump(program, nextAltFixup, pc); pc = emitREBytecode(state, re, pc, nextAlt); program[pc++] = REOP_JUMP; nextAltFixup = pc; pc += OFFSET_LEN; resolveForwardJump(program, nextTermFixup, pc); resolveForwardJump(program, nextAltFixup, pc); break; case REOP_FLAT: /* * Consecutize FLAT's if possible. */ if (t.flatIndex != -1) { while ((t.next != null) && (t.next.op == REOP_FLAT) && ((t.flatIndex + t.length) == t.next.flatIndex)) { t.length += t.next.length; t.next = t.next.next; } } 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_ASSERT: nextTermFixup = pc; pc += OFFSET_LEN; pc = emitREBytecode(state, re, pc, t.kid); program[pc++] = REOP_ASSERTTEST; resolveForwardJump(program, nextTermFixup, pc); break; case REOP_ASSERT_NOT: nextTermFixup = pc; pc += OFFSET_LEN; pc = emitREBytecode(state, re, pc, t.kid); program[pc++] = REOP_ASSERTNOTTEST; 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 += OFFSET_LEN; pc = emitREBytecode(state, re, pc, t.kid); program[pc++] = REOP_ENDCHILD; resolveForwardJump(program, nextTermFixup, pc); break; case REOP_CLASS: pc = addIndex(program, pc, t.index); re.classList[t.index] = new RECharSet(t.bmsize, t.startIndex, t.kidlen); break; default: break; } t = t.next; } return pc; } private static void pushProgState(REGlobalData gData, int min, int max, REBackTrackData backTrackLastToSave, int continuation_pc, int continuation_op) { gData.stateStackTop = new REProgState(gData.stateStackTop, min, max, gData.cp, backTrackLastToSave, continuation_pc, continuation_op); } private static REProgState popProgState(REGlobalData gData) { REProgState state = gData.stateStackTop; gData.stateStackTop = state.previous; return state; } private static void pushBackTrackState(REGlobalData gData, byte op, int target) { gData.backTrackStackTop = new REBackTrackData(gData, op, target); } /* * Consecutive literal characters. */ private static boolean flatNMatcher(REGlobalData gData, int matchChars, int length, char[] chars, int end) { if ((gData.cp + length) > end) return false; for (int i = 0; i < length; i++) { if (gData.regexp.source[matchChars + i] != chars[gData.cp + i]) { return false; } } gData.cp += length; return true; } private static boolean flatNIMatcher(REGlobalData gData, int matchChars, int length, char[] chars, int end) { if ((gData.cp + length) > end) return false; for (int i = 0; i < length; i++) { if (upcase(gData.regexp.source[matchChars + i]) != upcase(chars[gData.cp + i])) { return false; } } gData.cp += length; return true; } /* 1. Evaluate DecimalEscape to obtain an EscapeValue E. 2. If E is not a character then go to step 6. 3. Let ch be E's character. 4. Let A be a one-element RECharSet containing the character ch. 5. Call CharacterSetMatcher(A, false) and return its Matcher result. 6. E must be an integer. Let n be that integer. 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception. 8. Return an internal Matcher closure that takes two arguments, a State x and a Continuation c, and performs the following: 1. Let cap be x's captures internal array. 2. Let s be cap[n]. 3. If s is undefined, then call c(x) and return its result. 4. Let e be x's endIndex. 5. Let len be s's length. 6. Let f be e+len. 7. If f>InputLength, return failure. 8. If there exists an integer i between 0 (inclusive) and len (exclusive) such that Canonicalize(s[i]) is not the same character as Canonicalize(Input [e+i]), then return failure. 9. Let y be the State (f, cap). 10. Call c(y) and return its result. */ private static boolean backrefMatcher(REGlobalData gData, int parenIndex, char[] chars, int end) { int len; int i; int parenContent = gData.parens_index(parenIndex); if (parenContent == -1) return true; len = gData.parens_length(parenIndex); if ((gData.cp + len) > end) return false; if ((gData.regexp.flags & JSREG_FOLD) != 0) { for (i = 0; i < len; i++) { if (upcase(chars[parenContent + i]) != upcase(chars[gData.cp + i])) return false; } } else { for (i = 0; i < len; i++) { if (chars[parenContent + i] != chars[gData.cp + i]) return false; } } gData.cp += len; return true; } /* Add a single character to the RECharSet */ private static void addCharacterToCharSet(RECharSet cs, char c) { int byteIndex = (int)(c / 8); if (c > cs.length) throw new RuntimeException(); cs.bits[byteIndex] |= 1 << (c & 0x7); } /* Add a character range, c1 to c2 (inclusive) to the RECharSet */ private static void addCharacterRangeToCharSet(RECharSet cs, char c1, char c2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -