added antlr comparison test
This commit is contained in:
@@ -24,10 +24,14 @@ libraryDependencies += "org.projectlombok" % "lombok" % "1.18.2"
|
||||
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
|
||||
libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.6" % "test"
|
||||
|
||||
libraryDependencies += "org.antlr" % "antlr4" % "4.7.1" % "compile"
|
||||
libraryDependencies += "org.antlr" % "antlr4" % "4.7.1" % "test"
|
||||
libraryDependencies += "org.antlr" % "antlr4-runtime" % "4.7.1" % "test"
|
||||
libraryDependencies += "org.tukaani" % "xz" % "1.8" % "test"
|
||||
|
||||
artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
|
||||
artifact.name + "-" + module.revision + "." + artifact.extension
|
||||
}
|
||||
|
||||
enablePlugins(Antlr4Plugin)
|
||||
antlr4Version in Antlr4 := "4.7.1"
|
||||
antlr4PackageName in Antlr4 := Some("org.oggio88.worth.antlr")
|
@@ -7,3 +7,4 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.9.3")
|
||||
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "4.1.0")
|
||||
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.3")
|
||||
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")
|
||||
addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.1")
|
@@ -27,17 +27,27 @@ value
|
||||
| NUMBER
|
||||
| obj
|
||||
| array
|
||||
| 'true'
|
||||
| 'false'
|
||||
| 'null'
|
||||
| TRUE
|
||||
| FALSE
|
||||
| NULL
|
||||
;
|
||||
|
||||
TRUE
|
||||
: 'true'
|
||||
;
|
||||
|
||||
FALSE
|
||||
: 'false'
|
||||
;
|
||||
|
||||
NULL
|
||||
: 'null'
|
||||
;
|
||||
|
||||
STRING
|
||||
: '"' (ESC | SAFECODEPOINT)* '"'
|
||||
;
|
||||
|
||||
|
||||
fragment ESC
|
||||
: '\\' (["\\/bfnrt] | UNICODE)
|
||||
;
|
@@ -0,0 +1,25 @@
|
||||
package org.oggio88.worth.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class LookAheadInputStream extends InputStream {
|
||||
|
||||
private final InputStream stream;
|
||||
private int currentByte;
|
||||
|
||||
LookAheadInputStream(InputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int result = currentByte;
|
||||
currentByte = stream.read();
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getCurrentByte(){
|
||||
return currentByte;
|
||||
}
|
||||
}
|
@@ -23,6 +23,37 @@ public class JSONDumper extends ValueDumper {
|
||||
|
||||
protected Writer writer;
|
||||
|
||||
private String escapeString(String value){
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (char c : value.toCharArray()) {
|
||||
switch (c) {
|
||||
case '"':
|
||||
sb.append("\\\"");
|
||||
break;
|
||||
case '\r':
|
||||
sb.append("\\r");
|
||||
break;
|
||||
case '\n':
|
||||
sb.append("\\n");
|
||||
break;
|
||||
case '\t':
|
||||
sb.append("\\t");
|
||||
break;
|
||||
case '\\':
|
||||
sb.append("\\\\");
|
||||
break;
|
||||
default: {
|
||||
if (c < 128)
|
||||
sb.append(c);
|
||||
else {
|
||||
sb.append("\\u").append(String.format("%04X", (int) c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(Value value, OutputStream stream) {
|
||||
dump(value, new OutputStreamWriter(stream));
|
||||
@@ -121,40 +152,13 @@ public class JSONDumper extends ValueDumper {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected void objectKey(String key) {
|
||||
this.writer.write("\"" + key + "\"");
|
||||
this.writer.write("\"" + escapeString(key) + "\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected void stringValue(String value) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (char c : value.toCharArray()) {
|
||||
switch (c) {
|
||||
case '"':
|
||||
sb.append("\\\"");
|
||||
break;
|
||||
case '\r':
|
||||
sb.append("\\r");
|
||||
break;
|
||||
case '\n':
|
||||
sb.append("\\n");
|
||||
break;
|
||||
case '\t':
|
||||
sb.append("\\t");
|
||||
break;
|
||||
case '\\':
|
||||
sb.append("\\\\");
|
||||
break;
|
||||
default: {
|
||||
if (c < 128)
|
||||
sb.append(c);
|
||||
else {
|
||||
sb.append("\\u").append(String.format("%04X", (int) c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.writer.write("\"" + sb.toString() + "\"");
|
||||
this.writer.write("\"" + escapeString(value) + "\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,7 +1,10 @@
|
||||
package org.oggio88.worth.utils;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.oggio88.worth.buffer.CircularBuffer;
|
||||
import org.oggio88.worth.exception.ParseException;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class WorthUtils {
|
||||
|
102
src/test/java/org/oggio88/worth/antlr/JSONListenerImpl.java
Normal file
102
src/test/java/org/oggio88/worth/antlr/JSONListenerImpl.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package org.oggio88.worth.antlr;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
import org.oggio88.worth.serialization.ValueParser;
|
||||
import org.oggio88.worth.xface.Value;
|
||||
|
||||
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.get(0).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) {
|
||||
|
||||
}
|
||||
}
|
28
src/test/java/org/oggio88/worth/antlr/ParseTest.java
Normal file
28
src/test/java/org/oggio88/worth/antlr/ParseTest.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package org.oggio88.worth.antlr;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.junit.Test;
|
||||
import org.oggio88.worth.serialization.json.JSONDumper;
|
||||
import org.oggio88.worth.xface.Value;
|
||||
|
||||
public class ParseTest {
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void test(){
|
||||
|
||||
ANTLRInputStream inputStream = new ANTLRInputStream(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);
|
||||
// TestRig.main(new String[] {"org.oggio88.worth.antlr.JSON", "json", "-ps", "tree.ps", "src/test/resources/test.json"});
|
||||
}
|
||||
}
|
@@ -3,8 +3,13 @@ package org.oggio88.worth.serialization.json;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.SneakyThrows;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.oggio88.worth.antlr.JSONLexer;
|
||||
import org.oggio88.worth.antlr.JSONListenerImpl;
|
||||
import org.oggio88.worth.xface.Value;
|
||||
import org.tukaani.xz.XZInputStream;
|
||||
|
||||
@@ -65,7 +70,7 @@ public class PerformanceTest {
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void loopTest() {
|
||||
double jacksonTime, worthTime;
|
||||
double jacksonTime, worthTime, antlrTime;
|
||||
final int loops = 100;
|
||||
Chronometer chr = new Chronometer();
|
||||
{
|
||||
@@ -85,6 +90,21 @@ public class PerformanceTest {
|
||||
worthTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
|
||||
System.out.printf("Worth time: %8s msec\n", String.format("%.3f", worthTime));
|
||||
}
|
||||
{
|
||||
chr.reset();
|
||||
for (int i = 0; i < loops; i++) {
|
||||
ANTLRInputStream inputStream = new ANTLRInputStream(
|
||||
getClass().getResourceAsStream("/wordpress.json"));
|
||||
JSONLexer lexer = new JSONLexer(inputStream);
|
||||
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
|
||||
org.oggio88.worth.antlr.JSONParser parser = new org.oggio88.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
|
||||
@@ -92,7 +112,7 @@ public class PerformanceTest {
|
||||
@SneakyThrows
|
||||
public void hugeJSONTest() {
|
||||
byte[] testData = extractTestData();
|
||||
double jacksonTime, worthTime;
|
||||
double jacksonTime, worthTime, antlrTime;
|
||||
Chronometer chr = new Chronometer();
|
||||
{
|
||||
chr.reset();
|
||||
@@ -107,5 +127,17 @@ public class PerformanceTest {
|
||||
worthTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
||||
System.out.printf("Worth time: %8s sec\n", String.format("%.3f", worthTime));
|
||||
}
|
||||
{
|
||||
chr.reset();
|
||||
ANTLRInputStream inputStream = new ANTLRInputStream(new ByteArrayInputStream(testData));
|
||||
JSONLexer lexer = new JSONLexer(inputStream);
|
||||
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
|
||||
org.oggio88.worth.antlr.JSONParser parser = new org.oggio88.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user