tree grammar JSONTree;
options {
tokenVocab=JSON; ASTLabelType=CommonTree; }
@header {
package net.nextquestion.json;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
}
@members {
private Object extractNumber(CommonTree numberToken, CommonTree exponentToken) {
String numberBody = numberToken.getText();
String exponent = (exponentToken == null) ? null : exponentToken.getText().substring(1); boolean isReal = numberBody.indexOf('.') >= 0 || exponent != null;
if (!isReal) {
return new Integer(numberBody);
} else {
double result = Double.parseDouble(numberBody);
if (exponent != null) {
result = result * Math.pow(10.0f, Double.parseDouble(exponent));
}
return new Double(result);
}
}
private String extractString(CommonTree token) {
StringBuffer sb = new StringBuffer(token.getText());
int startPoint = 1; for (;;) {
int slashIndex = sb.indexOf("\\", startPoint); if (slashIndex == -1) break;
char escapeType = sb.charAt(slashIndex + 1);
switch (escapeType) {
case'u':
String unicode = extractUnicode(sb, slashIndex);
sb.replace(slashIndex, slashIndex + 6, unicode); break;
case 'b':
sb.replace(slashIndex, slashIndex + 2, "\b"); break;
case 't':
sb.replace(slashIndex, slashIndex + 2, "\t"); break;
case 'n':
sb.replace(slashIndex, slashIndex + 2, "\n"); break;
case 'f':
sb.replace(slashIndex, slashIndex + 2, "\f"); break;
case 'r':
sb.replace(slashIndex, slashIndex + 2, "\r"); break;
case '\'':
sb.replace(slashIndex, slashIndex + 2, "\'"); break;
case '\"':
sb.replace(slashIndex, slashIndex + 2, "\""); break;
case '\':
sb.replace(slashIndex, slashIndex + 2, "\\"); break;
}
startPoint = slashIndex+1;
}
sb.deleteCharAt(0);
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
private String extractUnicode(StringBuffer sb, int slashIndex) {
String result;
String code = sb.substring(slashIndex + 2, slashIndex + 6);
int charNum = Integer.parseInt(code, 16); try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8");
osw.write(charNum);
osw.flush();
result = baos.toString("UTF-8"); } catch (Exception e) {
e.printStackTrace();
result = null;
}
return result;
}
}
value returns [Object result]
: s=string { $result = s; }
| n=number { $result = n; }
| o=object { $result = o; }
| a=array { $result = a; }
| TRUE { $result=Boolean.TRUE; }
| FALSE {$result = Boolean.FALSE; }
| NULL {$result = null; }
;
string returns [String result]
: ^(STRING String)
{ $result = extractString($String); }
;
object returns [Map result]
@init { result = new HashMap(); }
: ^(OBJECT pair[$result]+)
;
number returns [Object result]
: ^(NUMBER Number Exponent?)
{ $result = extractNumber($Number, $Exponent); }
;
array returns [List list]
@init{ list = new ArrayList(); }
: ^(ARRAY (v=value {$list.add(v); })+ )
;
pair [Map map]
: ^(FIELD key=String v=value)
{ $map.put(extractString($key), v); }
;
new Character((char)charNum).toString()