package loon.utils;
import loon.BaseIO;
/*
* 工具类,用来解析python游戏的配置数据
*/
public class ParsePythonData {
static ObjectMap<Object, Object> cache;
final static char EOF = (char) -1;
public synchronized static Object parseString(String str) throws Exception {
if (cache == null) {
cache = new ObjectMap<Object, Object>();
}
Object o = cache.get(str);
if (o == null) {
o = new ParsePythonData().parseAll(new ArrayByte(str.getBytes()));
cache.put(str, o);
}
return o;
}
public synchronized static Object parseFile(String file) throws Exception {
if (cache == null) {
cache = new ObjectMap<Object, Object>();
}
Object o = cache.get(file);
if (o == null) {
o = new ParsePythonData().parseAll(BaseIO.loadArrayByte(file));
cache.put(file, o);
}
return o;
}
private StringBuffer buf = new StringBuffer();
private int lineNo = 1, pos;
private Object parse(ArrayByte in) throws Exception {
char i = readA(in);
if (i == '/') {
char flag = xread(in);
if (flag == '*') {
skipUtil(in, "*/");
i = readA(in);
} else {
pushBack(flag);
}
}
if (i == EOF) {
return null;
}
if (i == '{') {
ObjectMap<Object, Object> m = new ObjectMap<Object, Object>();
readMap(in, m, '}');
return m;
}
if (i == '[') {
TArray<Object> l = new TArray<Object>();
readList(in, l, ']');
return l;
}
if (i == '(') {
TArray<Object> l = new TArray<Object>();
readList(in, l, ')');
return l;
}
if (i == '"') {
String s = readString(in, '"');
return s;
}
if (i == '\'') {
String s = readString(in, '\'');
return s;
}
return readNumber(in, i);
}
public Object parseAll(ArrayByte in) throws Exception {
Object o = parse(in);
char i = readA(in);
if (i == EOF) {
in.close();
return o;
}
in.close();
return o;
}
private void pushBack(char c) {
buf.append(c);
}
private void confirm(char i, char c) throws Exception {
if (i != c) {
throw new Exception("Expected to read " + c + " but " + i + "("
+ ((int) i) + ") found" + at());
}
}
private void confirm(ArrayByte in, char c) throws Exception {
char i = readA(in);
confirm(i, c);
}
private char read(ArrayByte in) throws Exception {
char c = (char) in.read();
if (c == '\n') {
lineNo++;
pos = 0;
} else {
pos++;
}
return c;
}
private char readA(ArrayByte in) throws Exception {
char i = xread(in);
for (;;) {
while (i == '\n' || i == '\r' || i == ' ' || i == '\t') {
i = xread(in);
}
if (i == '/') {
char flag = xread(in);
if (flag == '*') {
skipUtil(in, "*/");
i = xread(in);
} else {
pushBack(flag);
return i;
}
} else {
return i;
}
}
}
private Object readNumber(ArrayByte in, char first) throws Exception {
StringBuffer sbr = new StringBuffer();
sbr.append(first);
for (;;) {
char i = xread(in);
if (i == EOF || i == ' ' || i == '\n' || i == '\r' || i == '\t'
|| i == ',' || i == '}' || i == ')' || i == ']' || i == ':') {
pushBack(i);
break;
}
sbr.append(i);
}
return sbr.toString();
}
private void readList(ArrayByte in, TArray<Object> l, char end)
throws Exception {
for (;;) {
char i = readA(in);
if (i == EOF) {
throw new Exception("Expected to read " + end
+ " but EOF found" + at());
}
if (i == end) {
return;
}
pushBack(i);
Object e = parse(in);
l.add(e);
i = readA(in);
if (i == end) {
return;
}
confirm(i, ',');
}
}
private void readMap(ArrayByte in, ObjectMap<Object, Object> m, char end)
throws Exception {
for (;;) {
char i = readA(in);
if (i == EOF) {
throw new Exception("Expected to read " + end
+ " but EOF found" + at());
}
if (i == end) {
return;
}
pushBack(i);
Object key = parse(in);
confirm(in, ':');
Object value = parse(in);
m.put(key, value);
i = readA(in);
if (i == end) {
return;
}
confirm(i, ',');
}
}
private String readString(ArrayByte in, char end) throws Exception {
StringBuffer sb = new StringBuffer();
char i = xread(in);
for (;;) {
if (i == end) {
char flag = xread(in);
if (flag == end && (flag == '"' || flag == '\'')) {
sb.append(flag);
i = xread(in);
continue;
} else {
pushBack(flag);
break;
}
}
if (i == '\\') {
i = xread(in);
}
if (i == EOF) {
throw new Exception("Expected to read " + end
+ " but EOF found" + at());
}
sb.append(i);
i = xread(in);
}
return sb.toString();
}
private char xread(ArrayByte in) throws Exception {
int len = buf.length();
if (len > 0) {
char i = buf.charAt(len - 1);
buf.setLength(len - 1);
return i;
}
return read(in);
}
private String at() {
return " at line:" + lineNo + " pos:" + pos;
}
private void skipUtil(ArrayByte in, String end) throws Exception {
LoopStringBuilder loopBuilder = new LoopStringBuilder(end.length());
for (;;) {
char b;
if ((b = xread(in)) == EOF) {
return;
}
loopBuilder.add(b);
if (loopBuilder.get().equals(end)) {
break;
}
}
}
}