/* * Copyright 1999-2017 Alibaba Group Holding Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.druid.sql.dialect.odps.parser; import static com.alibaba.druid.sql.parser.CharTypes.isFirstIdentifierChar; import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar; import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI; import java.util.HashMap; import java.util.Map; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.NotAllowCommentException; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.Token; public class OdpsLexer extends Lexer { public final static Keywords DEFAULT_ODPS_KEYWORDS; static { Map<String, Token> map = new HashMap<String, Token>(); map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords()); map.put("SHOW", Token.SHOW); map.put("PARTITION", Token.PARTITION); map.put("PARTITIONED", Token.PARTITIONED); map.put("OVERWRITE", Token.OVERWRITE); map.put("OVER", Token.OVER); map.put("LIMIT", Token.LIMIT); map.put("IF", Token.IF); map.put("DISTRIBUTE", Token.DISTRIBUTE); map.put("TRUE", Token.TRUE); map.put("FALSE", Token.FALSE); DEFAULT_ODPS_KEYWORDS = new Keywords(map); } public OdpsLexer(String input){ super(input); super.keywods = DEFAULT_ODPS_KEYWORDS; } public OdpsLexer(String input, boolean skipComment, boolean keepComments){ super(input, skipComment); this.skipComment = skipComment; this.keepComments = keepComments; super.keywods = DEFAULT_ODPS_KEYWORDS; } public OdpsLexer(String input, CommentHandler commentHandler){ super(input, commentHandler); super.keywods = DEFAULT_ODPS_KEYWORDS; } public void scanComment() { if (ch != '/' && ch != '-') { throw new IllegalStateException(); } Token lastToken = this.token; mark = pos; bufPos = 0; scanChar(); // /*+ */ if (ch == '*') { scanChar(); bufPos++; while (ch == ' ') { scanChar(); bufPos++; } boolean isHint = false; int startHintSp = bufPos + 1; if (ch == '+') { isHint = true; scanChar(); bufPos++; } for (;;) { if (ch == '*' && charAt(pos + 1) == '/') { bufPos += 2; scanChar(); scanChar(); break; } scanChar(); bufPos++; } if (isHint) { stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1); token = Token.HINT; } else { stringVal = subString(mark, bufPos + 1); token = Token.MULTI_LINE_COMMENT; commentCount++; if (keepComments) { addComment(stringVal); } } if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { return; } if (token != Token.HINT && !isAllowComment()) { throw new NotAllowCommentException(); } return; } if (!isAllowComment()) { throw new NotAllowCommentException(); } if (ch == '/' || ch == '-') { scanChar(); bufPos++; for (;;) { if (ch == '\r') { if (charAt(pos + 1) == '\n') { line++; bufPos += 2; scanChar(); break; } bufPos++; break; } else if (ch == EOI) { break; } if (ch == '\n') { line++; scanChar(); bufPos++; break; } scanChar(); bufPos++; } stringVal = subString(mark, ch != EOI ? bufPos : bufPos + 1); token = Token.LINE_COMMENT; commentCount++; if (keepComments) { addComment(stringVal); } endOfComment = isEOF(); if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { return; } return; } } public void scanIdentifier() { final char first = ch; if (first == '`') { mark = pos; bufPos = 1; char ch; for (;;) { ch = charAt(++pos); if (ch == '`') { bufPos++; ch = charAt(++pos); break; } else if (ch == EOI) { throw new ParserException("illegal identifier"); } bufPos++; continue; } this.ch = charAt(pos); stringVal = subString(mark, bufPos); token = Token.IDENTIFIER; return; } final boolean firstFlag = isFirstIdentifierChar(first); if (!firstFlag) { throw new ParserException("illegal identifier"); } mark = pos; bufPos = 1; char ch; for (;;) { ch = charAt(++pos); if (!isIdentifierChar(ch)) { break; } bufPos++; continue; } this.ch = charAt(pos); if (ch == '@') { // for user identifier, like email, xx@alibaba-inc.com bufPos++; for (;;) { ch = charAt(++pos); if (ch != '-' && ch != '.' && !isIdentifierChar(ch)) { break; } bufPos++; continue; } } this.ch = charAt(pos); stringVal = addSymbol(); Token tok = keywods.getKeyword(stringVal); if (tok != null) { token = tok; } else { token = Token.IDENTIFIER; } } public void scanNumber() { mark = pos; if (ch == '-') { bufPos++; ch = charAt(++pos); } for (;;) { if (ch >= '0' && ch <= '9') { bufPos++; } else { break; } ch = charAt(++pos); } boolean isDouble = false; if (ch == '.') { if (charAt(pos + 1) == '.') { token = Token.LITERAL_INT; return; } bufPos++; ch = charAt(++pos); isDouble = true; for (;;) { if (ch >= '0' && ch <= '9') { bufPos++; } else { break; } ch = charAt(++pos); } } if (ch == 'e' || ch == 'E') { bufPos++; ch = charAt(++pos); if (ch == '+' || ch == '-') { bufPos++; ch = charAt(++pos); } for (;;) { if (ch >= '0' && ch <= '9') { bufPos++; } else { break; } ch = charAt(++pos); } isDouble = true; } if (isDouble) { token = Token.LITERAL_FLOAT; } else { if (isFirstIdentifierChar(ch) && !(ch == 'b' && bufPos == 1 && charAt(pos - 1) == '0')) { bufPos++; for (;;) { ch = charAt(++pos); if (!isIdentifierChar(ch)) { break; } bufPos++; continue; } stringVal = addSymbol(); token = Token.IDENTIFIER; } else { token = Token.LITERAL_INT; } } } public void scanVariable() { if (ch == ':') { token = Token.COLON; ch = charAt(++pos); return; } super.scanVariable(); } protected final void scanString() { scanString2(); } protected final void scanAlias() { scanAlias2(); } }