blob: 4610ae477eac904abeb5af9b241c8285ca51ac0b [file] [log] [blame]
/*******************************************************************************
* 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; }
}