void lex()

in src/main/user-impl/java/com/mysql/cj/xdevapi/ExprParser.java [277:480]


    void lex() {
        for (int i = 0; i < this.string.length(); ++i) {
            int start = i; // for routines that consume more than one char
            char c = this.string.charAt(i);
            if (Character.isWhitespace(c)) {
                // ignore
            } else if (Character.isDigit(c)) {
                i = lexNumber(i);
            } else if (!(c == '_' || Character.isUnicodeIdentifierStart(c))) {
                // non-identifier, e.g. operator or quoted literal
                switch (c) {
                    case ':':
                        this.tokens.add(new Token(TokenType.COLON, c));
                        break;
                    case '+':
                        this.tokens.add(new Token(TokenType.PLUS, c));
                        break;
                    case '-':
                        if (nextCharEquals(i, '>')) {
                            i++;
                            this.tokens.add(new Token(TokenType.COLDOCPATH, "->"));
                        } else {
                            this.tokens.add(new Token(TokenType.MINUS, c));
                        }
                        break;
                    case '*':
                        if (nextCharEquals(i, '*')) {
                            i++;
                            this.tokens.add(new Token(TokenType.DOUBLESTAR, "**"));
                        } else {
                            this.tokens.add(new Token(TokenType.STAR, c));
                        }
                        break;
                    case '/':
                        this.tokens.add(new Token(TokenType.SLASH, c));
                        break;
                    case '$':
                        this.tokens.add(new Token(TokenType.DOLLAR, c));
                        break;
                    case '%':
                        this.tokens.add(new Token(TokenType.MOD, c));
                        break;
                    case '=':
                        if (nextCharEquals(i, '=')) {
                            i++;
                        }
                        this.tokens.add(new Token(TokenType.EQ, "=="));
                        break;
                    case '&':
                        if (nextCharEquals(i, '&')) {
                            i++;
                            this.tokens.add(new Token(TokenType.ANDAND, "&&"));
                        } else {
                            this.tokens.add(new Token(TokenType.BITAND, c));
                        }
                        break;
                    case '|':
                        if (nextCharEquals(i, '|')) {
                            i++;
                            this.tokens.add(new Token(TokenType.OROR, "||"));
                        } else {
                            this.tokens.add(new Token(TokenType.BITOR, c));
                        }
                        break;
                    case '^':
                        this.tokens.add(new Token(TokenType.BITXOR, c));
                        break;
                    case '(':
                        this.tokens.add(new Token(TokenType.LPAREN, c));
                        break;
                    case ')':
                        this.tokens.add(new Token(TokenType.RPAREN, c));
                        break;
                    case '[':
                        this.tokens.add(new Token(TokenType.LSQBRACKET, c));
                        break;
                    case ']':
                        this.tokens.add(new Token(TokenType.RSQBRACKET, c));
                        break;
                    case '{':
                        this.tokens.add(new Token(TokenType.LCURLY, c));
                        break;
                    case '}':
                        this.tokens.add(new Token(TokenType.RCURLY, c));
                        break;
                    case '~':
                        this.tokens.add(new Token(TokenType.NEG, c));
                        break;
                    case ',':
                        this.tokens.add(new Token(TokenType.COMMA, c));
                        break;
                    case '!':
                        if (nextCharEquals(i, '=')) {
                            i++;
                            this.tokens.add(new Token(TokenType.NE, "!="));
                        } else {
                            this.tokens.add(new Token(TokenType.BANG, c));
                        }
                        break;
                    case '?':
                        this.tokens.add(new Token(TokenType.EROTEME, c));
                        break;
                    case '<':
                        if (nextCharEquals(i, '<')) {
                            i++;
                            this.tokens.add(new Token(TokenType.LSHIFT, "<<"));
                        } else if (nextCharEquals(i, '=')) {
                            i++;
                            this.tokens.add(new Token(TokenType.LE, "<="));
                        } else {
                            this.tokens.add(new Token(TokenType.LT, c));
                        }
                        break;
                    case '>':
                        if (nextCharEquals(i, '>')) {
                            i++;
                            this.tokens.add(new Token(TokenType.RSHIFT, ">>"));
                        } else if (nextCharEquals(i, '=')) {
                            i++;
                            this.tokens.add(new Token(TokenType.GE, ">="));
                        } else {
                            this.tokens.add(new Token(TokenType.GT, c));
                        }
                        break;
                    case '.':
                        if (nextCharEquals(i, '*')) {
                            i++;
                            this.tokens.add(new Token(TokenType.DOTSTAR, ".*"));
                        } else if (i + 1 < this.string.length() && Character.isDigit(this.string.charAt(i + 1))) {
                            i = lexNumber(i);
                        } else {
                            this.tokens.add(new Token(TokenType.DOT, c));
                        }
                        break;
                    case '"':
                    case '\'':
                    case '`':
                        char quoteChar = c;
                        StringBuilder val = new StringBuilder();
                        try {
                            boolean escapeNextChar = false;
                            for (c = this.string.charAt(++i); c != quoteChar || escapeNextChar
                                    || i + 1 < this.string.length() && this.string.charAt(i + 1) == quoteChar; c = this.string.charAt(++i)) {
                                if (escapeNextChar) {
                                    if (escapeChars.containsKey(c)) {
                                        val.append(escapeChars.get(c));
                                    } else if (c == 'u') {
                                        // \\u[4 hex digits] represents a unicode code point (ISO/IEC 10646)
                                        char[] buf = new char[4];
                                        this.string.getChars(++i, i + 4, buf, 0);
                                        String hexCodePoint = String.valueOf(buf);
                                        try {
                                            val.append((char) Integer.parseInt(hexCodePoint, 16));
                                        } catch (NumberFormatException e) {
                                            throw new WrongArgumentException("Invalid Unicode code point '" + hexCodePoint + "'");
                                        }
                                        i += 3;
                                    } else {
                                        val.append('\\').append(c);
                                    }
                                    escapeNextChar = false;
                                } else if (c == '\\' || c == quoteChar) { // Escape sequence or two consecutive quotes
                                    escapeNextChar = true;
                                } else {
                                    val.append(c);
                                }
                            }
                            if (escapeNextChar) {
                                throw new WrongArgumentException("Unterminated escape sequence at " + i);
                            }
                        } catch (StringIndexOutOfBoundsException ex) {
                            throw new WrongArgumentException("Unterminated string starting at " + start);
                        }
                        this.tokens.add(new Token(quoteChar == '`' ? TokenType.IDENT : TokenType.LSTRING, val.toString()));
                        break;
                    default:
                        throw new WrongArgumentException("Can't parse at position " + i);
                }
            } else {
                // otherwise, it's an identifier
                for (; i < this.string.length() && Character.isUnicodeIdentifierPart(this.string.charAt(i)); ++i) {
                }
                String val = this.string.substring(start, i);
                String valLower = val.toLowerCase();
                if (i < this.string.length()) {
                    // last char, this logic is artifact of the preceding loop
                    --i;
                }
                if (reservedWords.containsKey(valLower)) {
                    // Map operator names to values the server understands
                    if ("and".equals(valLower)) {
                        this.tokens.add(new Token(reservedWords.get(valLower), "&&"));
                    } else if ("or".equals(valLower)) {
                        this.tokens.add(new Token(reservedWords.get(valLower), "||"));
                    } else {
                        // we case-normalize reserved words
                        this.tokens.add(new Token(reservedWords.get(valLower), valLower));
                    }
                } else {
                    this.tokens.add(new Token(TokenType.IDENT, val));
                }
            }
        }
    }