mirror of
https://github.com/2006-Scape/Parabot.git
synced 2026-07-03 08:39:09 +00:00
Moved to Maven
This commit is contained in:
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $
|
||||
* Created on 2006-4-15
|
||||
*/
|
||||
package org.json.simple.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
/**
|
||||
* Parser for JSON text. Please note that JSONParser is NOT thread-safe.
|
||||
*
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public class JSONParser {
|
||||
public static final int S_INIT = 0;
|
||||
public static final int S_IN_FINISHED_VALUE = 1;// string,number,boolean,null,object,array
|
||||
public static final int S_IN_OBJECT = 2;
|
||||
public static final int S_IN_ARRAY = 3;
|
||||
public static final int S_PASSED_PAIR_KEY = 4;
|
||||
public static final int S_IN_PAIR_VALUE = 5;
|
||||
public static final int S_END = 6;
|
||||
public static final int S_IN_ERROR = -1;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private LinkedList handlerStatusStack;
|
||||
private Yylex lexer = new Yylex((Reader) null);
|
||||
private Yytoken token = null;
|
||||
private int status = S_INIT;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private int peekStatus(LinkedList statusStack) {
|
||||
if (statusStack.size() == 0)
|
||||
return -1;
|
||||
Integer status = (Integer) statusStack.getFirst();
|
||||
return status.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the parser to the initial state without resetting the underlying
|
||||
* reader.
|
||||
*
|
||||
*/
|
||||
public void reset() {
|
||||
token = null;
|
||||
status = S_INIT;
|
||||
handlerStatusStack = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the parser to the initial state with a new character reader.
|
||||
*
|
||||
* @param in
|
||||
* - The new character reader.
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
*/
|
||||
public void reset(Reader in) {
|
||||
lexer.yyreset(in);
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The position of the beginning of the current token.
|
||||
*/
|
||||
public int getPosition() {
|
||||
return lexer.getPosition();
|
||||
}
|
||||
|
||||
public Object parse(String s) throws ParseException {
|
||||
return parse(s, (ContainerFactory) null);
|
||||
}
|
||||
|
||||
public Object parse(String s, ContainerFactory containerFactory)
|
||||
throws ParseException {
|
||||
StringReader in = new StringReader(s);
|
||||
try {
|
||||
return parse(in, containerFactory);
|
||||
} catch (IOException ie) {
|
||||
/*
|
||||
* Actually it will never happen.
|
||||
*/
|
||||
throw new ParseException(-1,
|
||||
ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
|
||||
}
|
||||
}
|
||||
|
||||
public Object parse(Reader in) throws IOException, ParseException {
|
||||
return parse(in, (ContainerFactory) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON text into java object from the input source.
|
||||
*
|
||||
* @param in
|
||||
* @param containerFactory
|
||||
* - Use this factory to createyour own JSON object and JSON
|
||||
* array containers.
|
||||
* @return Instance of the following: org.json.simple.JSONObject,
|
||||
* org.json.simple.JSONArray, java.lang.String, java.lang.Number,
|
||||
* java.lang.Boolean, null
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Object parse(Reader in, ContainerFactory containerFactory)
|
||||
throws IOException, ParseException {
|
||||
reset(in);
|
||||
LinkedList statusStack = new LinkedList();
|
||||
LinkedList valueStack = new LinkedList();
|
||||
|
||||
try {
|
||||
do {
|
||||
nextToken();
|
||||
switch (status) {
|
||||
case S_INIT:
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_VALUE:
|
||||
status = S_IN_FINISHED_VALUE;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack.addFirst(token.value);
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_BRACE:
|
||||
status = S_IN_OBJECT;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack
|
||||
.addFirst(createObjectContainer(containerFactory));
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_SQUARE:
|
||||
status = S_IN_ARRAY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack
|
||||
.addFirst(createArrayContainer(containerFactory));
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
}// inner switch
|
||||
break;
|
||||
|
||||
case S_IN_FINISHED_VALUE:
|
||||
if (token.type == Yytoken.TYPE_EOF)
|
||||
return valueStack.removeFirst();
|
||||
else
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
|
||||
case S_IN_OBJECT:
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_COMMA:
|
||||
break;
|
||||
case Yytoken.TYPE_VALUE:
|
||||
if (token.value instanceof String) {
|
||||
String key = (String) token.value;
|
||||
valueStack.addFirst(key);
|
||||
status = S_PASSED_PAIR_KEY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
} else {
|
||||
status = S_IN_ERROR;
|
||||
}
|
||||
break;
|
||||
case Yytoken.TYPE_RIGHT_BRACE:
|
||||
if (valueStack.size() > 1) {
|
||||
statusStack.removeFirst();
|
||||
valueStack.removeFirst();
|
||||
status = peekStatus(statusStack);
|
||||
} else {
|
||||
status = S_IN_FINISHED_VALUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
break;
|
||||
}// inner switch
|
||||
break;
|
||||
|
||||
case S_PASSED_PAIR_KEY:
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_COLON:
|
||||
break;
|
||||
case Yytoken.TYPE_VALUE:
|
||||
statusStack.removeFirst();
|
||||
String key = (String) valueStack.removeFirst();
|
||||
Map parent = (Map) valueStack.getFirst();
|
||||
parent.put(key, token.value);
|
||||
status = peekStatus(statusStack);
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_SQUARE:
|
||||
statusStack.removeFirst();
|
||||
key = (String) valueStack.removeFirst();
|
||||
parent = (Map) valueStack.getFirst();
|
||||
List newArray = createArrayContainer(containerFactory);
|
||||
parent.put(key, newArray);
|
||||
status = S_IN_ARRAY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack.addFirst(newArray);
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_BRACE:
|
||||
statusStack.removeFirst();
|
||||
key = (String) valueStack.removeFirst();
|
||||
parent = (Map) valueStack.getFirst();
|
||||
Map newObject = createObjectContainer(containerFactory);
|
||||
parent.put(key, newObject);
|
||||
status = S_IN_OBJECT;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack.addFirst(newObject);
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case S_IN_ARRAY:
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_COMMA:
|
||||
break;
|
||||
case Yytoken.TYPE_VALUE:
|
||||
List val = (List) valueStack.getFirst();
|
||||
val.add(token.value);
|
||||
break;
|
||||
case Yytoken.TYPE_RIGHT_SQUARE:
|
||||
if (valueStack.size() > 1) {
|
||||
statusStack.removeFirst();
|
||||
valueStack.removeFirst();
|
||||
status = peekStatus(statusStack);
|
||||
} else {
|
||||
status = S_IN_FINISHED_VALUE;
|
||||
}
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_BRACE:
|
||||
val = (List) valueStack.getFirst();
|
||||
Map newObject = createObjectContainer(containerFactory);
|
||||
val.add(newObject);
|
||||
status = S_IN_OBJECT;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack.addFirst(newObject);
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_SQUARE:
|
||||
val = (List) valueStack.getFirst();
|
||||
List newArray = createArrayContainer(containerFactory);
|
||||
val.add(newArray);
|
||||
status = S_IN_ARRAY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
valueStack.addFirst(newArray);
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
}// inner switch
|
||||
break;
|
||||
case S_IN_ERROR:
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}// switch
|
||||
if (status == S_IN_ERROR) {
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}
|
||||
} while (token.type != Yytoken.TYPE_EOF);
|
||||
} catch (IOException ie) {
|
||||
throw ie;
|
||||
}
|
||||
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}
|
||||
|
||||
private void nextToken() throws ParseException, IOException {
|
||||
token = lexer.yylex();
|
||||
if (token == null)
|
||||
token = new Yytoken(Yytoken.TYPE_EOF, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Map createObjectContainer(ContainerFactory containerFactory) {
|
||||
if (containerFactory == null)
|
||||
return new JSONObject();
|
||||
Map m = containerFactory.createObjectContainer();
|
||||
|
||||
if (m == null)
|
||||
return new JSONObject();
|
||||
return m;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private List createArrayContainer(ContainerFactory containerFactory) {
|
||||
if (containerFactory == null)
|
||||
return new JSONArray();
|
||||
List l = containerFactory.creatArrayContainer();
|
||||
|
||||
if (l == null)
|
||||
return new JSONArray();
|
||||
return l;
|
||||
}
|
||||
|
||||
public void parse(String s, ContentHandler contentHandler)
|
||||
throws ParseException {
|
||||
parse(s, contentHandler, false);
|
||||
}
|
||||
|
||||
public void parse(String s, ContentHandler contentHandler, boolean isResume)
|
||||
throws ParseException {
|
||||
StringReader in = new StringReader(s);
|
||||
try {
|
||||
parse(in, contentHandler, isResume);
|
||||
} catch (IOException ie) {
|
||||
/*
|
||||
* Actually it will never happen.
|
||||
*/
|
||||
throw new ParseException(-1,
|
||||
ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
|
||||
}
|
||||
}
|
||||
|
||||
public void parse(Reader in, ContentHandler contentHandler)
|
||||
throws IOException, ParseException {
|
||||
parse(in, contentHandler, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream processing of JSON text.
|
||||
*
|
||||
* @see ContentHandler
|
||||
*
|
||||
* @param in
|
||||
* @param contentHandler
|
||||
* @param isResume
|
||||
* - Indicates if it continues previous parsing operation. If set
|
||||
* to true, resume parsing the old stream, and parameter 'in'
|
||||
* will be ignored. If this method is called for the first time
|
||||
* in this instance, isResume will be ignored.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void parse(Reader in, ContentHandler contentHandler, boolean isResume)
|
||||
throws IOException, ParseException {
|
||||
if (!isResume) {
|
||||
reset(in);
|
||||
handlerStatusStack = new LinkedList();
|
||||
} else {
|
||||
if (handlerStatusStack == null) {
|
||||
isResume = false;
|
||||
reset(in);
|
||||
handlerStatusStack = new LinkedList();
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList statusStack = handlerStatusStack;
|
||||
|
||||
try {
|
||||
do {
|
||||
switch (status) {
|
||||
case S_INIT:
|
||||
contentHandler.startJSON();
|
||||
nextToken();
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_VALUE:
|
||||
status = S_IN_FINISHED_VALUE;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.primitive(token.value))
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_BRACE:
|
||||
status = S_IN_OBJECT;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startObject())
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_SQUARE:
|
||||
status = S_IN_ARRAY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startArray())
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
}// inner switch
|
||||
break;
|
||||
|
||||
case S_IN_FINISHED_VALUE:
|
||||
nextToken();
|
||||
if (token.type == Yytoken.TYPE_EOF) {
|
||||
contentHandler.endJSON();
|
||||
status = S_END;
|
||||
return;
|
||||
} else {
|
||||
status = S_IN_ERROR;
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}
|
||||
|
||||
case S_IN_OBJECT:
|
||||
nextToken();
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_COMMA:
|
||||
break;
|
||||
case Yytoken.TYPE_VALUE:
|
||||
if (token.value instanceof String) {
|
||||
String key = (String) token.value;
|
||||
status = S_PASSED_PAIR_KEY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startObjectEntry(key))
|
||||
return;
|
||||
} else {
|
||||
status = S_IN_ERROR;
|
||||
}
|
||||
break;
|
||||
case Yytoken.TYPE_RIGHT_BRACE:
|
||||
if (statusStack.size() > 1) {
|
||||
statusStack.removeFirst();
|
||||
status = peekStatus(statusStack);
|
||||
} else {
|
||||
status = S_IN_FINISHED_VALUE;
|
||||
}
|
||||
if (!contentHandler.endObject())
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
break;
|
||||
}// inner switch
|
||||
break;
|
||||
|
||||
case S_PASSED_PAIR_KEY:
|
||||
nextToken();
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_COLON:
|
||||
break;
|
||||
case Yytoken.TYPE_VALUE:
|
||||
statusStack.removeFirst();
|
||||
status = peekStatus(statusStack);
|
||||
if (!contentHandler.primitive(token.value))
|
||||
return;
|
||||
if (!contentHandler.endObjectEntry())
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_SQUARE:
|
||||
statusStack.removeFirst();
|
||||
statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
|
||||
status = S_IN_ARRAY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startArray())
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_BRACE:
|
||||
statusStack.removeFirst();
|
||||
statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
|
||||
status = S_IN_OBJECT;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startObject())
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case S_IN_PAIR_VALUE:
|
||||
/*
|
||||
* S_IN_PAIR_VALUE is just a marker to indicate the end of
|
||||
* an object entry, it doesn't proccess any token, therefore
|
||||
* delay consuming token until next round.
|
||||
*/
|
||||
statusStack.removeFirst();
|
||||
status = peekStatus(statusStack);
|
||||
if (!contentHandler.endObjectEntry())
|
||||
return;
|
||||
break;
|
||||
|
||||
case S_IN_ARRAY:
|
||||
nextToken();
|
||||
switch (token.type) {
|
||||
case Yytoken.TYPE_COMMA:
|
||||
break;
|
||||
case Yytoken.TYPE_VALUE:
|
||||
if (!contentHandler.primitive(token.value))
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_RIGHT_SQUARE:
|
||||
if (statusStack.size() > 1) {
|
||||
statusStack.removeFirst();
|
||||
status = peekStatus(statusStack);
|
||||
} else {
|
||||
status = S_IN_FINISHED_VALUE;
|
||||
}
|
||||
if (!contentHandler.endArray())
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_BRACE:
|
||||
status = S_IN_OBJECT;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startObject())
|
||||
return;
|
||||
break;
|
||||
case Yytoken.TYPE_LEFT_SQUARE:
|
||||
status = S_IN_ARRAY;
|
||||
statusStack.addFirst(new Integer(status));
|
||||
if (!contentHandler.startArray())
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
status = S_IN_ERROR;
|
||||
}// inner switch
|
||||
break;
|
||||
|
||||
case S_END:
|
||||
return;
|
||||
|
||||
case S_IN_ERROR:
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}// switch
|
||||
if (status == S_IN_ERROR) {
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}
|
||||
} while (token.type != Yytoken.TYPE_EOF);
|
||||
} catch (IOException ie) {
|
||||
status = S_IN_ERROR;
|
||||
throw ie;
|
||||
} catch (ParseException pe) {
|
||||
status = S_IN_ERROR;
|
||||
throw pe;
|
||||
} catch (RuntimeException re) {
|
||||
status = S_IN_ERROR;
|
||||
throw re;
|
||||
} catch (Error e) {
|
||||
status = S_IN_ERROR;
|
||||
throw e;
|
||||
}
|
||||
|
||||
status = S_IN_ERROR;
|
||||
throw new ParseException(getPosition(),
|
||||
ParseException.ERROR_UNEXPECTED_TOKEN, token);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user