001/* Copyright 2006 FangYidong 002 003 Licensed under the Apache License, Version 2.0 (the "License"); 004 you may not use this file except in compliance with the License. 005 You may obtain a copy of the License at 006 007 http://www.apache.org/licenses/LICENSE-2.0 008 009 Unless required by applicable law or agreed to in writing, software 010 distributed under the License is distributed on an "AS IS" BASIS, 011 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 See the License for the specific language governing permissions and 013 limitations under the License. */ 014package org.json.simple.parser; 015 016import java.io.IOException; 017import java.io.Reader; 018import java.io.StringReader; 019import java.util.LinkedList; 020import java.util.List; 021import java.util.Map; 022 023import org.json.simple.JSONArray; 024import org.json.simple.JSONObject; 025 026 027/** 028 * Parser for JSON text. Please note that JSONParser is NOT thread-safe. 029 * 030 * @author FangYidong<fangyidong@yahoo.com.cn> 031 * @deprecated since 2.0.0, copied to a new package {@link org.json.simple.Jsoner}. 032 */ 033@Deprecated 034public class JSONParser { 035 /** 036 * description omitted. 037 */ 038 public static final int S_INIT=0; 039 /** 040 * description omitted. 041 */ 042 public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array 043 /** 044 * description omitted. 045 */ 046 public static final int S_IN_OBJECT=2; 047 /** 048 * description omitted. 049 */ 050 public static final int S_IN_ARRAY=3; 051 /** 052 * description omitted. 053 */ 054 public static final int S_PASSED_PAIR_KEY=4; 055 /** 056 * description omitted. 057 */ 058 public static final int S_IN_PAIR_VALUE=5; 059 /** 060 * description omitted. 061 */ 062 public static final int S_END=6; 063 /** 064 * description omitted. 065 */ 066 public static final int S_IN_ERROR=-1; 067 068 private LinkedList handlerStatusStack; 069 private Yylex lexer = new Yylex((Reader)null); 070 private Yytoken token = null; 071 private int status = S_INIT; 072 073 private int peekStatus(LinkedList statusStack){ 074 if(statusStack.size()==0) 075 return -1; 076 Integer status=(Integer)statusStack.getFirst(); 077 return status.intValue(); 078 } 079 080 /** 081 * Reset the parser to the initial state without resetting the underlying reader. 082 * 083 */ 084 public void reset(){ 085 token = null; 086 status = S_INIT; 087 handlerStatusStack = null; 088 } 089 090 /** 091 * Reset the parser to the initial state with a new character reader. 092 * 093 * @param in - The new character reader. 094 */ 095 public void reset(Reader in){ 096 lexer.yyreset(in); 097 reset(); 098 } 099 100 /** 101 * @return The position of the beginning of the current token. 102 */ 103 public int getPosition(){ 104 return lexer.getPosition(); 105 } 106 107 /** 108 * description omitted. 109 * 110 * @param s description omitted. 111 * @return description omitted. 112 * @throws ParseException description omitted. 113 */ 114 public Object parse(String s) throws ParseException{ 115 return parse(s, (ContainerFactory)null); 116 } 117 118 /** 119 * description omitted. 120 * 121 * @param s description omitted. 122 * @param containerFactory description omitted. 123 * @return description omitted. 124 * @throws ParseException description omitted. 125 */ 126 public Object parse(String s, ContainerFactory containerFactory) throws ParseException{ 127 StringReader in=new StringReader(s); 128 try{ 129 return parse(in, containerFactory); 130 } 131 catch(IOException ie){ 132 /* 133 * Actually it will never happen. 134 */ 135 throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); 136 } 137 } 138 139 /** 140 * description omitted. 141 * 142 * @param in description omitted. 143 * @return description omitted. 144 * @throws IOException description omitted. 145 * @throws ParseException description omitted. 146 */ 147 public Object parse(Reader in) throws IOException, ParseException{ 148 return parse(in, (ContainerFactory)null); 149 } 150 151 /** 152 * Parse JSON text into java object from the input source. 153 * 154 * @param in description omitted. 155 * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers. 156 * @return Instance of the following: 157 * org.json.simple.JSONObject, 158 * org.json.simple.JSONArray, 159 * java.lang.String, 160 * java.lang.Number, 161 * java.lang.Boolean, 162 * null 163 * 164 * @throws IOException description omitted. 165 * @throws ParseException description omitted. 166 */ 167 public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{ 168 reset(in); 169 LinkedList statusStack = new LinkedList(); 170 LinkedList valueStack = new LinkedList(); 171 172 try{ 173 do{ 174 nextToken(); 175 switch(status){ 176 case S_INIT: 177 switch(token.type){ 178 case Yytoken.TYPE_VALUE: 179 status=S_IN_FINISHED_VALUE; 180 statusStack.addFirst(new Integer(status)); 181 valueStack.addFirst(token.value); 182 break; 183 case Yytoken.TYPE_LEFT_BRACE: 184 status=S_IN_OBJECT; 185 statusStack.addFirst(new Integer(status)); 186 valueStack.addFirst(createObjectContainer(containerFactory)); 187 break; 188 case Yytoken.TYPE_LEFT_SQUARE: 189 status=S_IN_ARRAY; 190 statusStack.addFirst(new Integer(status)); 191 valueStack.addFirst(createArrayContainer(containerFactory)); 192 break; 193 default: 194 status=S_IN_ERROR; 195 }//inner switch 196 break; 197 198 case S_IN_FINISHED_VALUE: 199 if(token.type==Yytoken.TYPE_EOF) 200 return valueStack.removeFirst(); 201 else 202 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 203 204 case S_IN_OBJECT: 205 switch(token.type){ 206 case Yytoken.TYPE_COMMA: 207 break; 208 case Yytoken.TYPE_VALUE: 209 if(token.value instanceof String){ 210 String key=(String)token.value; 211 valueStack.addFirst(key); 212 status=S_PASSED_PAIR_KEY; 213 statusStack.addFirst(new Integer(status)); 214 } 215 else{ 216 status=S_IN_ERROR; 217 } 218 break; 219 case Yytoken.TYPE_RIGHT_BRACE: 220 if(valueStack.size()>1){ 221 statusStack.removeFirst(); 222 valueStack.removeFirst(); 223 status=peekStatus(statusStack); 224 } 225 else{ 226 status=S_IN_FINISHED_VALUE; 227 } 228 break; 229 default: 230 status=S_IN_ERROR; 231 break; 232 }//inner switch 233 break; 234 235 case S_PASSED_PAIR_KEY: 236 switch(token.type){ 237 case Yytoken.TYPE_COLON: 238 break; 239 case Yytoken.TYPE_VALUE: 240 statusStack.removeFirst(); 241 String key=(String)valueStack.removeFirst(); 242 Map parent=(Map)valueStack.getFirst(); 243 parent.put(key,token.value); 244 status=peekStatus(statusStack); 245 break; 246 case Yytoken.TYPE_LEFT_SQUARE: 247 statusStack.removeFirst(); 248 key=(String)valueStack.removeFirst(); 249 parent=(Map)valueStack.getFirst(); 250 List newArray=createArrayContainer(containerFactory); 251 parent.put(key,newArray); 252 status=S_IN_ARRAY; 253 statusStack.addFirst(new Integer(status)); 254 valueStack.addFirst(newArray); 255 break; 256 case Yytoken.TYPE_LEFT_BRACE: 257 statusStack.removeFirst(); 258 key=(String)valueStack.removeFirst(); 259 parent=(Map)valueStack.getFirst(); 260 Map newObject=createObjectContainer(containerFactory); 261 parent.put(key,newObject); 262 status=S_IN_OBJECT; 263 statusStack.addFirst(new Integer(status)); 264 valueStack.addFirst(newObject); 265 break; 266 default: 267 status=S_IN_ERROR; 268 } 269 break; 270 271 case S_IN_ARRAY: 272 switch(token.type){ 273 case Yytoken.TYPE_COMMA: 274 break; 275 case Yytoken.TYPE_VALUE: 276 List val=(List)valueStack.getFirst(); 277 val.add(token.value); 278 break; 279 case Yytoken.TYPE_RIGHT_SQUARE: 280 if(valueStack.size()>1){ 281 statusStack.removeFirst(); 282 valueStack.removeFirst(); 283 status=peekStatus(statusStack); 284 } 285 else{ 286 status=S_IN_FINISHED_VALUE; 287 } 288 break; 289 case Yytoken.TYPE_LEFT_BRACE: 290 val=(List)valueStack.getFirst(); 291 Map newObject=createObjectContainer(containerFactory); 292 val.add(newObject); 293 status=S_IN_OBJECT; 294 statusStack.addFirst(new Integer(status)); 295 valueStack.addFirst(newObject); 296 break; 297 case Yytoken.TYPE_LEFT_SQUARE: 298 val=(List)valueStack.getFirst(); 299 List newArray=createArrayContainer(containerFactory); 300 val.add(newArray); 301 status=S_IN_ARRAY; 302 statusStack.addFirst(new Integer(status)); 303 valueStack.addFirst(newArray); 304 break; 305 default: 306 status=S_IN_ERROR; 307 }//inner switch 308 break; 309 case S_IN_ERROR: 310 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 311 }//switch 312 if(status==S_IN_ERROR){ 313 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 314 } 315 }while(token.type!=Yytoken.TYPE_EOF); 316 } 317 catch(IOException ie){ 318 throw ie; 319 } 320 321 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 322 } 323 324 private void nextToken() throws ParseException, IOException{ 325 token = lexer.yylex(); 326 if(token == null) 327 token = new Yytoken(Yytoken.TYPE_EOF, null); 328 } 329 330 private Map createObjectContainer(ContainerFactory containerFactory){ 331 if(containerFactory == null) 332 return new JSONObject(); 333 Map m = containerFactory.createObjectContainer(); 334 335 if(m == null) 336 return new JSONObject(); 337 return m; 338 } 339 340 private List createArrayContainer(ContainerFactory containerFactory){ 341 if(containerFactory == null) 342 return new JSONArray(); 343 List l = containerFactory.creatArrayContainer(); 344 345 if(l == null) 346 return new JSONArray(); 347 return l; 348 } 349 350 /** 351 * description omitted. 352 * 353 * @param s description omitted. 354 * @param contentHandler description omitted. 355 * @throws ParseException description omitted. 356 */ 357 public void parse(String s, ContentHandler contentHandler) throws ParseException{ 358 parse(s, contentHandler, false); 359 } 360 361 /** 362 * description omitted. 363 * 364 * @param s description omitted. 365 * @param contentHandler description omitted. 366 * @param isResume description omitted. 367 * @throws ParseException description omitted. 368 */ 369 public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{ 370 StringReader in=new StringReader(s); 371 try{ 372 parse(in, contentHandler, isResume); 373 } 374 catch(IOException ie){ 375 /* 376 * Actually it will never happen. 377 */ 378 throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); 379 } 380 } 381 382 /** 383 * description omitted. 384 * 385 * @param in description omitted. 386 * @param contentHandler description omitted. 387 * @throws IOException description omitted. 388 * @throws ParseException description omitted. 389 */ 390 public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException{ 391 parse(in, contentHandler, false); 392 } 393 394 /** 395 * Stream processing of JSON text. 396 * 397 * @see ContentHandler 398 * 399 * @param in description omitted. 400 * @param contentHandler description omitted. 401 * @param isResume - Indicates if it continues previous parsing operation. 402 * If set to true, resume parsing the old stream, and parameter 'in' will be ignored. 403 * If this method is called for the first time in this instance, isResume will be ignored. 404 * 405 * @throws IOException description omitted. 406 * @throws ParseException description omitted. 407 */ 408 public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException{ 409 if(!isResume){ 410 reset(in); 411 handlerStatusStack = new LinkedList(); 412 } 413 else{ 414 if(handlerStatusStack == null){ 415 isResume = false; 416 reset(in); 417 handlerStatusStack = new LinkedList(); 418 } 419 } 420 421 LinkedList statusStack = handlerStatusStack; 422 423 try{ 424 do{ 425 switch(status){ 426 case S_INIT: 427 contentHandler.startJSON(); 428 nextToken(); 429 switch(token.type){ 430 case Yytoken.TYPE_VALUE: 431 status=S_IN_FINISHED_VALUE; 432 statusStack.addFirst(new Integer(status)); 433 if(!contentHandler.primitive(token.value)) 434 return; 435 break; 436 case Yytoken.TYPE_LEFT_BRACE: 437 status=S_IN_OBJECT; 438 statusStack.addFirst(new Integer(status)); 439 if(!contentHandler.startObject()) 440 return; 441 break; 442 case Yytoken.TYPE_LEFT_SQUARE: 443 status=S_IN_ARRAY; 444 statusStack.addFirst(new Integer(status)); 445 if(!contentHandler.startArray()) 446 return; 447 break; 448 default: 449 status=S_IN_ERROR; 450 }//inner switch 451 break; 452 453 case S_IN_FINISHED_VALUE: 454 nextToken(); 455 if(token.type==Yytoken.TYPE_EOF){ 456 contentHandler.endJSON(); 457 status = S_END; 458 return; 459 } 460 else{ 461 status = S_IN_ERROR; 462 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 463 } 464 465 case S_IN_OBJECT: 466 nextToken(); 467 switch(token.type){ 468 case Yytoken.TYPE_COMMA: 469 break; 470 case Yytoken.TYPE_VALUE: 471 if(token.value instanceof String){ 472 String key=(String)token.value; 473 status=S_PASSED_PAIR_KEY; 474 statusStack.addFirst(new Integer(status)); 475 if(!contentHandler.startObjectEntry(key)) 476 return; 477 } 478 else{ 479 status=S_IN_ERROR; 480 } 481 break; 482 case Yytoken.TYPE_RIGHT_BRACE: 483 if(statusStack.size()>1){ 484 statusStack.removeFirst(); 485 status=peekStatus(statusStack); 486 } 487 else{ 488 status=S_IN_FINISHED_VALUE; 489 } 490 if(!contentHandler.endObject()) 491 return; 492 break; 493 default: 494 status=S_IN_ERROR; 495 break; 496 }//inner switch 497 break; 498 499 case S_PASSED_PAIR_KEY: 500 nextToken(); 501 switch(token.type){ 502 case Yytoken.TYPE_COLON: 503 break; 504 case Yytoken.TYPE_VALUE: 505 statusStack.removeFirst(); 506 status=peekStatus(statusStack); 507 if(!contentHandler.primitive(token.value)) 508 return; 509 if(!contentHandler.endObjectEntry()) 510 return; 511 break; 512 case Yytoken.TYPE_LEFT_SQUARE: 513 statusStack.removeFirst(); 514 statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); 515 status=S_IN_ARRAY; 516 statusStack.addFirst(new Integer(status)); 517 if(!contentHandler.startArray()) 518 return; 519 break; 520 case Yytoken.TYPE_LEFT_BRACE: 521 statusStack.removeFirst(); 522 statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); 523 status=S_IN_OBJECT; 524 statusStack.addFirst(new Integer(status)); 525 if(!contentHandler.startObject()) 526 return; 527 break; 528 default: 529 status=S_IN_ERROR; 530 } 531 break; 532 533 case S_IN_PAIR_VALUE: 534 /* 535 * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token, 536 * therefore delay consuming token until next round. 537 */ 538 statusStack.removeFirst(); 539 status = peekStatus(statusStack); 540 if(!contentHandler.endObjectEntry()) 541 return; 542 break; 543 544 case S_IN_ARRAY: 545 nextToken(); 546 switch(token.type){ 547 case Yytoken.TYPE_COMMA: 548 break; 549 case Yytoken.TYPE_VALUE: 550 if(!contentHandler.primitive(token.value)) 551 return; 552 break; 553 case Yytoken.TYPE_RIGHT_SQUARE: 554 if(statusStack.size()>1){ 555 statusStack.removeFirst(); 556 status=peekStatus(statusStack); 557 } 558 else{ 559 status=S_IN_FINISHED_VALUE; 560 } 561 if(!contentHandler.endArray()) 562 return; 563 break; 564 case Yytoken.TYPE_LEFT_BRACE: 565 status=S_IN_OBJECT; 566 statusStack.addFirst(new Integer(status)); 567 if(!contentHandler.startObject()) 568 return; 569 break; 570 case Yytoken.TYPE_LEFT_SQUARE: 571 status=S_IN_ARRAY; 572 statusStack.addFirst(new Integer(status)); 573 if(!contentHandler.startArray()) 574 return; 575 break; 576 default: 577 status=S_IN_ERROR; 578 }//inner switch 579 break; 580 581 case S_END: 582 return; 583 584 case S_IN_ERROR: 585 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 586 }//switch 587 if(status==S_IN_ERROR){ 588 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 589 } 590 }while(token.type!=Yytoken.TYPE_EOF); 591 } 592 catch(IOException ie){ 593 status = S_IN_ERROR; 594 throw ie; 595 } 596 catch(ParseException pe){ 597 status = S_IN_ERROR; 598 throw pe; 599 } 600 catch(RuntimeException re){ 601 status = S_IN_ERROR; 602 throw re; 603 } 604 catch(Error e){ 605 status = S_IN_ERROR; 606 throw e; 607 } 608 609 status = S_IN_ERROR; 610 throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); 611 } 612}