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.novocode" % "junit-interface" % "0.11" % "test"
|
||||||
libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.6" % "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.antlr" % "antlr4-runtime" % "4.7.1" % "test"
|
||||||
libraryDependencies += "org.tukaani" % "xz" % "1.8" % "test"
|
libraryDependencies += "org.tukaani" % "xz" % "1.8" % "test"
|
||||||
|
|
||||||
artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
|
artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
|
||||||
artifact.name + "-" + module.revision + "." + artifact.extension
|
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("de.heikoseeberger" % "sbt-header" % "4.1.0")
|
||||||
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.3")
|
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.3")
|
||||||
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")
|
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")
|
||||||
|
addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.1")
|
@@ -27,17 +27,27 @@ value
|
|||||||
| NUMBER
|
| NUMBER
|
||||||
| obj
|
| obj
|
||||||
| array
|
| array
|
||||||
| 'true'
|
| TRUE
|
||||||
| 'false'
|
| FALSE
|
||||||
| 'null'
|
| NULL
|
||||||
;
|
;
|
||||||
|
|
||||||
|
TRUE
|
||||||
|
: 'true'
|
||||||
|
;
|
||||||
|
|
||||||
|
FALSE
|
||||||
|
: 'false'
|
||||||
|
;
|
||||||
|
|
||||||
|
NULL
|
||||||
|
: 'null'
|
||||||
|
;
|
||||||
|
|
||||||
STRING
|
STRING
|
||||||
: '"' (ESC | SAFECODEPOINT)* '"'
|
: '"' (ESC | SAFECODEPOINT)* '"'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
fragment ESC
|
fragment ESC
|
||||||
: '\\' (["\\/bfnrt] | UNICODE)
|
: '\\' (["\\/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;
|
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
|
@Override
|
||||||
public void dump(Value value, OutputStream stream) {
|
public void dump(Value value, OutputStream stream) {
|
||||||
dump(value, new OutputStreamWriter(stream));
|
dump(value, new OutputStreamWriter(stream));
|
||||||
@@ -121,40 +152,13 @@ public class JSONDumper extends ValueDumper {
|
|||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected void objectKey(String key) {
|
protected void objectKey(String key) {
|
||||||
this.writer.write("\"" + key + "\"");
|
this.writer.write("\"" + escapeString(key) + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected void stringValue(String value) {
|
protected void stringValue(String value) {
|
||||||
StringBuilder sb = new StringBuilder();
|
this.writer.write("\"" + escapeString(value) + "\"");
|
||||||
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() + "\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
package org.oggio88.worth.utils;
|
package org.oggio88.worth.utils;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import org.oggio88.worth.buffer.CircularBuffer;
|
||||||
|
import org.oggio88.worth.exception.ParseException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class WorthUtils {
|
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.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.SneakyThrows;
|
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.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.oggio88.worth.antlr.JSONLexer;
|
||||||
|
import org.oggio88.worth.antlr.JSONListenerImpl;
|
||||||
import org.oggio88.worth.xface.Value;
|
import org.oggio88.worth.xface.Value;
|
||||||
import org.tukaani.xz.XZInputStream;
|
import org.tukaani.xz.XZInputStream;
|
||||||
|
|
||||||
@@ -65,7 +70,7 @@ public class PerformanceTest {
|
|||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void loopTest() {
|
public void loopTest() {
|
||||||
double jacksonTime, worthTime;
|
double jacksonTime, worthTime, antlrTime;
|
||||||
final int loops = 100;
|
final int loops = 100;
|
||||||
Chronometer chr = new Chronometer();
|
Chronometer chr = new Chronometer();
|
||||||
{
|
{
|
||||||
@@ -85,6 +90,21 @@ public class PerformanceTest {
|
|||||||
worthTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
|
worthTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
|
||||||
System.out.printf("Worth time: %8s msec\n", String.format("%.3f", worthTime));
|
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
|
@Test
|
||||||
@@ -92,7 +112,7 @@ public class PerformanceTest {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void hugeJSONTest() {
|
public void hugeJSONTest() {
|
||||||
byte[] testData = extractTestData();
|
byte[] testData = extractTestData();
|
||||||
double jacksonTime, worthTime;
|
double jacksonTime, worthTime, antlrTime;
|
||||||
Chronometer chr = new Chronometer();
|
Chronometer chr = new Chronometer();
|
||||||
{
|
{
|
||||||
chr.reset();
|
chr.reset();
|
||||||
@@ -107,5 +127,17 @@ public class PerformanceTest {
|
|||||||
worthTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
worthTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
||||||
System.out.printf("Worth time: %8s sec\n", String.format("%.3f", worthTime));
|
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