/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.parser.sql.dialect.mysql.parser;
import static com.alipay.zdal.parser.sql.parser.CharTypes.isFirstIdentifierChar;
import static com.alipay.zdal.parser.sql.parser.CharTypes.isIdentifierChar;
import static com.alipay.zdal.parser.sql.parser.LayoutCharacters.EOI;
import static com.alipay.zdal.parser.sql.parser.Token.LITERAL_CHARS;
import java.util.HashMap;
import java.util.Map;
import com.alipay.zdal.parser.sql.parser.Keywords;
import com.alipay.zdal.parser.sql.parser.Lexer;
import com.alipay.zdal.parser.sql.parser.NotAllowCommentException;
import com.alipay.zdal.parser.sql.parser.SQLParserException;
import com.alipay.zdal.parser.sql.parser.Token;
/**
*
* @author ����
* @version $Id: MySqlLexer.java, v 0.1 2012-11-17 ����3:40:13 Exp $
*/
public class MySqlLexer extends Lexer {
public final static Keywords DEFAULT_MYSQL_KEYWORDS;
static {
Map<String, Token> map = new HashMap<String, Token>();
map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());
map.put("DUAL", Token.DUAL);
map.put("FALSE", Token.FALSE);
map.put("IDENTIFIED", Token.IDENTIFIED);
map.put("IF", Token.IF);
map.put("KILL", Token.KILL);
map.put("LIMIT", Token.LIMIT);
map.put("TRUE", Token.TRUE);
DEFAULT_MYSQL_KEYWORDS = new Keywords(map);
}
public MySqlLexer(char[] input, int inputLength, boolean skipComment) {
super(input, inputLength, skipComment);
super.keywods = DEFAULT_MYSQL_KEYWORDS;
}
public MySqlLexer(String input) {
super(input);
super.keywods = DEFAULT_MYSQL_KEYWORDS;
}
public void scanVariable() {
final char first = ch;
if (ch != '@' && ch != ':' && ch != '#' && ch != '$') {
throw new SQLParserException("illegal variable");
}
int hash = first;
np = bp;
sp = 1;
if (buf[bp + 1] == '@') {
ch = buf[++bp];
hash = 31 * hash + ch;
sp++;
}
if (buf[bp + 1] == '`') {
++bp;
++sp;
char ch;
for (;;) {
ch = buf[++bp];
if (ch == '`') {
sp++;
ch = buf[++bp];
break;
} else if (ch == EOI) {
throw new SQLParserException("illegal identifier");
}
hash = 31 * hash + ch;
sp++;
continue;
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
token = Token.VARIANT;
} else if (buf[bp + 1] == '{') {
++bp;
++sp;
char ch;
for (;;) {
ch = buf[++bp];
if (ch == '}') {
sp++;
ch = buf[++bp];
break;
} else if (ch == EOI) {
throw new SQLParserException("illegal identifier");
}
hash = 31 * hash + ch;
sp++;
continue;
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
token = Token.VARIANT;
} else {
for (;;) {
ch = buf[++bp];
if (!isIdentifierChar(ch)) {
break;
}
hash = 31 * hash + ch;
sp++;
continue;
}
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
token = Token.VARIANT;
}
public void scanIdentifier() {
final char first = ch;
if (ch == '`') {
int hash = first;
np = bp;
sp = 1;
char ch;
for (;;) {
ch = buf[++bp];
if (ch == '`') {
sp++;
ch = buf[++bp];
break;
} else if (ch == EOI) {
throw new SQLParserException("illegal identifier");
}
hash = 31 * hash + ch;
sp++;
continue;
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
Token tok = keywods.getKeyword(stringVal);
if (tok != null) {
token = tok;
} else {
token = Token.IDENTIFIER;
}
} else {
final boolean firstFlag = isFirstIdentifierChar(first);
if (!firstFlag) {
throw new SQLParserException("illegal identifier");
}
int hash = first;
np = bp;
sp = 1;
char ch;
for (;;) {
ch = buf[++bp];
if (!isIdentifierChar(ch)) {
break;
}
hash = 31 * hash + ch;
sp++;
continue;
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
Token tok = keywods.getKeyword(stringVal);
if (tok != null) {
token = tok;
} else {
token = Token.IDENTIFIER;
}
}
}
protected void scanString() {
np = bp;
boolean hasSpecial = false;
for (;;) {
if (bp >= buflen) {
lexError(tokenPos, "unclosed.str.lit");
return;
}
ch = buf[++bp];
if (ch == '\\') {
scanChar();
if (!hasSpecial) {
System.arraycopy(buf, np + 1, sbuf, 0, sp);
hasSpecial = true;
}
switch (ch) {
case '\0':
putChar('\0');
break;
case '\'':
putChar('\'');
break;
case '"':
putChar('"');
break;
case 'b':
putChar('\b');
break;
case 'n':
putChar('\n');
break;
case 'r':
putChar('\r');
break;
case 't':
putChar('\t');
break;
case '\\':
putChar('\\');
break;
case 'Z':
putChar((char) 0x1A); // ctrl + Z
break;
default:
putChar(ch);
break;
}
scanChar();
}
if (ch == '\'') {
scanChar();
if (ch != '\'') {
token = LITERAL_CHARS;
break;
} else {
System.arraycopy(buf, np + 1, sbuf, 0, sp);
hasSpecial = true;
putChar('\'');
continue;
}
}
if (!hasSpecial) {
sp++;
continue;
}
if (sp == sbuf.length) {
putChar(ch);
} else {
sbuf[sp++] = ch;
}
}
if (!hasSpecial) {
stringVal = new String(buf, np + 1, sp);
} else {
stringVal = new String(sbuf, 0, sp);
}
}
public void scanComment() {
if (ch != '/' && ch != '-') {
throw new IllegalStateException();
}
np = bp;
sp = 0;
scanChar();
// /*+ */
if (ch == '*') {
scanChar();
sp++;
while (ch == ' ') {
scanChar();
sp++;
}
boolean isHint = false;
int startHintSp = sp + 1;
if (ch == '!') {
isHint = true;
scanChar();
sp++;
}
for (;;) {
if (ch == '*' && buf[bp + 1] == '/') {
sp += 2;
scanChar();
scanChar();
break;
}
scanChar();
sp++;
}
if (isHint) {
stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 1);
token = Token.HINT;
} else {
stringVal = new String(buf, np, sp);
token = Token.MULTI_LINE_COMMENT;
}
if (token != Token.HINT && !isAllowComment()) {
throw new NotAllowCommentException();
}
return;
}
if (!isAllowComment()) {
throw new NotAllowCommentException();
}
if (ch == '/' || ch == '-') {
scanChar();
sp++;
for (;;) {
if (ch == '\r') {
if (buf[bp + 1] == '\n') {
sp += 2;
scanChar();
break;
}
sp++;
break;
} else if (ch == EOI) {
break;
}
if (ch == '\n') {
scanChar();
sp++;
break;
}
scanChar();
sp++;
}
stringVal = new String(buf, np + 1, sp);
token = Token.LINE_COMMENT;
return;
}
}
}