// Length of atom
int lenAtom = 0;
// Loop while we've got input
FastStringBuffer fsb = new FastStringBuffer(FastStringBuffer.SMALL);
atomLoop:
while (idx < len) {
// Is there a next char?
if ((idx + 1) < len) {
int c = pattern.charAt(idx + 1);
// If the next 'char' is an escape, look past the whole escape
if (pattern.charAt(idx) == '\\') {
int idxEscape = idx;
escape(false);
if (idx < len) {
c = pattern.charAt(idx);
}
idx = idxEscape;
}
// Switch on next char
switch (c) {
case '{':
case '?':
case '*':
case '+':
// If the next character is a quantifier operator and our atom is non-empty, the
// current character should bind to the quantifier operator rather than the atom
if (lenAtom != 0) {
break atomLoop;
}
}
}
// Switch on current char
switch (pattern.charAt(idx)) {
case ']':
case '.':
case '[':
case '(':
case ')':
case '|':
break atomLoop;
case '{':
case '?':
case '*':
case '+':
// We should have an atom by now
if (lenAtom == 0) {
// No atom before quantifier
syntaxError("No expression before quantifier");
}
break atomLoop;
case '\\': {
// Get the escaped character (advances input automatically)
int idxBeforeEscape = idx;
IntPredicate charClass = escape(false);
// Check if it's a simple escape (as opposed to, say, a backreference)
if (charClass instanceof BackReference || !(charClass instanceof IntValuePredicate)) {
// Not a simple escape, so backup to where we were before the escape.
idx = idxBeforeEscape;
break atomLoop;
}
// Add escaped char to atom
fsb.appendWideChar(((IntValuePredicate) charClass).getTarget());
lenAtom++;
break;
}
case '^':
case '$':
if (isXPath) {
break atomLoop;
}
// else fall through ($ is not a metacharacter in XSD)
default:
// Add normal character to atom
fsb.appendWideChar(pattern.charAt(idx++));
lenAtom++;
break;
}
}
// This shouldn't happen
if (fsb.length() == 0) {
internalError();
}
// Emit the instruction into the program
node.atom = GeneralUnicodeString.makeUnicodeString(fsb.condense());
return appendNode(node);
}