/* * $Id: JSONParser.java,v 1.2 2008-08-07 01:18:55 parg Exp $ * Created on 2006-4-15 */ package org.json.simple.parser; import java.io.Reader; import java.util.Stack; import org.gudy.azureus2.core3.util.LightHashMap; import org.json.simple.JSONArray; import org.json.simple.JSONObject; /** * @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_ERROR=-1; private int peekStatus(Stack statusStack){ if(statusStack.size()==0) return -1; Integer status=(Integer)statusStack.peek(); return status.intValue(); } public Object parse(Reader in) throws Exception{ Stack statusStack=new Stack(); Stack valueStack=new Stack(); Yylex lexer=new Yylex(in); Yytoken token=null; int status=S_INIT; try{ do{ token=lexer.yylex(); if(token==null) token=new Yytoken(Yytoken.TYPE_EOF,null); switch(status){ case S_INIT: switch(token.type){ case Yytoken.TYPE_VALUE: status=S_IN_FINISHED_VALUE; statusStack.push(new Integer(status)); valueStack.push(token.value); break; case Yytoken.TYPE_LEFT_BRACE: status=S_IN_OBJECT; statusStack.push(new Integer(status)); valueStack.push(new JSONObject()); break; case Yytoken.TYPE_LEFT_SQUARE: status=S_IN_ARRAY; statusStack.push(new Integer(status)); valueStack.push(new JSONArray()); break; default: status=S_IN_ERROR; }//inner switch break; case S_IN_FINISHED_VALUE: if(token.type==Yytoken.TYPE_EOF) return valueStack.pop(); else return null; 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.push(key); status=S_PASSED_PAIR_KEY; statusStack.push(new Integer(status)); } else{ status=S_IN_ERROR; } break; case Yytoken.TYPE_RIGHT_BRACE: if(valueStack.size()>1){ statusStack.pop(); JSONObject map = (JSONObject)valueStack.pop(); map.compactify(-0.9f); 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.pop(); String key=(String)valueStack.pop(); JSONObject parent=(JSONObject)valueStack.peek(); parent.put(key,token.value); status=peekStatus(statusStack); break; case Yytoken.TYPE_LEFT_SQUARE: statusStack.pop(); key=(String)valueStack.pop(); parent=(JSONObject)valueStack.peek(); JSONArray newArray=new JSONArray(); parent.put(key,newArray); status=S_IN_ARRAY; statusStack.push(new Integer(status)); valueStack.push(newArray); break; case Yytoken.TYPE_LEFT_BRACE: statusStack.pop(); key=(String)valueStack.pop(); parent=(JSONObject)valueStack.peek(); JSONObject newObject=new JSONObject(); parent.put(key,newObject); status=S_IN_OBJECT; statusStack.push(new Integer(status)); valueStack.push(newObject); break; default: status=S_IN_ERROR; } break; case S_IN_ARRAY: switch(token.type){ case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: JSONArray val=(JSONArray)valueStack.peek(); val.add(token.value); break; case Yytoken.TYPE_RIGHT_SQUARE: if(valueStack.size()>1){ statusStack.pop(); valueStack.pop(); status=peekStatus(statusStack); } else{ status=S_IN_FINISHED_VALUE; } break; case Yytoken.TYPE_LEFT_BRACE: val=(JSONArray)valueStack.peek(); JSONObject newObject=new JSONObject(); val.add(newObject); status=S_IN_OBJECT; statusStack.push(new Integer(status)); valueStack.push(newObject); break; case Yytoken.TYPE_LEFT_SQUARE: val=(JSONArray)valueStack.peek(); JSONArray newArray=new JSONArray(); val.add(newArray); status=S_IN_ARRAY; statusStack.push(new Integer(status)); valueStack.push(newArray); break; default: status=S_IN_ERROR; }//inner switch break; case S_IN_ERROR: return null; }//switch if(status==S_IN_ERROR) return null; }while(token.type!=Yytoken.TYPE_EOF); } catch(Exception e){ throw e; } return null; } }