package org.textmapper.json;
import java.io.IOException;
import java.text.MessageFormat;
import org.textmapper.json.JsonLexer.ErrorReporter;
import org.textmapper.json.JsonLexer.Span;
import org.textmapper.json.JsonLexer.Tokens;
public class JsonParser {
public static class ParseException extends Exception {
private static final long serialVersionUID = 1L;
public ParseException() {
}
}
private final ErrorReporter reporter;
public JsonParser(ErrorReporter reporter) {
this.reporter = reporter;
}
private static final boolean DEBUG_SYNTAX = false;
private static final int[] tmAction = JsonLexer.unpack_int(28,
"\uffff\uffff\uffff\uffff\uffff\uffff\6\0\7\0\1\0\2\0\3\0\0\0\4\0\5\0\11\0\uffff\uffff" +
"\13\0\uffff\uffff\16\0\17\0\uffff\uffff\uffff\uffff\10\0\uffff\uffff\15\0\uffff\uffff" +
"\12\0\14\0\20\0\uffff\uffff\ufffe\uffff");
private static final int[] lapg_sym_goto = JsonLexer.unpack_int(21,
"\0\0\1\0\5\0\7\0\13\0\15\0\16\0\20\0\20\0\26\0\32\0\36\0\42\0\46\0\47\0\53\0\57\0" +
"\61\0\62\0\66\0\67\0");
private static final int[] lapg_sym_from = JsonLexer.unpack_int(55,
"\32\0\0\0\2\0\22\0\26\0\1\0\16\0\0\0\2\0\22\0\26\0\2\0\21\0\14\0\16\0\21\0\0\0\1" +
"\0\2\0\22\0\24\0\26\0\0\0\2\0\22\0\26\0\0\0\2\0\22\0\26\0\0\0\2\0\22\0\26\0\0\0\2" +
"\0\22\0\26\0\0\0\0\0\2\0\22\0\26\0\0\0\2\0\22\0\26\0\1\0\24\0\1\0\0\0\2\0\22\0\26" +
"\0\2\0");
private static final int[] lapg_sym_to = JsonLexer.unpack_int(55,
"\33\0\1\0\1\0\1\0\1\0\13\0\23\0\2\0\2\0\2\0\2\0\17\0\25\0\22\0\24\0\26\0\3\0\14\0" +
"\3\0\3\0\14\0\3\0\4\0\4\0\4\0\4\0\5\0\5\0\5\0\5\0\6\0\6\0\6\0\6\0\7\0\7\0\7\0\7\0" +
"\32\0\10\0\20\0\27\0\31\0\11\0\11\0\11\0\11\0\15\0\30\0\16\0\12\0\12\0\12\0\12\0" +
"\21\0");
private static final int[] tmRuleLen = JsonLexer.unpack_int(17,
"\1\0\1\0\1\0\1\0\1\0\1\0\1\0\1\0\3\0\2\0\3\0\1\0\3\0\3\0\2\0\1\0\3\0");
private static final int[] tmRuleSymbol = JsonLexer.unpack_int(17,
"\15\0\16\0\16\0\16\0\16\0\16\0\16\0\16\0\17\0\17\0\20\0\21\0\21\0\22\0\22\0\23\0" +
"\23\0");
protected static final String[] tmSymbolNames = new String[] {
"eoi",
"'{'",
"'}'",
"'['",
"']'",
"':'",
"','",
"space",
"JSONString",
"JSONNumber",
"'null'",
"'true'",
"'false'",
"JSONText",
"JSONValue",
"JSONObject",
"JSONMember",
"JSONMemberList",
"JSONArray",
"JSONElementList",
};
public interface Nonterminals extends Tokens {
// non-terminals
int JSONText = 13;
int JSONValue = 14;
int JSONObject = 15;
int JSONMember = 16;
int JSONMemberList = 17;
int JSONArray = 18;
int JSONElementList = 19;
}
/**
* -3-n Lookahead (state id)
* -2 Error
* -1 Shift
* 0..n Reduce (rule index)
*/
protected static int tmAction(int state, int symbol) {
return tmAction[state];
}
protected static int tmGoto(int state, int symbol) {
int min = lapg_sym_goto[symbol], max = lapg_sym_goto[symbol + 1] - 1;
int i, e;
while (min <= max) {
e = (min + max) >> 1;
i = lapg_sym_from[e];
if (i == state) {
return lapg_sym_to[e];
} else if (i < state) {
min = e + 1;
} else {
max = e - 1;
}
}
return -1;
}
protected int tmHead;
protected Span[] tmStack;
protected Span tmNext;
protected JsonLexer tmLexer;
public Object parse(JsonLexer lexer) throws IOException, ParseException {
tmLexer = lexer;
tmStack = new Span[1024];
tmHead = 0;
tmStack[0] = new Span();
tmStack[0].state = 0;
tmNext = tmLexer.next();
while (tmStack[tmHead].state != 27) {
int action = tmAction(tmStack[tmHead].state, tmNext.symbol);
if (action >= 0) {
reduce(action);
} else if (action == -1) {
shift();
}
if (action == -2 || tmStack[tmHead].state == -1) {
break;
}
}
if (tmStack[tmHead].state != 27) {
reporter.error(MessageFormat.format("syntax error before line {0}",
tmLexer.getTokenLine()), tmNext.line, tmNext.offset, tmNext.endoffset);
throw new ParseException();
}
return tmStack[tmHead - 1].value;
}
protected void shift() throws IOException {
tmStack[++tmHead] = tmNext;
tmStack[tmHead].state = tmGoto(tmStack[tmHead - 1].state, tmNext.symbol);
if (DEBUG_SYNTAX) {
System.out.println(MessageFormat.format("shift: {0} ({1})", tmSymbolNames[tmNext.symbol], tmLexer.tokenText()));
}
if (tmStack[tmHead].state != -1 && tmNext.symbol != 0) {
tmNext = tmLexer.next();
}
}
protected void reduce(int rule) {
Span left = new Span();
left.value = (tmRuleLen[rule] != 0) ? tmStack[tmHead + 1 - tmRuleLen[rule]].value : null;
left.symbol = tmRuleSymbol[rule];
left.state = 0;
if (DEBUG_SYNTAX) {
System.out.println("reduce to " + tmSymbolNames[tmRuleSymbol[rule]]);
}
Span startsym = (tmRuleLen[rule] != 0) ? tmStack[tmHead + 1 - tmRuleLen[rule]] : tmNext;
left.line = startsym.line;
left.offset = startsym.offset;
left.endoffset = (tmRuleLen[rule] != 0) ? tmStack[tmHead].endoffset : tmNext.offset;
applyRule(left, rule, tmRuleLen[rule]);
for (int e = tmRuleLen[rule]; e > 0; e--) {
tmStack[tmHead--] = null;
}
tmStack[++tmHead] = left;
tmStack[tmHead].state = tmGoto(tmStack[tmHead - 1].state, left.symbol);
}
@SuppressWarnings("unchecked")
protected void applyRule(Span tmLeft, int ruleIndex, int ruleLength) {
}
}