| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| options { |
| ERROR_REPORTING = true; |
| STATIC = false; |
| // DEBUG_PARSER = true; |
| // DEBUG_LOOKAHEAD = true; |
| // DEBUG_TOKEN_MANAGER = true; |
| LOOKAHEAD = 1; |
| // CHOICE_AMBIGUITY_CHECK = 3; |
| // OTHER_AMBIGUITY_CHECK = 3; |
| } |
| |
| PARSER_BEGIN(JSON) |
| |
| package org.ofbiz.base.json; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javolution.util.FastMap; |
| |
| import org.ofbiz.base.util.UtilIO; |
| |
| public class JSON { |
| private boolean allowResolve; |
| |
| public JSON(String fileName) { |
| this(System.in); |
| try { ReInit(new FileInputStream(new File(fileName))); } |
| catch(Exception e) { e.printStackTrace(); } |
| // allowed[TEXT] = 1; |
| // allowed[FIRST_COLUMN_TEXT] = 1; |
| } |
| |
| public JSON allowResolve(boolean allowResolve) { |
| this.allowResolve = allowResolve; |
| token_source.SwitchTo(allowResolve ? RESOLVE : DEFAULT); |
| return this; |
| } |
| } |
| |
| PARSER_END(JSON) |
| TOKEN_MGR_DECLS: { |
| protected LinkedList<Integer> stateStack = new LinkedList<Integer>(); |
| protected StringBuilder statePrefix = new StringBuilder(); |
| |
| protected void pushState(int state) { |
| //System.err.println(statePrefix + "push: " + lexStateNames[curLexState] + " -> " + lexStateNames[state]); |
| stateStack.add(curLexState); |
| statePrefix.append(' '); |
| SwitchTo(state); |
| } |
| |
| protected void popState() { |
| int oldState = stateStack.removeLast(); |
| statePrefix.setLength(statePrefix.length() - 1); |
| //System.err.println(statePrefix + "pop: " + lexStateNames[curLexState] + " -> " + lexStateNames[oldState]); |
| SwitchTo(oldState); |
| } |
| } |
| <DEFAULT,RESOLVE> |
| TOKEN: |
| { |
| <OBJECT_BEGIN: "{"> |
| | <OBJECT_END: "}"> |
| | <ARRAY_BEGIN: "["> |
| | <ARRAY_END: "]"> |
| | <ITEM_SEP: ","> |
| | <KEY_SEP: ":"> |
| | <TRUE: "true"> |
| | <FALSE: "false"> |
| | <NULL: "null"> |
| | <WHOLE_NUMBER: |
| <NUMBER_PREFIX> |
| > |
| | <FLOAT_NUMBER: |
| <NUMBER_PREFIX> |
| ("." (["0"-"9"])*)? |
| ( |
| ["e", "E"] |
| (["+", "-"])? |
| (["0"-"9"])+ |
| )? |
| > |
| | <#NUMBER_PREFIX: |
| (["-"])? |
| ( |
| "0" |
| | ["1"-"9"] (["0"-"9"])* |
| ) |
| > |
| } |
| |
| <DEFAULT,RESOLVE,IN_RESOLVE_VALUE> |
| TOKEN: |
| { |
| <STRING_START: "\""> { pushState(IN_STRING); } |
| } |
| |
| <IN_RESOLVE_VALUE> |
| TOKEN: |
| { |
| <CLOSE_PAREN: ")"> { popState(); } |
| } |
| |
| <RESOLVE> |
| TOKEN: |
| { |
| <RESOLVE_BEGIN: "resolve("> { pushState(IN_RESOLVE_VALUE); } |
| } |
| |
| <IN_STRING> |
| TOKEN: |
| { |
| <CHARACTER: (~["\"","\\","\u0000"-"\u001f"])+> |
| | <STRING_END: "\""> { popState(); } |
| | <CONTROL_CHAR: "\\" ["\"", "\\", "/", "b","f","n","r","t"]> |
| | <UNICODE: "\\u" |
| ["a"-"f", "A"-"F", "0"-"9"] |
| ["a"-"f", "A"-"F", "0"-"9"] |
| ["a"-"f", "A"-"F", "0"-"9"] |
| ["a"-"f", "A"-"F", "0"-"9"] |
| > |
| } |
| |
| <DEFAULT,RESOLVE> |
| SKIP: |
| { |
| <WHITESPACE: [" ", "\r", "\n", "\t"]> |
| } |
| |
| <DEFAULT,RESOLVE> |
| MORE: |
| { |
| <COMMENT_START: "/*"> { if (curLexState != IN_COMMENT) pushState(IN_COMMENT); } |
| } |
| |
| <IN_COMMENT> |
| MORE: |
| { |
| <(~[])> |
| } |
| |
| <IN_COMMENT> |
| MORE: |
| { |
| <COMMENT_END: "*/"> { popState(); } |
| } |
| |
| Object JSONValue(): |
| { Object value; } |
| { |
| value=JSONItem() |
| <EOF> |
| { return value; } |
| } |
| |
| Object JSONItem(): |
| { Object value; } |
| { |
| ( |
| value=JSONString() |
| | value=JSONLong() |
| | value=JSONFloat() |
| | value=JSONObject() |
| | value=JSONArray() |
| | value=True() |
| | value=False() |
| | value=Null() |
| | value=JSONResolve() |
| ) |
| { return value; } |
| } |
| |
| Object JSONResolve(): |
| { |
| String name, value; |
| } |
| { |
| <RESOLVE_BEGIN> |
| value=JSONString() |
| <CLOSE_PAREN> |
| { |
| try { |
| return UtilIO.readObject(value.toCharArray()); |
| } catch (ClassNotFoundException e) { |
| throw generateParseException(); |
| } catch (IOException e) { |
| throw generateParseException(); |
| } |
| } |
| } |
| String JSONString(): |
| { |
| StringBuilder sb = new StringBuilder(); |
| } |
| { |
| <STRING_START> ( |
| <CHARACTER> { sb.append(getToken(0).image); } |
| | <CONTROL_CHAR> { |
| switch (getToken(0).image.charAt(1)) { |
| case '"': sb.append('"'); break; |
| case '\\': sb.append('\\'); break; |
| case '/': sb.append('/'); break; |
| case 'b': sb.append('\b'); break; |
| case 'f': sb.append('\f'); break; |
| case 'n': sb.append('\n'); break; |
| case 'r': sb.append('\r'); break; |
| case 't': sb.append('\t'); break; |
| } |
| } |
| | <UNICODE> { |
| int v = Integer.parseInt(getToken(0).image.substring(2), 16); |
| sb.append((char) v); |
| } |
| )* |
| <STRING_END> |
| { return sb.toString(); } |
| } |
| |
| Long JSONLong(): |
| {} |
| { |
| try { |
| <WHOLE_NUMBER> { return new Long(getToken(0).image); } |
| } catch (NumberFormatException e) { |
| throw generateParseException(); |
| } |
| } |
| |
| Double JSONFloat(): |
| {} |
| { |
| try { |
| <FLOAT_NUMBER> { return new Double(getToken(0).image); } |
| } catch (NumberFormatException e) { |
| throw generateParseException(); |
| } |
| } |
| |
| Map<String, Object> JSONObject(): |
| { |
| Map<String, Object> map = FastMap.newInstance(); |
| } |
| { |
| <OBJECT_BEGIN> |
| (JSONObjectEntry(map))? (<ITEM_SEP> (JSONObjectEntry(map))?)* |
| <OBJECT_END> |
| { return map; } |
| } |
| |
| void JSONObjectEntry(Map<String, Object> map): |
| { |
| String key; |
| Object value; |
| } |
| { |
| key=JSONString() <KEY_SEP> value=JSONItem() |
| { map.put(key, value); } |
| } |
| |
| List<Object> JSONArray(): |
| { |
| ArrayList<Object> list = new ArrayList<Object>(); |
| Object value; |
| } |
| { |
| <ARRAY_BEGIN> |
| (<ITEM_SEP>)* |
| ( |
| value=JSONItem() { list.add(value); } |
| ( |
| <ITEM_SEP> |
| (value=JSONItem() { list.add(value); })? |
| )* |
| )? |
| <ARRAY_END> |
| { return list; } |
| } |
| |
| Boolean True(): |
| {} |
| { |
| <TRUE> { return Boolean.TRUE; } |
| } |
| |
| Boolean False(): |
| {} |
| { |
| <FALSE> { return Boolean.FALSE; } |
| } |
| |
| Object Null(): |
| {} |
| { |
| <NULL> { return null; } |
| } |