in source/com.microsoft.tfs.core/src/com/microsoft/tfs/core/clients/workitem/internal/wiqlparse/Parser.java [18:296]
public static List<Node> parseLexems(final String input) {
if (input == null) {
throw new IllegalArgumentException("input must not be null"); //$NON-NLS-1$
}
final List<Node> lexems = new ArrayList<Node>();
final int length = input.length(); // "num1"
int currentPos = 0; // "num2"
while (currentPos < length) {
/*
* skip over any whitespace characters
*/
if (Character.isWhitespace(input.charAt(currentPos))) {
++currentPos;
continue;
}
/*
* name (unbracketed): starts with a letter or underscore
*/
if (Character.isLetter(input.charAt(currentPos)) || input.charAt(currentPos) == '_') {
Node node;
Boolean flag;
final int startIndex = currentPos;
while ((currentPos < length)
&& ((Character.isLetterOrDigit(input.charAt(currentPos)) || (input.charAt(currentPos) == '_'))
|| (input.charAt(currentPos) == '.'))) {
currentPos++;
}
if (input.charAt(currentPos - 1) == '.') {
currentPos--;
}
final String val = input.substring(startIndex, currentPos);
flag = Tools.TranslateBoolToken(val);
if (flag != null) {
node = new NodeBoolValue(flag.booleanValue());
} else {
node = new NodeName(val);
}
node.setStartOffset(startIndex);
node.setEndOffset(currentPos);
lexems.add(node);
continue;
}
/*
* variable (AKA macro): starts with a '@' character
*/
if (input.charAt(currentPos) == '@') {
/*
* move the current position past the '@' character
*/
final int startIx = ++currentPos;
/*
* read characters until we reach one that is not a letter or
* digit
*/
while ((currentPos < length) && Character.isLetterOrDigit(input.charAt(currentPos))) {
++currentPos;
}
final NodeVariable node = new NodeVariable(input.substring(startIx, currentPos));
node.setStartOffset(startIx - 1);
node.setEndOffset(currentPos);
lexems.add(node);
continue;
}
/*
* name (bracketed): starts with an opening square bracket
*/
if (input.charAt(currentPos) == '[') {
final int num5 = ++currentPos;
int num6 = length;
boolean flag2 = true;
while (currentPos < length) {
if (input.charAt(currentPos) == ']') {
num6 = currentPos++;
flag2 = false;
break;
}
currentPos++;
}
final NodeName name = new NodeName(input.substring(num5, num6));
name.setStartOffset(num5 - 1);
name.setEndOffset(num6 + 1);
if (flag2) {
throw new SyntaxException(name, SyntaxError.EXPECTING_CLOSING_SQUARE_BRACKET);
}
if (num5 == num6) {
throw new SyntaxException(name, SyntaxError.EMPTY_NAME);
}
lexems.add(name);
continue;
}
/*
* number: starts with a digit, or a '-' or '+' followed immediately
* by a digit
*/
if ((((input.charAt(currentPos) == '-') || (input.charAt(currentPos) == '+')) && (currentPos + 1) < length)
&& Character.isDigit(input.charAt(currentPos + 1)) || Character.isDigit(input.charAt(currentPos))) {
final int startIx = currentPos;
/*
* read past the starting '-' or '+' character if there is one
*/
if (input.charAt(currentPos) == '-' || input.charAt(currentPos) == '+') {
currentPos++;
}
/*
* read characters until we reach one that is not a digit
*/
while ((currentPos < length) && Character.isDigit(input.charAt(currentPos))) {
currentPos++;
}
/*
* if the next character is a '.' character ...
*/
if ((currentPos < length) && input.charAt(currentPos) == '.') {
/*
* ... move past it, and read characters until we reach one
* that is not a digit
*/
++currentPos;
while ((currentPos < length) && Character.isDigit(input.charAt(currentPos))) {
++currentPos;
}
}
/*
* if the next character is a 'e' or 'E' character ...
*/
if ((currentPos < length) && (input.charAt(currentPos) == 'e' || input.charAt(currentPos) == 'E')) {
/*
* ... move past it ...
*/
++currentPos;
/*
* ... read past a single '-' or '+' character, if one
* exists ...
*/
if ((currentPos < length) && (input.charAt(currentPos) == '-' || input.charAt(currentPos) == '+')) {
++currentPos;
}
/*
* ... and read characters until we reach one that is not a
* digit
*/
while ((currentPos < length) && Character.isDigit(input.charAt(currentPos))) {
++currentPos;
}
}
final NodeNumber node = new NodeNumber(input.substring(startIx, currentPos));
node.setStartOffset(startIx);
node.setEndOffset(currentPos);
lexems.add(node);
continue;
}
/*
* string (AKA quoted identifier): starts with a single-quote or a
* double-quote character
*/
if (input.charAt(currentPos) == '\'' || input.charAt(currentPos) == '\"') {
/*
* read past and record the starting quote character
*/
final char quoteCharacter = input.charAt(currentPos++);
final int startIx = currentPos;
int endIx = length;
/*
* read characters until we reach a closing quote character
*/
boolean didNotFindClosingQuoteCharacter = true;
while (currentPos < length) {
if (input.charAt(currentPos) == quoteCharacter) {
/*
* we have to handle this case carefully: this could be
* a closing quote character, or it could be an embedded
* (escaped) quote character
*/
/*
* move past it ...
*/
currentPos++;
/*
* ... if we're at the end of the string, or if the next
* character is NOT the quote character, then it really
* was a closing quote character
*/
if (currentPos == length || input.charAt(currentPos) != quoteCharacter) {
endIx = currentPos - 1;
didNotFindClosingQuoteCharacter = false;
break;
}
}
currentPos++;
}
String stringValue = input.substring(startIx, endIx);
/*
* replace any embedded (escaped) quote characters in the string
* with their non-escaped equivalents
*/
stringValue = stringValue.replaceAll(
("\\" + quoteCharacter + "\\" + quoteCharacter), //$NON-NLS-1$ //$NON-NLS-2$
String.valueOf(quoteCharacter));
final NodeString node = new NodeString(stringValue);
node.setStartOffset(startIx - 1);
node.setEndOffset(endIx + 1);
if (didNotFindClosingQuoteCharacter) {
throw new SyntaxException(node, SyntaxError.EXPECTING_CLOSING_QUOTE);
}
lexems.add(node);
continue;
}
/*
* two-character long operator
*/
if ((currentPos + 1 < length) && (
// "<=" or "<>"
(input.charAt(currentPos) == '<' && (input.charAt(currentPos + 1) == '=')
|| (input.charAt(currentPos + 1) == '>')) ||
// ">="
(input.charAt(currentPos) == '>' && input.charAt(currentPos + 1) == '=')
||
// "!="
(input.charAt(currentPos) == '!' && input.charAt(currentPos + 1) == '=') ||
// "==", "=<" , or "=>"
(input.charAt(currentPos) == '='
&& (input.charAt(currentPos + 1) == '='
|| input.charAt(currentPos + 1) == '<'
|| input.charAt(currentPos + 1) == '>'))
||
// "&&"
(input.charAt(currentPos) == '&' && input.charAt(currentPos + 1) == '&') ||
// "||"
(input.charAt(currentPos) == '|' && input.charAt(currentPos + 1) == '|'))) {
final NodeOperation node = new NodeOperation(input.substring(currentPos, currentPos + 2));
node.setStartOffset(currentPos);
node.setEndOffset(currentPos + 2);
lexems.add(node);
currentPos += 2;
}
/*
* one-character long operator
*/
else {
final NodeOperation node = new NodeOperation(input.substring(currentPos, currentPos + 1));
node.setStartOffset(currentPos);
node.setEndOffset(currentPos + 1);
lexems.add(node);
++currentPos;
}
}
return lexems;
}