?? re.java
字號:
*/ protected final void setParenStart(int which, int i) { if (which < parenCount) { switch (which) { case 0: start0 = i; break; case 1: start1 = i; break; case 2: start2 = i; break; default: if (startn == null) { allocParens(); } startn[which] = i; break; } } } /** * Sets the end of a paren level * * @param which Which paren level * @param i Index in input array */ protected final void setParenEnd(int which, int i) { if (which < parenCount) { switch (which) { case 0: end0 = i; break; case 1: end1 = i; break; case 2: end2 = i; break; default: if (endn == null) { allocParens(); } endn[which] = i; break; } } } /** * Throws an Error representing an internal error condition probably resulting * from a bug in the regular expression compiler (or possibly data corruption). * In practice, this should be very rare. * * @param s Error description */ protected void internalError(String s) throws Error { throw new Error("RE internal error: " + s); } /** * Performs lazy allocation of subexpression arrays */ private void allocParens() { // Allocate arrays for subexpressions startn = new int[maxParen]; endn = new int[maxParen]; // Set sub-expression pointers to invalid values for (int i = 0; i < maxParen; i++) { startn[i] = -1; endn[i] = -1; } } /** * Try to match a string against a subset of nodes in the program * * @param firstNode Node to start at in program * @param lastNode Last valid node (used for matching a subexpression without * matching the rest of the program as well). * @param idxStart Starting position in character array * @return Final input array index if match succeeded. -1 if not. */ protected int matchNodes(int firstNode, int lastNode, int idxStart) { // Our current place in the string int idx = idxStart; // Loop while node is valid int next, opcode, opdata; int idxNew; char[] instruction = program.instruction; for (int node = firstNode; node < lastNode; ) { opcode = instruction[node /* + offsetOpcode */]; next = node + (short) instruction[node + offsetNext]; opdata = instruction[node + offsetOpdata]; switch (opcode) { case OP_MAYBE: case OP_STAR: { // Try to match the following subexpr. If it matches: // MAYBE: Continues matching rest of the expression // STAR: Points back here to repeat subexpr matching if ((idxNew = matchNodes(node + nodeSize, maxNode, idx)) != -1) { return idxNew; } // If failed, just continue with the rest of expression break; } case OP_PLUS: { // Try to match the subexpr again (and again (and ... if ((idxNew = matchNodes(next, maxNode, idx)) != -1) { return idxNew; } // If failed, just continue with the rest of expression // Rest is located at the next pointer of the next instruction // (which must be OP_CONTINUE) node = next + (short) instruction[next + offsetNext]; continue; } case OP_RELUCTANTMAYBE: case OP_RELUCTANTSTAR: { // Try to match the rest without using the reluctant subexpr if ((idxNew = matchNodes(next, maxNode, idx)) != -1) { return idxNew; } // Try reluctant subexpr. If it matches: // RELUCTANTMAYBE: Continues matching rest of the expression // RELUCTANTSTAR: Points back here to repeat reluctant star matching return matchNodes(node + nodeSize, next, idx); } case OP_RELUCTANTPLUS: { // Continue matching the rest without using the reluctant subexpr if ((idxNew = matchNodes(next + (short) instruction[next + offsetNext], maxNode, idx)) != -1) { return idxNew; } // Try to match subexpression again break; } case OP_OPEN: // Match subexpression if ((program.flags & REProgram.OPT_HASBACKREFS) != 0) { startBackref[opdata] = idx; } if ((idxNew = matchNodes(next, maxNode, idx)) != -1) { // Increase valid paren count if (opdata >= parenCount) { parenCount = opdata + 1; } // Don't set paren if already set later on if (getParenStart(opdata) == -1) { setParenStart(opdata, idx); } } return idxNew; case OP_CLOSE: // Done matching subexpression if ((program.flags & REProgram.OPT_HASBACKREFS) != 0) { endBackref[opdata] = idx; } if ((idxNew = matchNodes(next, maxNode, idx)) != -1) { // Increase valid paren count if (opdata >= parenCount) { parenCount = opdata + 1; } // Don't set paren if already set later on if (getParenEnd(opdata) == -1) { setParenEnd(opdata, idx); } } return idxNew; case OP_BACKREF: { // Get the start and end of the backref int s = startBackref[opdata]; int e = endBackref[opdata]; // We don't know the backref yet if (s == -1 || e == -1) { return -1; } // The backref is empty size if (s == e) { break; } // Get the length of the backref int l = e - s; // If there's not enough input left, give up. if (search.isEnd(idx + l - 1)) { return -1; } // Case fold the backref? final boolean caseFold = ((matchFlags & MATCH_CASEINDEPENDENT) != 0); // Compare backref to input for (int i = 0; i < l; i++) { if (compareChars(search.charAt(idx++), search.charAt(s + i), caseFold) != 0) { return -1; } } } break; case OP_BOL: // Fail if we're not at the start of the string if (idx != 0) { // If we're multiline matching, we could still be at the start of a line if ((matchFlags & MATCH_MULTILINE) == MATCH_MULTILINE) { // Continue if at the start of a line if (isNewline(idx - 1)) { break; } } return -1; } break; case OP_EOL: // If we're not at the end of string if (!search.isEnd(0) && !search.isEnd(idx)) { // If we're multi-line matching if ((matchFlags & MATCH_MULTILINE) == MATCH_MULTILINE) { // Continue if we're at the end of a line if (isNewline(idx)) { break; } } return -1; } break; case OP_ESCAPE: // Which escape? switch (opdata) { // Word boundary match case E_NBOUND: case E_BOUND: { char cLast = ((idx == 0) ? '\n' : search.charAt(idx - 1)); char cNext = ((search.isEnd(idx)) ? '\n' : search.charAt(idx)); if ((Character.isLetterOrDigit(cLast) == Character.isLetterOrDigit(cNext)) == (opdata == E_BOUND)) { return -1; } } break; // Alpha-numeric, digit, space, javaLetter, javaLetterOrDigit case E_ALNUM: case E_NALNUM: case E_DIGIT: case E_NDIGIT: case E_SPACE: case E_NSPACE: // Give up if out of input if (search.isEnd(idx)) { return -1; } char c = search.charAt(idx); // Switch on escape switch (opdata) { case E_ALNUM: case E_NALNUM: if (!((Character.isLetterOrDigit(c) || c == '_') == (opdata == E_ALNUM))) { return -1; } break; case E_DIGIT: case E_NDIGIT: if (!(Character.isDigit(c) == (opdata == E_DIGIT))) { return -1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -