moved antlr parser to subproject

This commit is contained in:
2019-07-28 16:11:45 +01:00
parent ff9b26ed93
commit 36b0a1da3a
8 changed files with 191 additions and 167 deletions

View File

@@ -0,0 +1,90 @@
/** Taken from "The Definitive ANTLR 4 Reference" by Terence Parr */
// Derived from http://json.org
grammar JSON;
json
: value
;
obj
: '{' pair (',' pair)* '}'
| '{' '}'
;
pair
: STRING ':' value
;
array
: '[' value (',' value)* ']'
| '[' ']'
;
value
: STRING
| NUMBER
| obj
| array
| TRUE
| FALSE
| NULL
;
TRUE
: 'true'
;
FALSE
: 'false'
;
NULL
: 'null'
;
STRING
: '"' (ESC | SAFECODEPOINT)* '"'
;
fragment ESC
: '\\' (["\\/bfnrt] | UNICODE)
;
fragment UNICODE
: 'u' HEX HEX HEX HEX
;
fragment HEX
: [0-9a-fA-F]
;
fragment SAFECODEPOINT
: ~ ["\\\u0000-\u001F]
;
NUMBER
: '-'? INT ('.' [0-9] +)? EXP?
;
fragment INT
: '0' | [1-9] [0-9]*
;
// no leading zeros
fragment EXP
: [Ee] [+\-]? INT
;
// \- since - means "range" inside [...]
WS
: [ \t\n\r] + -> skip
;

View File

@@ -0,0 +1,102 @@
package net.woggioni.worth.antlr;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.xface.Value;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
public class JSONListenerImpl extends ValueParser implements JSONListener {
public Value result = null;
private String unquote(String quoted) {
return quoted.substring(1, quoted.length() - 1);
}
@Override
public void enterJson(JSONParser.JsonContext ctx) {
}
@Override
public void exitJson(JSONParser.JsonContext ctx) {
result = stack.getFirst().value;
stack.clear();
}
@Override
public void enterObj(JSONParser.ObjContext ctx) {
beginObject();
}
@Override
public void exitObj(JSONParser.ObjContext ctx) {
endObject();
}
@Override
public void enterPair(JSONParser.PairContext ctx) {
objectKey(unquote(ctx.STRING().getText()));
}
@Override
public void exitPair(JSONParser.PairContext ctx) {
}
@Override
public void enterArray(JSONParser.ArrayContext ctx) {
beginArray();
}
@Override
public void exitArray(JSONParser.ArrayContext ctx) {
endArray();
}
@Override
public void enterValue(JSONParser.ValueContext ctx) {
if (ctx.obj() != null) {
} else if (ctx.array() != null) {
} else if (ctx.STRING() != null) {
stringValue(unquote(ctx.STRING().getText()));
} else if (ctx.TRUE() != null) {
booleanValue(true);
} else if (ctx.FALSE() != null) {
booleanValue(false);
} else if (ctx.NULL() != null) {
nullValue();
} else if (ctx.NUMBER() != null) {
String text = ctx.NUMBER().getText();
if (text.indexOf('.') < 0)
integerValue(Long.valueOf(text));
else
floatValue(Float.valueOf(text));
}
}
@Override
public void exitValue(JSONParser.ValueContext ctx) {
}
@Override
public void visitTerminal(TerminalNode node) {
}
@Override
public void visitErrorNode(ErrorNode node) {
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
}
}

View File

@@ -0,0 +1,45 @@
package net.woggioni.worth.antlr;
import lombok.SneakyThrows;
import net.woggioni.worth.serialization.JsonBombTest;
import net.woggioni.worth.serialization.json.JSONDumper;
import net.woggioni.worth.xface.Value;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.junit.Test;
import java.io.InputStreamReader;
import static net.woggioni.worth.serialization.JsonBombTest.infiniteJson;
public class ParseTest {
@Test
@SneakyThrows
public void test(){
CodePointCharStream inputStream = CharStreams.fromReader(new InputStreamReader(getClass().getResourceAsStream("/test.json")));
JSONLexer lexer = new JSONLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
JSONParser parser = new JSONParser(commonTokenStream);
JSONListenerImpl listener = new JSONListenerImpl();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(listener, parser.json());
Value result = listener.result;
new JSONDumper().dump(result, System.out);
}
@Test(expected = OutOfMemoryError.class)
@SneakyThrows
public void antlr() {
CharStream inputStream = CharStreams.fromReader(new InputStreamReader(infiniteJson()));
JSONLexer lexer = new JSONLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
net.woggioni.worth.antlr.JSONParser parser = new net.woggioni.worth.antlr.JSONParser(commonTokenStream);
JSONListenerImpl listener = new JSONListenerImpl();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(listener, parser.json());
}
}

View File

@@ -0,0 +1,143 @@
package net.woggioni.worth.serialization.json;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import net.woggioni.worth.antlr.JSONLexer;
import net.woggioni.worth.antlr.JSONListenerImpl;
import net.woggioni.worth.serialization.binary.JBONDumper;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.junit.Ignore;
import org.junit.Test;
import org.tukaani.xz.XZInputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class PerformanceTest {
@SneakyThrows
private static InputStream extractTestData() {
return new XZInputStream(new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/citylots.json.xz")));
}
private static InputStream smallTestData() {
return new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/wordpress.json"));
}
@Test
@Ignore
@SneakyThrows
public void profilerTest() {
while (true) {
Value value = new JSONParser().parse(getClass().getResourceAsStream("/wordpress.json"));
}
}
@Test
@SneakyThrows
public void loopTest() {
double jacksonTime, worthTime, antlrTime;
final int loops = 100;
Chronometer chr = new Chronometer();
{
ObjectMapper om = new ObjectMapper();
for(int j = 0; j < 2; j++) {
chr.reset();
for (int i = 0; i < loops; i++) {
JsonNode jsonNode = om.readTree(smallTestData());
}
}
jacksonTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
System.out.printf("Jackson time: %8s msec\n", String.format("%.3f", jacksonTime));
}
{
for(int j = 0; j < 2; j++) {
chr.reset();
for(int i = 0; i < loops; i++) {
Value value = new JSONParser().parse(smallTestData());
}
}
worthTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
System.out.printf("Worth time: %8s msec\n", String.format("%.3f", worthTime));
}
{
for(int j = 0; j < 2; j++) {
chr.reset();
for(int i = 0; i < loops; i++) {
CharStream inputStream = CharStreams.fromReader(new InputStreamReader(smallTestData()));
JSONLexer lexer = new JSONLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
net.woggioni.worth.antlr.JSONParser parser = new net.woggioni.worth.antlr.JSONParser(commonTokenStream);
JSONListenerImpl listener = new JSONListenerImpl();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(listener, parser.json());
}
}
antlrTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
System.out.printf("Antlr time: %8s msec\n", String.format("%.3f", antlrTime));
}
}
@Test
@Ignore
@SneakyThrows
public void hugeJSONTest() {
double jacksonTime, worthTime, antlrTime;
Chronometer chr = new Chronometer();
try(InputStream is = extractTestData()) {
chr.reset();
ObjectMapper om = new ObjectMapper();
om.readTree(is);
jacksonTime = chr.stop(Chronometer.TimeUnit.SECOND);
System.out.printf("Jackson time: %8s sec\n", String.format("%.3f", jacksonTime));
}
try(InputStream is = extractTestData()) {
chr.reset();
new JSONParser().parse(is);
worthTime = chr.stop(Chronometer.TimeUnit.SECOND);
System.out.printf("Worth time: %8s sec\n", String.format("%.3f", worthTime));
}
try(InputStream is = extractTestData()) {
chr.reset();
CharStream inputStream = CharStreams.fromReader(new InputStreamReader(is));
JSONLexer lexer = new JSONLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
net.woggioni.worth.antlr.JSONParser parser = new net.woggioni.worth.antlr.JSONParser(commonTokenStream);
JSONListenerImpl listener = new JSONListenerImpl();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(listener, parser.json());
antlrTime = chr.stop(Chronometer.TimeUnit.SECOND);
System.out.printf("Antlr time: %8s sec\n", String.format("%.3f", antlrTime));
}
}
@Test
@Ignore
@SneakyThrows
public void tess() {
Value value;
try(InputStream is = extractTestData()) {
Parser parser = JSONParser.newInstance();
value = parser.parse(is);
}
try(OutputStream os = new BufferedOutputStream(new FileOutputStream("/tmp/citylots.json"))) {
Dumper dumper = JSONDumper.newInstance();
dumper.dump(value, os);
}
try(OutputStream os = new BufferedOutputStream(new FileOutputStream("/tmp/citylots.jbon"))) {
Dumper dumper = JBONDumper.newInstance();
dumper.dump(value, os);
}
}
}