using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SQLFormatter
{
class SqlParser
{
private String fBefore;
private char fChar;
private int fPos;
private static String[] twoCharacterSymbol = { "<>", "<=", ">=", "||" };
public SqlParser() {
}
public static bool isSpace(char argChar) {
return argChar == ' ' || argChar == '\t' || argChar == '\n'
|| argChar == '\r' || argChar == 65535;
}
public static bool isLetter(char argChar) {
if (isSpace(argChar)) {
return false;
}
if (isDigit(argChar)) {
return false;
}
if (isSymbol(argChar)) {
return false;
}
return true;
}
public static bool isDigit(char argChar) {
return '0' <= argChar && argChar <= '9';
}
public static bool isSymbol(char argChar) {
switch (argChar) {
case '"':
case '?':
case '%':
case '&':
case '\'':
case '(':
case ')':
case '|':
case '*':
case '+':
case ',':
case '-':
case '.':
case '/':
case ':':
case ';':
case '<':
case '=':
case '>':
return true;
default:
return false;
}
}
SqlToken nextToken() {
int start_pos = fPos;
if (fPos >= fBefore.Length) {
fPos++;
return new SqlToken(SqlTokenConstants.END, "",
start_pos);
}
fChar = fBefore[fPos];
if (isSpace(fChar)) {
String workString = "";
for (;;) {
workString += fChar;
fChar = fBefore[fPos];
if (!isSpace(fChar)) {
return new SqlToken(SqlTokenConstants.SPACE,
workString, start_pos);
}
fPos++;
if (fPos >= fBefore.Length) {
return new SqlToken(SqlTokenConstants.SPACE,
workString, start_pos);
}
}
} else if (fChar == ';') {
fPos++;
return new SqlToken(SqlTokenConstants.SYMBOL, ";",
start_pos);
} else if (isDigit(fChar)) {
String s = "";
while (isDigit(fChar) || fChar == '.') {
s += fChar;
fPos++;
if (fPos >= fBefore.Length) {
break;
}
fChar = fBefore[fPos];
}
return new SqlToken(SqlTokenConstants.VALUE, s,
start_pos);
} else if (isLetter(fChar)) {
String s = "";
while (isLetter(fChar) || isDigit(fChar) || fChar == '.') {
s += fChar;
fPos++;
if (fPos >= fBefore.Length) {
break;
}
fChar = fBefore[fPos];
}
for (int i = 0; i < SqlConstants.SQL_RESERVED_WORDS.Length; i++) {
if(string.Compare(s, SqlConstants.SQL_RESERVED_WORDS[i], true) == 0){
return new SqlToken(SqlTokenConstants.KEYWORD, s, start_pos);
}
}
return new SqlToken(SqlTokenConstants.NAME, s, start_pos);
}
else if (fChar == '-') {
fPos++;
char ch2 = fBefore[fPos];
if (ch2 != '-') {
return new SqlToken(SqlTokenConstants.SYMBOL, "-", start_pos);
}
fPos++;
String s = "--";
for (;;) {
fChar = fBefore[fPos];
s += fChar;
fPos++;
if (fChar == '\n' || fPos >= fBefore.Length) {
return new SqlToken(SqlTokenConstants.COMMENT, s, start_pos);
}
}
}
else if (fChar == '/') {
fPos++;
char ch2 = fBefore[fPos];
if (ch2 != '*') {
return new SqlToken(SqlTokenConstants.SYMBOL, "/",
start_pos);
}
String s = "/*";
fPos++;
int ch0 = -1;
for (;;) {
ch0 = fChar;
fChar = fBefore[fPos];
s += fChar;
fPos++;
if (ch0 == '*' && fChar == '/') {
return new SqlToken(SqlTokenConstants.COMMENT,
s, start_pos);
}
}
} else if (fChar == '\'') {
fPos++;
String s = "'";
for (;;) {
fChar = fBefore[fPos];
s += fChar;
fPos++;
if (fChar == '\'') {
return new SqlToken(SqlTokenConstants.VALUE, s,
start_pos);
}
}
} else if (fChar == '\"') {
fPos++;
String s = "\"";
for (;;) {
fChar = fBefore[fPos];
s += fChar;
fPos++;
if (fChar == '\"') {
return new SqlToken(SqlTokenConstants.NAME, s,
start_pos);
}
}
}
else if (isSymbol(fChar)) {
String s = "" + fChar;
fPos++;
if (fPos >= fBefore.Length) {
return new SqlToken(SqlTokenConstants.SYMBOL, s,
start_pos);
}
char ch2 = fBefore[fPos];
for (int i = 0; i < twoCharacterSymbol.Length; i++) {
if (twoCharacterSymbol[i][0] == fChar
&& twoCharacterSymbol[i][1] == ch2) {
fPos++;
s += ch2;
break;
}
}
return new SqlToken(SqlTokenConstants.SYMBOL, s,
start_pos);
} else {
fPos++;
return new SqlToken(SqlTokenConstants.UNKNOWN, ""
+ fChar, start_pos);
}
}
public List<SqlToken> parse(String argSql)
{
fPos = 0;
fBefore = argSql;
List<SqlToken> list = new List<SqlToken>();
for (; ; )
{
SqlToken token = nextToken();
if (token.getType() == SqlTokenConstants.END)
{
break;
}
list.Add(token);
}
return list;
}
}
}