package org.h2.util;
public class ParserUtil {
public static final int KEYWORD = 1;
public static final int IDENTIFIER = 2;
public static final int ALL = IDENTIFIER + 1;
public static final int ARRAY = ALL + 1;
public static final int CASE = ARRAY + 1;
public static final int CHECK = CASE + 1;
public static final int CONSTRAINT = CHECK + 1;
public static final int CROSS = CONSTRAINT + 1;
public static final int CURRENT_DATE = CROSS + 1;
public static final int CURRENT_TIME = CURRENT_DATE + 1;
public static final int CURRENT_TIMESTAMP = CURRENT_TIME + 1;
public static final int CURRENT_USER = CURRENT_TIMESTAMP + 1;
public static final int DISTINCT = CURRENT_USER + 1;
public static final int EXCEPT = DISTINCT + 1;
public static final int EXISTS = EXCEPT + 1;
public static final int FALSE = EXISTS + 1;
public static final int FETCH = FALSE + 1;
public static final int FOR = FETCH + 1;
public static final int FOREIGN = FOR + 1;
public static final int FROM = FOREIGN + 1;
public static final int FULL = FROM + 1;
public static final int GROUP = FULL + 1;
public static final int HAVING = GROUP + 1;
public static final int IF = HAVING + 1;
public static final int INNER = IF + 1;
public static final int INTERSECT = INNER + 1;
public static final int INTERSECTS = INTERSECT + 1;
public static final int INTERVAL = INTERSECTS + 1;
public static final int IS = INTERVAL + 1;
public static final int JOIN = IS + 1;
public static final int LIKE = JOIN + 1;
public static final int LIMIT = LIKE + 1;
public static final int LOCALTIME = LIMIT + 1;
public static final int LOCALTIMESTAMP = LOCALTIME + 1;
public static final int MINUS = LOCALTIMESTAMP + 1;
public static final int NATURAL = MINUS + 1;
public static final int NOT = NATURAL + 1;
public static final int NULL = NOT + 1;
public static final int OFFSET = NULL + 1;
public static final int ON = OFFSET + 1;
public static final int ORDER = ON + 1;
public static final int PRIMARY = ORDER + 1;
public static final int QUALIFY = PRIMARY + 1;
public static final int ROW = QUALIFY + 1;
public static final int _ROWID_ = ROW + 1;
public static final int ROWNUM = _ROWID_ + 1;
public static final int SELECT = ROWNUM + 1;
public static final int TABLE = SELECT + 1;
public static final int TRUE = TABLE + 1;
public static final int UNION = TRUE + 1;
public static final int UNIQUE = UNION + 1;
public static final int VALUES = UNIQUE + 1;
public static final int WHERE = VALUES + 1;
public static final int WINDOW = WHERE + 1;
public static final int WITH = WINDOW + 1;
private static final int UPPER_OR_OTHER_LETTER =
1 << Character.UPPERCASE_LETTER
| 1 << Character.MODIFIER_LETTER
| 1 << Character.OTHER_LETTER;
private static final int UPPER_OR_OTHER_LETTER_OR_DIGIT =
UPPER_OR_OTHER_LETTER
| 1 << Character.DECIMAL_DIGIT_NUMBER;
private static final int LOWER_OR_OTHER_LETTER =
1 << Character.LOWERCASE_LETTER
| 1 << Character.MODIFIER_LETTER
| 1 << Character.OTHER_LETTER;
private static final int LOWER_OR_OTHER_LETTER_OR_DIGIT =
LOWER_OR_OTHER_LETTER
| 1 << Character.DECIMAL_DIGIT_NUMBER;
private static final int LETTER =
1 << Character.UPPERCASE_LETTER
| 1 << Character.LOWERCASE_LETTER
| 1 << Character.TITLECASE_LETTER
| 1 << Character.MODIFIER_LETTER
| 1 << Character.OTHER_LETTER;
private static final int LETTER_OR_DIGIT =
LETTER
| 1 << Character.DECIMAL_DIGIT_NUMBER;
private ParserUtil() {
}
public static boolean isKeyword(String s, boolean ignoreCase) {
int length = s.length();
if (length == 0) {
return false;
}
return getSaveTokenType(s, ignoreCase, 0, length, false) != IDENTIFIER;
}
public static boolean isSimpleIdentifier(String s, boolean databaseToUpper, boolean databaseToLower) {
int length = s.length();
if (length == 0) {
return false;
}
int startFlags, partFlags;
if (databaseToUpper) {
if (databaseToLower) {
throw new IllegalArgumentException("databaseToUpper && databaseToLower");
} else {
startFlags = UPPER_OR_OTHER_LETTER;
partFlags = UPPER_OR_OTHER_LETTER_OR_DIGIT;
}
} else {
if (databaseToLower) {
startFlags = LOWER_OR_OTHER_LETTER;
partFlags = LOWER_OR_OTHER_LETTER_OR_DIGIT;
} else {
startFlags = LETTER;
partFlags = LETTER_OR_DIGIT;
}
}
char c = s.charAt(0);
if ((startFlags >>> Character.getType(c) & 1) == 0 && c != '_') {
return false;
}
for (int i = 1; i < length; i++) {
c = s.charAt(i);
if ((partFlags >>> Character.getType(c) & 1) == 0 && c != '_') {
return false;
}
}
return getSaveTokenType(s, !databaseToUpper, 0, length, true) == IDENTIFIER;
}
public static int getSaveTokenType(String s, boolean ignoreCase, int start, int end, boolean additionalKeywords) {
char c = s.charAt(start);
if (ignoreCase) {
c &= 0xffdf;
}
switch (c) {
case 'A':
if (eq("ALL", s, ignoreCase, start, end)) {
return ALL;
} else if (eq("ARRAY", s, ignoreCase, start, end)) {
return ARRAY;
}
if (additionalKeywords) {
if (eq("AND", s, ignoreCase, start, end) || eq("AS", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'B':
if (additionalKeywords) {
if (eq("BETWEEN", s, ignoreCase, start, end) || eq("BOTH", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'C':
if (eq("CASE", s, ignoreCase, start, end)) {
return CASE;
} else if (eq("CHECK", s, ignoreCase, start, end)) {
return CHECK;
} else if (eq("CONSTRAINT", s, ignoreCase, start, end)) {
return CONSTRAINT;
} else if (eq("CROSS", s, ignoreCase, start, end)) {
return CROSS;
} else if (eq("CURRENT_DATE", s, ignoreCase, start, end)) {
return CURRENT_DATE;
} else if (eq("CURRENT_TIME", s, ignoreCase, start, end)) {
return CURRENT_TIME;
} else if (eq("CURRENT_TIMESTAMP", s, ignoreCase, start, end)) {
return CURRENT_TIMESTAMP;
} else if (eq("CURRENT_USER", s, ignoreCase, start, end)) {
return CURRENT_USER;
}
return IDENTIFIER;
case 'D':
if (eq("DISTINCT", s, ignoreCase, start, end)) {
return DISTINCT;
}
return IDENTIFIER;
case 'E':
if (eq("EXCEPT", s, ignoreCase, start, end)) {
return EXCEPT;
} else if (eq("EXISTS", s, ignoreCase, start, end)) {
return EXISTS;
}
return IDENTIFIER;
case 'F':
if (eq("FETCH", s, ignoreCase, start, end)) {
return FETCH;
} else if (eq("FROM", s, ignoreCase, start, end)) {
return FROM;
} else if (eq("FOR", s, ignoreCase, start, end)) {
return FOR;
} else if (eq("FOREIGN", s, ignoreCase, start, end)) {
return FOREIGN;
} else if (eq("FULL", s, ignoreCase, start, end)) {
return FULL;
} else if (eq("FALSE", s, ignoreCase, start, end)) {
return FALSE;
}
if (additionalKeywords) {
if (eq("FILTER", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'G':
if (eq("GROUP", s, ignoreCase, start, end)) {
return GROUP;
}
if (additionalKeywords) {
if (eq("GROUPS", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'H':
if (eq("HAVING", s, ignoreCase, start, end)) {
return HAVING;
}
return IDENTIFIER;
case 'I':
if (eq("IF", s, ignoreCase, start, end)) {
return IF;
} else if (eq("INNER", s, ignoreCase, start, end)) {
return INNER;
} else if (eq("INTERSECT", s, ignoreCase, start, end)) {
return INTERSECT;
} else if (eq("INTERSECTS", s, ignoreCase, start, end)) {
return INTERSECTS;
} else if (eq("INTERVAL", s, ignoreCase, start, end)) {
return INTERVAL;
} else if (eq("IS", s, ignoreCase, start, end)) {
return IS;
}
if (additionalKeywords) {
if (eq("ILIKE", s, ignoreCase, start, end) || eq("IN", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'J':
if (eq("JOIN", s, ignoreCase, start, end)) {
return JOIN;
}
return IDENTIFIER;
case 'L':
if (eq("LIMIT", s, ignoreCase, start, end)) {
return LIMIT;
} else if (eq("LIKE", s, ignoreCase, start, end)) {
return LIKE;
} else if (eq("LOCALTIME", s, ignoreCase, start, end)) {
return LOCALTIME;
} else if (eq("LOCALTIMESTAMP", s, ignoreCase, start, end)) {
return LOCALTIMESTAMP;
}
if (additionalKeywords) {
if (eq("LEADING", s, ignoreCase, start, end) || eq("LEFT", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'M':
if (eq("MINUS", s, ignoreCase, start, end)) {
return MINUS;
}
return IDENTIFIER;
case 'N':
if (eq("NOT", s, ignoreCase, start, end)) {
return NOT;
} else if (eq("NATURAL", s, ignoreCase, start, end)) {
return NATURAL;
} else if (eq("NULL", s, ignoreCase, start, end)) {
return NULL;
}
return IDENTIFIER;
case 'O':
if (eq("OFFSET", s, ignoreCase, start, end)) {
return OFFSET;
} else if (eq("ON", s, ignoreCase, start, end)) {
return ON;
} else if (eq("ORDER", s, ignoreCase, start, end)) {
return ORDER;
}
if (additionalKeywords) {
if (eq("OR", s, ignoreCase, start, end) || eq("OVER", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'P':
if (eq("PRIMARY", s, ignoreCase, start, end)) {
return PRIMARY;
}
if (additionalKeywords) {
if (eq("PARTITION", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'Q':
if (eq("QUALIFY", s, ignoreCase, start, end)) {
return QUALIFY;
}
return IDENTIFIER;
case 'R':
if (eq("ROW", s, ignoreCase, start, end)) {
return ROW;
} else if (eq("ROWNUM", s, ignoreCase, start, end)) {
return ROWNUM;
}
if (additionalKeywords) {
if (eq("RANGE", s, ignoreCase, start, end) || eq("REGEXP", s, ignoreCase, start, end)
|| eq("ROWS", s, ignoreCase, start, end) || eq("RIGHT", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'S':
if (eq("SELECT", s, ignoreCase, start, end)) {
return SELECT;
}
if (additionalKeywords) {
if (eq("SYSDATE", s, ignoreCase, start, end) || eq("SYSTIME", s, ignoreCase, start, end)
|| eq("SYSTIMESTAMP", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'T':
if (eq("TABLE", s, ignoreCase, start, end)) {
return TABLE;
} else if (eq("TRUE", s, ignoreCase, start, end)) {
return TRUE;
}
if (additionalKeywords) {
if (eq("TODAY", s, ignoreCase, start, end) || eq("TOP", s, ignoreCase, start, end)
|| eq("TRAILING", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'U':
if (eq("UNIQUE", s, ignoreCase, start, end)) {
return UNIQUE;
} else if (eq("UNION", s, ignoreCase, start, end)) {
return UNION;
}
return IDENTIFIER;
case 'V':
if (eq("VALUES", s, ignoreCase, start, end)) {
return VALUES;
}
return IDENTIFIER;
case 'W':
if (eq("WHERE", s, ignoreCase, start, end)) {
return WHERE;
} else if (eq("WINDOW", s, ignoreCase, start, end)) {
return WINDOW;
} else if (eq("WITH", s, ignoreCase, start, end)) {
return WITH;
}
return IDENTIFIER;
case '_':
if (end - start == 7 && "_ROWID_".regionMatches(ignoreCase, 0, s, start, 7)) {
return _ROWID_;
}
default:
return IDENTIFIER;
}
}
private static boolean eq(String expected, String s, boolean ignoreCase, int start, int end) {
int len = expected.length();
return end - start == len && expected.regionMatches(ignoreCase, 1, s, start + 1, len - 1);
}
}