JSONParser.java

  1. package org.drip.json.parser;

  2. /*
  3.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  4.  */

  5. /*!
  6.  * Copyright (C) 2020 Lakshmi Krishnamurthy
  7.  * Copyright (C) 2019 Lakshmi Krishnamurthy
  8.  * Copyright (C) 2018 Lakshmi Krishnamurthy
  9.  * Copyright (C) 2017 Lakshmi Krishnamurthy
  10.  * Copyright (C) 2016 Lakshmi Krishnamurthy
  11.  *
  12.  *  This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics,
  13.  *      asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment
  14.  *      analytics, and portfolio construction analytics within and across fixed income, credit, commodity,
  15.  *      equity, FX, and structured products. It also includes auxiliary libraries for algorithm support,
  16.  *      numerical analysis, numerical optimization, spline builder, model validation, statistical learning,
  17.  *      and computational support.
  18.  *  
  19.  *      https://lakshmidrip.github.io/DROP/
  20.  *  
  21.  *  DROP is composed of three modules:
  22.  *  
  23.  *  - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/
  24.  *  - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
  25.  *  - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/
  26.  *
  27.  *  DROP Product Core implements libraries for the following:
  28.  *  - Fixed Income Analytics
  29.  *  - Loan Analytics
  30.  *  - Transaction Cost Analytics
  31.  *
  32.  *  DROP Portfolio Core implements libraries for the following:
  33.  *  - Asset Allocation Analytics
  34.  *  - Asset Liability Management Analytics
  35.  *  - Capital Estimation Analytics
  36.  *  - Exposure Analytics
  37.  *  - Margin Analytics
  38.  *  - XVA Analytics
  39.  *
  40.  *  DROP Computational Core implements libraries for the following:
  41.  *  - Algorithm Support
  42.  *  - Computation Support
  43.  *  - Function Analysis
  44.  *  - Model Validation
  45.  *  - Numerical Analysis
  46.  *  - Numerical Optimizer
  47.  *  - Spline Builder
  48.  *  - Statistical Learning
  49.  *
  50.  *  Documentation for DROP is Spread Over:
  51.  *
  52.  *  - Main                     => https://lakshmidrip.github.io/DROP/
  53.  *  - Wiki                     => https://github.com/lakshmiDRIP/DROP/wiki
  54.  *  - GitHub                   => https://github.com/lakshmiDRIP/DROP
  55.  *  - Repo Layout Taxonomy     => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
  56.  *  - Javadoc                  => https://lakshmidrip.github.io/DROP/Javadoc/index.html
  57.  *  - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
  58.  *  - Release Versions         => https://lakshmidrip.github.io/DROP/version.html
  59.  *  - Community Credits        => https://lakshmidrip.github.io/DROP/credits.html
  60.  *  - Issues Catalog           => https://github.com/lakshmiDRIP/DROP/issues
  61.  *  - JUnit                    => https://lakshmidrip.github.io/DROP/junit/index.html
  62.  *  - Jacoco                   => https://lakshmidrip.github.io/DROP/jacoco/index.html
  63.  *
  64.  *  Licensed under the Apache License, Version 2.0 (the "License");
  65.  *      you may not use this file except in compliance with the License.
  66.  *  
  67.  *  You may obtain a copy of the License at
  68.  *      http://www.apache.org/licenses/LICENSE-2.0
  69.  *  
  70.  *  Unless required by applicable law or agreed to in writing, software
  71.  *      distributed under the License is distributed on an "AS IS" BASIS,
  72.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  73.  *  
  74.  *  See the License for the specific language governing permissions and
  75.  *      limitations under the License.
  76.  */

  77. /**
  78.  * <i>JSONParser</i> is an Adaptation of the JSONParser Class from the RFC4627 compliant JSON Simple
  79.  * (https://code.google.com/p/json-simple/).
  80.  *
  81.  *  <br><br>
  82.  *  <ul>
  83.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ComputationalCore.md">Computational Core Module</a></li>
  84.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ComputationSupportLibrary.md">Computation Support</a></li>
  85.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/json">RFC-4627 Compliant JSON Encoder/Decoder (Parser)</a></li>
  86.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/json/parser">RFC4627 Compliant JSON Message Parser</a></li>
  87.  *  </ul>
  88.  *
  89.  * @author Fang Yidong
  90.  * @author Lakshmi Krishnamurthy
  91.  */

  92. public class JSONParser {
  93.     public static final int S_INIT=0;
  94.     public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array
  95.     public static final int S_IN_OBJECT=2;
  96.     public static final int S_IN_ARRAY=3;
  97.     public static final int S_PASSED_PAIR_KEY=4;
  98.     public static final int S_IN_PAIR_VALUE=5;
  99.     public static final int S_END=6;
  100.     public static final int S_IN_ERROR=-1;
  101.    
  102.     @SuppressWarnings ("rawtypes") private java.util.LinkedList handlerStatusStack;

  103.     private Yylex lexer = new Yylex((java.io.Reader)null);
  104.     private Yytoken token = null;
  105.     private int status = S_INIT;
  106.    
  107.     @SuppressWarnings ("rawtypes") private int peekStatus(java.util.LinkedList statusStack){
  108.             if(statusStack.size()==0)
  109.                     return -1;
  110.             Integer status=(Integer)statusStack.getFirst();
  111.             return status.intValue();
  112.     }
  113.    
  114. /**
  115.  *  Reset the parser to the initial state without resetting the underlying reader.
  116.  *
  117.  */
  118. public void reset(){
  119.     token = null;
  120.     status = S_INIT;
  121.     handlerStatusStack = null;
  122. }

  123. /**
  124.  * Reset the parser to the initial state with a new character reader.
  125.  *
  126.  * @param in - The new character reader.
  127.  */
  128.     public void reset(java.io.Reader in){
  129.             lexer.yyreset(in);
  130.             reset();
  131.     }
  132.    
  133.     /**
  134.      * @return The position of the beginning of the current token.
  135.      */
  136.     public int getPosition(){
  137.             return lexer.getPosition();
  138.     }
  139.    
  140.     public Object parse(String s) throws ParseException{
  141.             return parse(s, (ContainerFactory)null);
  142.     }
  143.    
  144.     /**
  145.      * Parse the JSON String
  146.      *
  147.      * @param s The String
  148.      * @param containerFactory The Container Factory
  149.      *
  150.      * @return The JSON Object
  151.      *
  152.      * @throws ParseException Thrown if the Inputs are Invalid
  153.      */

  154.     public Object parse(String s, ContainerFactory containerFactory) throws ParseException{
  155.         java.io.StringReader in=new java.io.StringReader(s);
  156.             try{
  157.                     return parse(in, containerFactory);
  158.             }
  159.             catch(java.io.IOException ie){
  160.                     /*
  161.                      * Actually it will never happen.
  162.                      */
  163.                     throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
  164.             }
  165.     }
  166.    
  167.     public Object parse(java.io.Reader in) throws java.io.IOException, ParseException{
  168.             return parse(in, (ContainerFactory)null);
  169.     }
  170.    
  171.     /**
  172.      * Parse JSON text into java object from the input source.
  173.      *      
  174.      * @param in The Input Reader
  175.  * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers.
  176.      * @return Instance of the following:
  177.      *  org.json.simple.JSONObject,
  178.      *      org.json.simple.JSONArray,
  179.      *      java.lang.String,
  180.      *      java.lang.Number,
  181.      *      java.lang.Boolean,
  182.      *      null
  183.      *
  184.      * @throws java.io.IOException Thrown if the Inputs are Invalid
  185.      *
  186.      * @throws ParseException Thrown if the Inputs are Invalid
  187.      */
  188.     @SuppressWarnings ({"rawtypes", "unchecked"}) public Object parse(java.io.Reader in, ContainerFactory containerFactory) throws java.io.IOException, ParseException{
  189.             reset(in);
  190.             java.util.LinkedList statusStack = new java.util.LinkedList();
  191.             java.util.LinkedList valueStack = new java.util.LinkedList();
  192.            
  193.             try{
  194.                     do{
  195.                             nextToken();
  196.                             switch(status){
  197.                             case S_INIT:
  198.                                     switch(token.type){
  199.                                     case Yytoken.TYPE_VALUE:
  200.                                             status=S_IN_FINISHED_VALUE;
  201.                                             statusStack.addFirst(status);
  202.                                             valueStack.addFirst(token.value);
  203.                                             break;
  204.                                     case Yytoken.TYPE_LEFT_BRACE:
  205.                                             status=S_IN_OBJECT;
  206.                                             statusStack.addFirst(status);
  207.                                             valueStack.addFirst(createObjectContainer(containerFactory));
  208.                                             break;
  209.                                     case Yytoken.TYPE_LEFT_SQUARE:
  210.                                             status=S_IN_ARRAY;
  211.                                             statusStack.addFirst(status);
  212.                                             valueStack.addFirst(createArrayContainer(containerFactory));
  213.                                             break;
  214.                                     default:
  215.                                             status=S_IN_ERROR;
  216.                                     }//inner switch
  217.                                     break;
  218.                                    
  219.                             case S_IN_FINISHED_VALUE:
  220.                                     if(token.type==Yytoken.TYPE_EOF)
  221.                                             return valueStack.removeFirst();
  222.                                     else
  223.                                             throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  224.                                    
  225.                             case S_IN_OBJECT:
  226.                                     switch(token.type){
  227.                                     case Yytoken.TYPE_COMMA:
  228.                                             break;
  229.                                     case Yytoken.TYPE_VALUE:
  230.                                             if(token.value instanceof String){
  231.                                                     String key=(String)token.value;
  232.                                                     valueStack.addFirst(key);
  233.                                                     status=S_PASSED_PAIR_KEY;
  234.                                                     statusStack.addFirst(status);
  235.                                             }
  236.                                             else{
  237.                                                     status=S_IN_ERROR;
  238.                                             }
  239.                                             break;
  240.                                     case Yytoken.TYPE_RIGHT_BRACE:
  241.                                             if(valueStack.size()>1){
  242.                                                     statusStack.removeFirst();
  243.                                                     valueStack.removeFirst();
  244.                                                     status=peekStatus(statusStack);
  245.                                             }
  246.                                             else{
  247.                                                     status=S_IN_FINISHED_VALUE;
  248.                                             }
  249.                                             break;
  250.                                     default:
  251.                                             status=S_IN_ERROR;
  252.                                             break;
  253.                                     }//inner switch
  254.                                     break;
  255.                                    
  256.                             case S_PASSED_PAIR_KEY:
  257.                                     switch(token.type){
  258.                                     case Yytoken.TYPE_COLON:
  259.                                             break;
  260.                                     case Yytoken.TYPE_VALUE:
  261.                                             statusStack.removeFirst();
  262.                                             String key=(String)valueStack.removeFirst();
  263.                                             java.util.Map parent=(java.util.Map)valueStack.getFirst();
  264.                                             parent.put(key,token.value);
  265.                                             status=peekStatus(statusStack);
  266.                                             break;
  267.                                     case Yytoken.TYPE_LEFT_SQUARE:
  268.                                             statusStack.removeFirst();
  269.                                             key=(String)valueStack.removeFirst();
  270.                                             parent=(java.util.Map)valueStack.getFirst();
  271.                                             java.util.List newArray=createArrayContainer(containerFactory);
  272.                                             parent.put(key,newArray);
  273.                                             status=S_IN_ARRAY;
  274.                                             statusStack.addFirst(status);
  275.                                             valueStack.addFirst(newArray);
  276.                                             break;
  277.                                     case Yytoken.TYPE_LEFT_BRACE:
  278.                                             statusStack.removeFirst();
  279.                                             key=(String)valueStack.removeFirst();
  280.                                             parent=(java.util.Map)valueStack.getFirst();
  281.                                             java.util.Map newObject=createObjectContainer(containerFactory);
  282.                                             parent.put(key,newObject);
  283.                                             status=S_IN_OBJECT;
  284.                                             statusStack.addFirst(status);
  285.                                             valueStack.addFirst(newObject);
  286.                                             break;
  287.                                     default:
  288.                                             status=S_IN_ERROR;
  289.                                     }
  290.                                     break;
  291.                                    
  292.                             case S_IN_ARRAY:
  293.                                     switch(token.type){
  294.                                     case Yytoken.TYPE_COMMA:
  295.                                             break;
  296.                                     case Yytoken.TYPE_VALUE:
  297.                                         java.util.List val=(java.util.List)valueStack.getFirst();
  298.                                             val.add(token.value);
  299.                                             break;
  300.                                     case Yytoken.TYPE_RIGHT_SQUARE:
  301.                                             if(valueStack.size()>1){
  302.                                                     statusStack.removeFirst();
  303.                                                     valueStack.removeFirst();
  304.                                                     status=peekStatus(statusStack);
  305.                                             }
  306.                                             else{
  307.                                                     status=S_IN_FINISHED_VALUE;
  308.                                             }
  309.                                             break;
  310.                                     case Yytoken.TYPE_LEFT_BRACE:
  311.                                             val=(java.util.List)valueStack.getFirst();
  312.                                             java.util.Map newObject=createObjectContainer(containerFactory);
  313.                                             val.add(newObject);
  314.                                             status=S_IN_OBJECT;
  315.                                             statusStack.addFirst(status);
  316.                                             valueStack.addFirst(newObject);
  317.                                             break;
  318.                                     case Yytoken.TYPE_LEFT_SQUARE:
  319.                                             val=(java.util.List)valueStack.getFirst();
  320.                                             java.util.List newArray=createArrayContainer(containerFactory);
  321.                                             val.add(newArray);
  322.                                             status=S_IN_ARRAY;
  323.                                             statusStack.addFirst(status);
  324.                                             valueStack.addFirst(newArray);
  325.                                             break;
  326.                                     default:
  327.                                             status=S_IN_ERROR;
  328.                                     }//inner switch
  329.                                     break;
  330.                             case S_IN_ERROR:
  331.                                     throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  332.                             }//switch
  333.                             if(status==S_IN_ERROR){
  334.                                     throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  335.                             }
  336.                     }while(token.type!=Yytoken.TYPE_EOF);
  337.             }
  338.             catch(java.io.IOException ie){
  339.                     throw ie;
  340.             }
  341.            
  342.             throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  343.     }
  344.    
  345.     private void nextToken() throws ParseException, java.io.IOException{
  346.             token = lexer.yylex();
  347.             if(token == null)
  348.                     token = new Yytoken(Yytoken.TYPE_EOF, null);
  349.     }
  350.    
  351.     @SuppressWarnings ("rawtypes") private java.util.Map createObjectContainer(ContainerFactory containerFactory){
  352.             if(containerFactory == null)
  353.                     return new org.drip.json.simple.JSONObject();
  354.             java.util.Map m = containerFactory.createObjectContainer();
  355.            
  356.             if(m == null)
  357.                     return new org.drip.json.simple.JSONObject();
  358.             return m;
  359.     }
  360.    
  361.     @SuppressWarnings ("rawtypes") private java.util.List createArrayContainer(ContainerFactory containerFactory){
  362.             if(containerFactory == null)
  363.                     return new org.drip.json.simple.JSONArray();
  364.             java.util.List l = containerFactory.creatArrayContainer();
  365.            
  366.             if(l == null)
  367.                     return new org.drip.json.simple.JSONArray();
  368.             return l;
  369.     }
  370.    
  371.     public void parse(String s, ContentHandler contentHandler) throws ParseException{
  372.             parse(s, contentHandler, false);
  373.     }
  374.    
  375.     public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{
  376.         java.io.StringReader in=new java.io.StringReader(s);
  377.             try{
  378.                     parse(in, contentHandler, isResume);
  379.             }
  380.             catch(java.io.IOException ie){
  381.                     /*
  382.                      * Actually it will never happen.
  383.                      */
  384.                     throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
  385.             }
  386.     }
  387.    
  388.     public void parse(java.io.Reader in, ContentHandler contentHandler) throws java.io.IOException, ParseException{
  389.             parse(in, contentHandler, false);
  390.     }
  391.    
  392.     /**
  393.      * Stream processing of JSON text.
  394.      *
  395.      * @see ContentHandler
  396.      *
  397.      * @param in The Input Reader
  398.      * @param contentHandler The Content Handler Instance
  399.      * @param isResume - Indicates if it continues previous parsing operation.
  400.  *                   If set to true, resume parsing the old stream, and parameter 'in' will be ignored.
  401.      *                   If this method is called for the first time in this instance, isResume will be ignored.
  402.      *
  403.      * @throws java.io.IOException Thrown if the Inputs are Invalid
  404.      *
  405.      * @throws ParseException Thrown if the Inputs are Invalid
  406.      */
  407.     @SuppressWarnings ({"rawtypes", "unchecked"}) public void parse(java.io.Reader in, ContentHandler contentHandler, boolean isResume) throws java.io.IOException, ParseException{
  408.             if(!isResume){
  409.                     reset(in);
  410.                     handlerStatusStack = new java.util.LinkedList();
  411.             }
  412.             else{
  413.                     if(handlerStatusStack == null){
  414.                             isResume = false;
  415.                             reset(in);
  416.                             handlerStatusStack = new java.util.LinkedList();
  417.                     }
  418.             }
  419.            
  420.             java.util.LinkedList statusStack = handlerStatusStack;    
  421.            
  422.             try{
  423.                     do{
  424.                             switch(status){
  425.                             case S_INIT:
  426.                                     contentHandler.startJSON();
  427.                                     nextToken();
  428.                                     switch(token.type){
  429.                                     case Yytoken.TYPE_VALUE:
  430.                                             status=S_IN_FINISHED_VALUE;
  431.                                             statusStack.addFirst(status);
  432.                                             if(!contentHandler.primitive(token.value))
  433.                                                     return;
  434.                                             break;
  435.                                     case Yytoken.TYPE_LEFT_BRACE:
  436.                                             status=S_IN_OBJECT;
  437.                                             statusStack.addFirst(status);
  438.                                             if(!contentHandler.startObject())
  439.                                                     return;
  440.                                             break;
  441.                                     case Yytoken.TYPE_LEFT_SQUARE:
  442.                                             status=S_IN_ARRAY;
  443.                                             statusStack.addFirst(status);
  444.                                             if(!contentHandler.startArray())
  445.                                                     return;
  446.                                             break;
  447.                                     default:
  448.                                             status=S_IN_ERROR;
  449.                                     }//inner switch
  450.                                     break;
  451.                                    
  452.                             case S_IN_FINISHED_VALUE:
  453.                                     nextToken();
  454.                                     if(token.type==Yytoken.TYPE_EOF){
  455.                                             contentHandler.endJSON();
  456.                                             status = S_END;
  457.                                             return;
  458.                                     }
  459.                                     else{
  460.                                             status = S_IN_ERROR;
  461.                                             throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  462.                                     }
  463.                    
  464.                             case S_IN_OBJECT:
  465.                                     nextToken();
  466.                                     switch(token.type){
  467.                                     case Yytoken.TYPE_COMMA:
  468.                                             break;
  469.                                     case Yytoken.TYPE_VALUE:
  470.                                             if(token.value instanceof String){
  471.                                                     String key=(String)token.value;
  472.                                                     status=S_PASSED_PAIR_KEY;
  473.                                                     statusStack.addFirst(status);
  474.                                                     if(!contentHandler.startObjectEntry(key))
  475.                                                             return;
  476.                                             }
  477.                                             else{
  478.                                                     status=S_IN_ERROR;
  479.                                             }
  480.                                             break;
  481.                                     case Yytoken.TYPE_RIGHT_BRACE:
  482.                                             if(statusStack.size()>1){
  483.                                                     statusStack.removeFirst();
  484.                                                     status=peekStatus(statusStack);
  485.                                             }
  486.                                             else{
  487.                                                     status=S_IN_FINISHED_VALUE;
  488.                                             }
  489.                                             if(!contentHandler.endObject())
  490.                                                     return;
  491.                                             break;
  492.                                     default:
  493.                                             status=S_IN_ERROR;
  494.                                             break;
  495.                                     }//inner switch
  496.                                     break;
  497.                                    
  498.                             case S_PASSED_PAIR_KEY:
  499.                                     nextToken();
  500.                                     switch(token.type){
  501.                                     case Yytoken.TYPE_COLON:
  502.                                             break;
  503.                                     case Yytoken.TYPE_VALUE:
  504.                                             statusStack.removeFirst();
  505.                                             status=peekStatus(statusStack);
  506.                                             if(!contentHandler.primitive(token.value))
  507.                                                     return;
  508.                                             if(!contentHandler.endObjectEntry())
  509.                                                     return;
  510.                                             break;
  511.                                     case Yytoken.TYPE_LEFT_SQUARE:
  512.                                             statusStack.removeFirst();
  513.                                             statusStack.addFirst(S_IN_PAIR_VALUE);
  514.                                             status=S_IN_ARRAY;
  515.                                             statusStack.addFirst(status);
  516.                                             if(!contentHandler.startArray())
  517.                                                     return;
  518.                                             break;
  519.                                     case Yytoken.TYPE_LEFT_BRACE:
  520.                                             statusStack.removeFirst();
  521.                                             statusStack.addFirst(S_IN_PAIR_VALUE);
  522.                                             status=S_IN_OBJECT;
  523.                                             statusStack.addFirst(status);
  524.                                             if(!contentHandler.startObject())
  525.                                                     return;
  526.                                             break;
  527.                                     default:
  528.                                             status=S_IN_ERROR;
  529.                                     }
  530.                                     break;
  531.                            
  532.                             case S_IN_PAIR_VALUE:
  533.                                     /*
  534.                                      * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token,
  535.                                      * therefore delay consuming token until next round.
  536.                                      */
  537.                                     statusStack.removeFirst();
  538.                                     status = peekStatus(statusStack);
  539.                                     if(!contentHandler.endObjectEntry())
  540.                                             return;
  541.                                     break;
  542.                                    
  543.                             case S_IN_ARRAY:
  544.                                     nextToken();
  545.                                     switch(token.type){
  546.                                     case Yytoken.TYPE_COMMA:
  547.                                             break;
  548.                                     case Yytoken.TYPE_VALUE:
  549.                                             if(!contentHandler.primitive(token.value))
  550.                                                     return;
  551.                                             break;
  552.                                     case Yytoken.TYPE_RIGHT_SQUARE:
  553.                                             if(statusStack.size()>1){
  554.                                                     statusStack.removeFirst();
  555.                                                     status=peekStatus(statusStack);
  556.                                             }
  557.                                             else{
  558.                                                     status=S_IN_FINISHED_VALUE;
  559.                                             }
  560.                                             if(!contentHandler.endArray())
  561.                                                     return;
  562.                                             break;
  563.                                     case Yytoken.TYPE_LEFT_BRACE:
  564.                                             status=S_IN_OBJECT;
  565.                                             statusStack.addFirst(status);
  566.                                             if(!contentHandler.startObject())
  567.                                                     return;
  568.                                             break;
  569.                                     case Yytoken.TYPE_LEFT_SQUARE:
  570.                                             status=S_IN_ARRAY;
  571.                                             statusStack.addFirst(status);
  572.                                             if(!contentHandler.startArray())
  573.                                                     return;
  574.                                             break;
  575.                                     default:
  576.                                             status=S_IN_ERROR;
  577.                                     }//inner switch
  578.                                     break;
  579.                                    
  580.                             case S_END:
  581.                                     return;
  582.                                    
  583.                             case S_IN_ERROR:
  584.                                     throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  585.                             }//switch
  586.                             if(status==S_IN_ERROR){
  587.                                     throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  588.                             }
  589.                     }while(token.type!=Yytoken.TYPE_EOF);
  590.             }
  591.             catch(java.io.IOException ie){
  592.                     status = S_IN_ERROR;
  593.                     throw ie;
  594.             }
  595.             catch(ParseException pe){
  596.                     status = S_IN_ERROR;
  597.                     throw pe;
  598.             }
  599.             catch(RuntimeException re){
  600.                     status = S_IN_ERROR;
  601.                     throw re;
  602.             }
  603.             catch(Error e){
  604.                     status = S_IN_ERROR;
  605.                     throw e;
  606.             }
  607.            
  608.             status = S_IN_ERROR;
  609.             throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  610.     }
  611. }