luaformatter/src/neoe/tools/LuaTokens.java

179 lines
3.7 KiB
Java

package neoe.tools;
import java.util.Arrays;
import java.util.List;
public class LuaTokens {
private String txt;
private int p;
private LuaTokenType type;
public LuaTokens(String txt) {
this.txt = txt;
this.p = 0;
}
StringBuilder sb = new StringBuilder();
public Object[] next() {
if (p >= txt.length())
return null;
sb.setLength(0);
char c = txt.charAt(p);
if (isSpace(c)) {
type = LuaTokenType.SPACE;
sb.append(c);
p++;
char c2;
while (p < txt.length()) {
if (isSpace(c2 = txt.charAt(p))) {
sb.append(c2);
p++;
} else {
break;
}
}
return submit(type, sb.toString());
} else if (isIdentifier(c) || (/* negtive number */c == '-' && Character.isDigit(peek(1)))) {
type = LuaTokenType.IDENTIFIER;
sb.append(c);
p++;
char c2;
while (p < txt.length()) {
if (isIdentifier(c2 = txt.charAt(p))) {
sb.append(c2);
p++;
} else {
break;
}
}
return submit(type, sb.toString());
} else if (c == '-' && peek(1) == '-') {
type = LuaTokenType.COMMENT;
sb.append("--");
p += 2;
int level = peekLongBrackets();
if (level < 0) {
readUntil("\n");
if (p < txt.length()) {
sb.setLength(sb.length() - 1);
p--;
}
} else {
readUntilLongBrackets(level);
}
return submit(type, sb.toString());
} else if (c == '\'' || c == '"') {
type = LuaTokenType.STRING;
sb.append(c);
p++;
while (true) {
if (p >= txt.length())
break;
char c2 = txt.charAt(p++);
sb.append(c2);
if (c2 == c) {
break;
} else if (c2 == '\\') {
sb.append(txt.charAt(p++));
}
}
// readUntil("" + (char) c);
return submit(type, sb.toString());
} else {
int level = peekLongBrackets();
if (level < 0) {
type = LuaTokenType.OPERATOR;
sb.append(c);
p++;
while (true) {
String t = sb.toString() + (char) peek(0);
if (longOperaters.contains(t)) {
sb.append(txt.charAt(p++));
} else {
break;
}
}
return submit(type, sb.toString());
} else {
type = LuaTokenType.STRING;
readUntilLongBrackets(level);
return submit(type, sb.toString());
}
}
}
final static List<String> longOperaters = Arrays.asList(new String[] { "<=", ">=", "==", "~=", "//", ">>", "<<" });
// private boolean isOp1(char c) {
// return "[]{}()".indexOf(c) >= 0;
// }
private Object[] submit(LuaTokenType type, String s) {
return new Object[] { type, s };
}
// private boolean isOperator(char c) {
// return !isIdentifier(c) && !isSpace(c) && c != '"' && c != '\'' && !isOp1(c);
// }
private void readUntilLongBrackets(int level) {
// sb.append("<LV:" + level + ">");
StringBuilder sb = new StringBuilder("]");
for (int i = 0; i < level; i++) {
sb.append('=');
}
sb.append(']');
readUntil(sb.toString());
}
private int peekLongBrackets() {
if (peek(0) == '[') {
int lv = 0;
while (peek(lv + 1) == '=') {
lv++;
}
if (peek(1 + lv) == '[') {
return lv;
}
}
return -1;
}
private void readUntil(String s) {
int p1 = txt.indexOf(s, p);
if (p1 < 0) {
sb.append(txt.substring(p));
p = txt.length();
} else {
sb.append(txt.substring(p, p1 + s.length()));
p = p1 + s.length();
}
}
private char peek(int i) {
if (p + i >= txt.length())
return 0;
return txt.charAt(p + i);
}
private boolean isIdentifier(char c) {
return Character.isDigit(c) || Character.isLetter(c) || c == '_';
}
private boolean isSpace(char c) {
return Character.isWhitespace(c);
}
}