Skip to content
Snippets Groups Projects
Commit 4a507826 authored by Johannes Mey's avatar Johannes Mey
Browse files

serializer and deserializer (reference resolving not working)

parent bf521752
No related branches found
No related tags found
1 merge request!1Mquat2
*.jarsrc/test/java/org/jastadd/relast/tests/Resolver2.java *.jar
.idea/ .idea/
.gradle/ .gradle/
build build
...@@ -8,6 +8,8 @@ out/ ...@@ -8,6 +8,8 @@ out/
*.class *.class
src/test/jastadd/relations/Relations.ast src/test/jastadd/relations/Relations.ast
src/test/jastadd/relations/Relations.jadd src/test/jastadd/relations/Relations.jadd
src/test/jastadd/relations/Relations2.ast
src/test/jastadd/relations/Relations2.jadd
src/test/jastadd/lowerbounds/LowerBounds.ast src/test/jastadd/lowerbounds/LowerBounds.ast
src/test/jastadd/lowerbounds/LowerBounds.jadd src/test/jastadd/lowerbounds/LowerBounds.jadd
src/test/jastadd/multiple/Multiple.ast src/test/jastadd/multiple/Multiple.ast
...@@ -15,8 +17,14 @@ src/test/jastadd/multiple/Multiple.jadd ...@@ -15,8 +17,14 @@ src/test/jastadd/multiple/Multiple.jadd
src/test/jastadd/resolver/Resolver.ast src/test/jastadd/resolver/Resolver.ast
src/test/jastadd/resolver/Resolver.jadd src/test/jastadd/resolver/Resolver.jadd
src/test/jastadd/resolver/ResolverRefResolver.jadd src/test/jastadd/resolver/ResolverRefResolver.jadd
src/test/jastadd/resolver/ResolverResolverStubs.jrag
src/test/jastadd/resolver2/Resolver.ast src/test/jastadd/resolver2/Resolver.ast
src/test/jastadd/resolver2/Resolver.jadd src/test/jastadd/resolver2/Resolver.jadd
src/test/jastadd/resolver2/ResolverRefResolver.jadd src/test/jastadd/resolver2/ResolverRefResolver.jadd
src/test/jastadd/resolver2/ResolverResolverStubs.jrag
src/test/jastadd/listnames/ListNames.ast src/test/jastadd/listnames/ListNames.ast
src/test/jastadd/listnames/ListNames.jadd src/test/jastadd/listnames/ListNames.jadd
src/test/jastadd/serializer/Serializer.ast
src/test/jastadd/serializer/Serializer.jadd
src/test/jastadd/serializer/SerializerSerializer.jadd
src/test/jastadd/serializer/SerializerRefResolver.jadd
...@@ -21,6 +21,8 @@ buildscript { ...@@ -21,6 +21,8 @@ buildscript {
dependencies { dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.8'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
runtime 'org.jastadd:jastadd:2.3.2' runtime 'org.jastadd:jastadd:2.3.2'
compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0' compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
...@@ -49,6 +51,7 @@ jar { ...@@ -49,6 +51,7 @@ jar {
jastadd { jastadd {
configureModuleBuild() configureModuleBuild()
modules { modules {
//noinspection GroovyAssignabilityCheck
module("RelAst") { module("RelAst") {
java { java {
...@@ -110,6 +113,7 @@ task preprocessRelationTest(type: JavaExec, group: 'verification') { ...@@ -110,6 +113,7 @@ task preprocessRelationTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/relations/Relations.relast', '--file', '--grammarName=src/test/jastadd/relations/Relations' args 'src/test/jastadd/relations/Relations.relast', '--file', '--grammarName=src/test/jastadd/relations/Relations'
} }
...@@ -121,6 +125,7 @@ task doublePreprocessRelationTest(type: JavaExec, group: 'verification') { ...@@ -121,6 +125,7 @@ task doublePreprocessRelationTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/relations/Relations.ast', '--file', '--grammarName=src/test/jastadd/relations/Relations2' args 'src/test/jastadd/relations/Relations.ast', '--file', '--grammarName=src/test/jastadd/relations/Relations2'
} }
...@@ -132,7 +137,11 @@ task compileRelationTest(type: JavaExec, group: 'verification') { ...@@ -132,7 +137,11 @@ task compileRelationTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd' main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=relations.ast', 'src/test/jastadd/relations/Relations.ast', 'src/test/jastadd/relations/Relations.jadd', 'src/test/jastadd/Utils.jadd' //noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=relations.ast',
'src/test/jastadd/relations/Relations.ast',
'src/test/jastadd/relations/Relations.jadd',
'src/test/jastadd/Utils.jadd'
} }
task preprocessLowerBoundsTest(type: JavaExec, group: 'verification') { task preprocessLowerBoundsTest(type: JavaExec, group: 'verification') {
...@@ -143,6 +152,7 @@ task preprocessLowerBoundsTest(type: JavaExec, group: 'verification') { ...@@ -143,6 +152,7 @@ task preprocessLowerBoundsTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/lowerbounds/LowerBounds.relast', '--file', '--grammarName=src/test/jastadd/lowerbounds/LowerBounds' args 'src/test/jastadd/lowerbounds/LowerBounds.relast', '--file', '--grammarName=src/test/jastadd/lowerbounds/LowerBounds'
} }
...@@ -154,7 +164,11 @@ task compileLowerBoundsTest(type: JavaExec, group: 'verification') { ...@@ -154,7 +164,11 @@ task compileLowerBoundsTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd' main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=lowerbounds.ast', 'src/test/jastadd/lowerbounds/LowerBounds.ast', 'src/test/jastadd/lowerbounds/LowerBounds.jadd', 'src/test/jastadd/Utils.jadd' //noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=lowerbounds.ast',
'src/test/jastadd/lowerbounds/LowerBounds.ast',
'src/test/jastadd/lowerbounds/LowerBounds.jadd',
'src/test/jastadd/Utils.jadd'
} }
task preprocessMultipleTest(type: JavaExec, group: 'verification') { task preprocessMultipleTest(type: JavaExec, group: 'verification') {
...@@ -165,6 +179,7 @@ task preprocessMultipleTest(type: JavaExec, group: 'verification') { ...@@ -165,6 +179,7 @@ task preprocessMultipleTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/multiple/Part1.relast', 'src/test/jastadd/multiple/Part2.relast', 'src/test/jastadd/multiple/Part3.relast', '--file', '--grammarName=src/test/jastadd/multiple/Multiple' args 'src/test/jastadd/multiple/Part1.relast', 'src/test/jastadd/multiple/Part2.relast', 'src/test/jastadd/multiple/Part3.relast', '--file', '--grammarName=src/test/jastadd/multiple/Multiple'
} }
...@@ -176,17 +191,22 @@ task compileMultipleTest(type: JavaExec, group: 'verification') { ...@@ -176,17 +191,22 @@ task compileMultipleTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd' main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=multiple.ast', 'src/test/jastadd/multiple/Multiple.ast', 'src/test/jastadd/multiple/Multiple.jadd', 'src/test/jastadd/Utils.jadd' //noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=multiple.ast',
'src/test/jastadd/multiple/Multiple.ast',
'src/test/jastadd/multiple/Multiple.jadd',
'src/test/jastadd/Utils.jadd'
} }
task preprocessResolverTest(type: JavaExec, group: 'verification') { task preprocessResolverTest(type: JavaExec, group: 'verification') {
doFirst { doFirst {
delete 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd' delete 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd', 'src/test/jastadd/resolver/ResolverResolverStubs.jrag'
} }
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/resolver/Resolver.relast', '--file', '--grammarName=src/test/jastadd/resolver/Resolver', '--resolverHelper' args 'src/test/jastadd/resolver/Resolver.relast', '--file', '--grammarName=src/test/jastadd/resolver/Resolver', '--resolverHelper'
} }
...@@ -198,7 +218,15 @@ task compileResolverTest(type: JavaExec, group: 'verification') { ...@@ -198,7 +218,15 @@ task compileResolverTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd' main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=resolver.ast', 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverUtils.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd', 'src/test/jastadd/resolver/MyRefResolver.jadd', 'src/test/jastadd/Utils.jadd' //noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=resolver.ast',
'src/test/jastadd/resolver/Resolver.ast',
'src/test/jastadd/resolver/Resolver.jadd',
'src/test/jastadd/resolver/ResolverUtils.jadd',
'src/test/jastadd/resolver/ResolverRefResolver.jadd',
'src/test/jastadd/resolver/ResolverResolverStubs.jrag',
'src/test/jastadd/resolver/MyRefResolver.jadd',
'src/test/jastadd/Utils.jadd'
} }
...@@ -210,6 +238,7 @@ task preprocessResolver2Test(type: JavaExec, group: 'verification') { ...@@ -210,6 +238,7 @@ task preprocessResolver2Test(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/resolver2/Resolver.relast', '--file', '--grammarName=src/test/jastadd/resolver2/Resolver', '--resolverHelper' args 'src/test/jastadd/resolver2/Resolver.relast', '--file', '--grammarName=src/test/jastadd/resolver2/Resolver', '--resolverHelper'
} }
...@@ -221,7 +250,15 @@ task compileResolver2Test(type: JavaExec, group: 'verification') { ...@@ -221,7 +250,15 @@ task compileResolver2Test(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd' main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=resolver2.ast', 'src/test/jastadd/resolver2/Resolver.ast', 'src/test/jastadd/resolver2/Resolver.jadd', 'src/test/jastadd/resolver2/ResolverUtils.jadd', 'src/test/jastadd/resolver2/ResolverRefResolver.jadd', 'src/test/jastadd/resolver2/MyRefResolver.jadd', 'src/test/jastadd/Utils.jadd' //noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=resolver2.ast',
'src/test/jastadd/resolver2/Resolver.ast',
'src/test/jastadd/resolver2/Resolver.jadd',
'src/test/jastadd/resolver2/ResolverUtils.jadd',
'src/test/jastadd/resolver2/ResolverRefResolver.jadd',
'src/test/jastadd/resolver2/ResolverResolverStubs.jrag',
'src/test/jastadd/resolver2/MyRefResolver.jadd',
'src/test/jastadd/Utils.jadd'
} }
task preprocessListNamesTest(type: JavaExec, group: 'verification') { task preprocessListNamesTest(type: JavaExec, group: 'verification') {
...@@ -232,6 +269,7 @@ task preprocessListNamesTest(type: JavaExec, group: 'verification') { ...@@ -232,6 +269,7 @@ task preprocessListNamesTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler' main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/listnames/ListNames.relast', '--file', '--grammarName=src/test/jastadd/listnames/ListNames', '--jastAddList=ListyMcListface' args 'src/test/jastadd/listnames/ListNames.relast', '--file', '--grammarName=src/test/jastadd/listnames/ListNames', '--jastAddList=ListyMcListface'
} }
...@@ -243,9 +281,44 @@ task compileListNamesTest(type: JavaExec, group: 'verification') { ...@@ -243,9 +281,44 @@ task compileListNamesTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd' main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=listnames.ast', 'src/test/jastadd/listnames/ListNames.ast', 'src/test/jastadd/listnames/ListNames.jadd', 'src/test/jastadd/Utils.jadd', '--List=ListyMcListface' //noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=listnames.ast', '--List=ListyMcListface',
'src/test/jastadd/listnames/ListNames.ast',
'src/test/jastadd/listnames/ListNames.jadd',
'src/test/jastadd/Utils.jadd'
} }
task preprocessSerializerTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/jastadd/serializer/Serializer.ast',
'src/test/jastadd/serializer/Serializer.jadd',
'src/test/jastadd/serializer/SerializerRefResolver.jadd',
'src/test/jastadd/serializer/SerializerSerializer.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/serializer/Serializer.relast', '--file', '--grammarName=src/test/jastadd/serializer/Serializer', '--serializer=jackson'
}
task compileSerializerTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/java-gen/serializer'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=serializer.ast',
'src/test/jastadd/serializer/Serializer.ast',
'src/test/jastadd/serializer/Serializer.jadd',
'src/test/jastadd/serializer/SerializerRefResolver.jadd',
'src/test/jastadd/serializer/SerializerSerializer.jadd',
'src/test/jastadd/Utils.jadd'
}
test { test {
outputs.upToDateWhen { false } outputs.upToDateWhen { false }
...@@ -271,3 +344,6 @@ compileResolver2Test.dependsOn preprocessResolver2Test ...@@ -271,3 +344,6 @@ compileResolver2Test.dependsOn preprocessResolver2Test
test.dependsOn compileListNamesTest test.dependsOn compileListNamesTest
compileListNamesTest.dependsOn preprocessListNamesTest compileListNamesTest.dependsOn preprocessListNamesTest
test.dependsOn compileSerializerTest
compileSerializerTest.dependsOn preprocessSerializerTest
\ No newline at end of file
...@@ -4,6 +4,7 @@ aspect BackendAbstractGrammar { ...@@ -4,6 +4,7 @@ aspect BackendAbstractGrammar {
public static String ASTNode.jastAddListType = "List"; public static String ASTNode.jastAddListType = "List";
public static boolean ASTNode.resolverHelper = false; public static boolean ASTNode.resolverHelper = false;
public static boolean ASTNode.serializer = false;
public String Program.generateAbstractGrammar() { public String Program.generateAbstractGrammar() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
...@@ -694,7 +695,13 @@ aspect NameResolutionHelper { ...@@ -694,7 +695,13 @@ aspect NameResolutionHelper {
return sb.toString(); return sb.toString();
} }
public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) { public String Program.generateResolverStubs() {
StringBuilder sb = new StringBuilder();
generateResolverStubs(sb);
return sb.toString();
}
public void Program.generateResolverStubs(StringBuilder sb) {
sb.append("aspect RefResolverStubs {\n\n"); sb.append("aspect RefResolverStubs {\n\n");
for (Relation r: getRelations()) { for (Relation r: getRelations()) {
...@@ -708,6 +715,9 @@ aspect NameResolutionHelper { ...@@ -708,6 +715,9 @@ aspect NameResolutionHelper {
} }
} }
sb.append("}\n\n"); sb.append("}\n\n");
}
public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) {
sb.append("aspect ReferenceCreation {\n\n"); sb.append("aspect ReferenceCreation {\n\n");
...@@ -871,6 +881,391 @@ aspect NameResolutionHelper { ...@@ -871,6 +881,391 @@ aspect NameResolutionHelper {
} }
} }
aspect Serializer {
protected static String ASTNode.jsonTypeKey = "type";
protected static String ASTNode.jsonNodeType = "com.fasterxml.jackson.databind.JsonNode";
protected static String ASTNode.jsonNodeTypeAccessor = ".get(\"" + jsonTypeKey + "\").asText()";
public String Program.generateSerializer() {
StringBuilder sb = new StringBuilder();
generateFromJson(sb);
generateToJson(sb);
writeUID(sb);
return sb.toString();
}
public void Program.generateFromJson(StringBuilder sb) {
sb.append("aspect JsonToModel {\n");
sb.append(ind(1) + "public class DeserializationException extends Exception {\n");
sb.append(ind(2) + "public DeserializationException(String message) {\n");
sb.append(ind(3) + "super(message);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "public DeserializationException(String message, Exception cause) {\n");
sb.append(ind(3) + "super(message, cause);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.serialize(com.fasterxml.jackson.core.JsonGenerator g) throws SerializationException {\n");
sb.append(ind(2) + "serialize(g, null);\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.serialize(com.fasterxml.jackson.core.JsonGenerator g, String field) throws SerializationException {\n");
sb.append(ind(2) + "throw new SerializationException(\"unable to serialize class \" + this.getClass().getSimpleName());\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.serialize(java.io.File file) throws SerializationException {\n");
sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(file, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n");
sb.append(ind(3) + "generator.setPrettyPrinter(new com.fasterxml.jackson.core.util.DefaultPrettyPrinter());\n");
sb.append(ind(3) + "serialize(generator);\n");
sb.append(ind(3) + "generator.close();\n");
sb.append(ind(2) + "} catch (java.io.IOException e) {\n");
sb.append(ind(3) + "throw new SerializationException(\"Unable to serialize file \" + file.getAbsolutePath(), e);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl decl : getTypeDeclList()) {
if (!decl.isUnresolved()) {
decl.deserialize(sb);
}
}
sb.append("}\n");
}
public void Program.generateToJson(StringBuilder sb) {
sb.append("aspect ModelToJson {\n");
sb.append(ind(1) + "public class SerializationException extends Exception {\n");
sb.append(ind(2) + "public SerializationException(String message) {\n");
sb.append(ind(3) + "super(message);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "public SerializationException(String message, Exception cause) {\n");
sb.append(ind(3) + "super(message, cause);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl decl : getTypeDeclList()) {
if (!decl.isUnresolved()) {
decl.serialize(sb);
}
}
sb.append("}\n");
}
public void TypeDecl.serialize(StringBuilder sb) {
sb.append(ind(1) + "public void " + getID() + ".serialize(com.fasterxml.jackson.core.JsonGenerator g, String fieldName) throws SerializationException {\n");
sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "if (fieldName == null) {\n");
sb.append(ind(4) + "g.writeStartObject();\n");
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "g.writeObjectFieldStart(fieldName);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "g.writeStringField(\"" + jsonTypeKey + "\", \"" + getID() + "\");\n");
sb.append(ind(3) + "g.writeStringField(\"id\", __uid());\n");
if (componentsTransitive().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"children\");\n");
for (Component child : componentsTransitive()) {
child.serialize(sb, 3);
}
sb.append(ind(3) + "g.writeEndObject(); // children\n");
}
if (relationComponents().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"relations\");\n");
for (RelationComponent relation : relationComponents()) {
relation.serialize(sb, 3);
}
sb.append(ind(3) + "g.writeEndObject(); // relations\n");
}
sb.append(ind(3) + "g.writeEndObject();\n");
sb.append(ind(2) + "} catch (java.io.IOException e) {\n");
sb.append(ind(3) + "throw new SerializationException(\"unable to serialize " + getID() + "\", e);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public abstract void Component.serialize(StringBuilder sb, int indent);
public void NormalComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "get" + getID() + "().serialize(g, \"" + getID() + "\");\n");
}
public void OptComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + getID() + "()) {\n");
sb.append(ind(indent + 1) + "get" + getID() + "().serialize(g, \"" + getID() + "\");\n");
sb.append(ind(indent) + "}\n");
}
public void TokenComponent.serialize(StringBuilder sb, int indent) {
String type = getTypeUse().getID();
switch (type) {
case "float":
case "Float":
case "double":
case "Double":
case "int":
case "Integer":
case "short":
case "Short":
case "long":
case "Long":
case "byte":
case "Byte":
sb.append(ind(indent) + "g.writeNumberField(\"" + getID() + "\", get" + getID() + "());\n");
break;
case "boolean":
case "Boolean":
sb.append(ind(indent) + "g.writeBooleanField(\"" + getID() + "\", get" + getID() + "());\n");
break;
case "char":
case "Character":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", Character.toString(get"+ getID() + "()));\n");
break;
case "String":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "());\n");
break;
case "java.time.Instant":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "()).toString());\n");
break;
case "java.time.Period":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "()).toString());\n");
break;
default:
// assume that the type is an enum. there is no way of checking this here
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "()).name());\n");
// sb.append("throw new DeserializationException(\"Unable to deserialize child node of type \"" + getTypeUse() + "\"\")")
}
}
public void NTAComponent.serialize(StringBuilder sb, int indent) {
// do not serialize NTA
}
public void ListComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (getNum" + getID() + "() > 0) {\n");
sb.append(ind(indent + 1) + "g.writeArrayFieldStart(\"" + getID() + "\");\n");
sb.append(ind(indent + 1) + "for (" + getTypeUse().decl().getID() + " child : get" + getID() + "List()) {\n");
sb.append(ind(indent + 2) + "child.serialize(g);\n");
sb.append(ind(indent + 1) + "}\n");
sb.append(ind(indent + 1) + "g.writeEndArray();\n");
sb.append(ind(indent) + "}\n");
}
public void OneRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().__uid());\n");
}
public void OptionalRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + getID() + "()) {\n");
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().__uid());\n");
sb.append(ind(indent) + "}\n");
}
public void ManyRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "g.writeArrayFieldStart(\"" + getID() + "\");\n");
sb.append(ind(indent) + "for (" + ofTypeDecl().getID() + " child : get" + getID() + "List()) {\n");
sb.append(ind(indent + 1) + "g.writeString(child.__uid());\n");
sb.append(ind(indent) + "}\n");
sb.append(ind(indent) + "g.writeEndArray();\n");
}
public void TypeDecl.deserialize(StringBuilder sb) {
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".deserialize(java.io.File file) throws DeserializationException {\n");
sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonFactory factory = mapper.getFactory();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonParser parser = factory.createParser(file);\n");
sb.append(ind(3) + "return deserialize((com.fasterxml.jackson.databind.JsonNode)mapper.readTree(parser));\n");
sb.append(ind(2) + "} catch (java.io.IOException e) {\n");
sb.append(ind(3) + "throw new DeserializationException(\"unable to deserialize \" + file.getAbsolutePath(), e);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".deserialize(" + jsonNodeType + " node) throws DeserializationException {\n");
sb.append(ind(2) + getID() + " element;\n");
if (getAbstract()) {
// switch case between all implementations of the abstract class
sb.append(ind(2) + "switch (node" + jsonNodeTypeAccessor + ") {\n");
for (TypeDecl subType : subTypeDecls()) {
sb.append(ind(3) + "case \"" + subType.getID() + "\":\n");
sb.append(ind(4) + "element = " + subType.getID() + ".deserialize(node);\n");
sb.append(ind(4) + "break;\n");
}
sb.append(ind(3) + "default:\n");
sb.append(ind(4) + "throw new DeserializationException(\"Unable to deserialize child of unexpected type \" + node" + jsonNodeTypeAccessor + " + \"(" + getID() + " expected)\");\n");
sb.append(ind(2) + "}\n");
} else {
sb.append(ind(2) + "element = new " + getID() + "();\n");
}
// deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.__uid = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n");
// deserialize containment children
if (componentsTransitive().size() > 0) {
sb.append(ind(2) + "if (node.has(\"children\")) {\n");
sb.append(ind(3) + jsonNodeType + " children = node.get(\"children\");\n");
for (Component component : componentsTransitive()) {
sb.append(ind(3) + "if (children.has(\"" + component.getID() + "\")) {\n");
component.deserialize(sb, 4);
sb.append(ind(3) + "}\n");
}
sb.append(ind(2) + "}\n");
}
// deserialize non-containment children
Set<RelationComponent> relationComponents = relationComponents();
if (relationComponents.size() > 0) {
sb.append(ind(2) + "if (node.has(\"relations\")) {\n");
sb.append(ind(3) + jsonNodeType + " relations = node.get(\"relations\");\n");
for (RelationComponent component : relationComponents) {
sb.append(ind(3) + "if (relations.has(\"" + component.getID() + "\")) {\n");
component.deserialize(sb, 4);
sb.append(ind(3) + "}\n");
}
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return element;\n");
sb.append(ind(1) + "}\n");
}
public abstract void Component.deserialize(StringBuilder sb, int indent);
public void NormalComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "element.set" + getID() + "(" + getTypeUse().decl().getID() + ".deserialize(children.get(\"" + getID() + "\")));\n");
sb.append(ind(indent - 1) + "} else {\n");
sb.append(ind(indent) + "throw new DeserializationException(\"deserializer of missing mandatory child " + getID() + "\");\n");
}
public void OptComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent + 1) + "element.set" + getID() + "(" + getTypeUse().decl().getID() + ".deserialize(children.get(\"" + getID() + "\")));\n");
}
public void TokenComponent.deserialize(StringBuilder sb, int indent) {
String type = getTypeUse().getID();
switch (type) {
case "float":
case "Float":
sb.append(ind(indent) + "element.set" + getID() + "(Float.valueOf(children.get(\"" + getID() + "\").asText()));\n");
break;
case "double":
case "Double":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asDouble());\n");
break;
case "int":
case "Integer":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asInt());\n");
break;
case "short":
case "Short":
sb.append(ind(indent) + "element.set" + getID() + "(Short.valueOf(children.get(\"" + getID() + "\").asText()));\n");
break;
case "long":
case "Long":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asLong());\n");
break;
case "byte":
case "Byte":
sb.append(ind(indent) + "element.set" + getID() + "(Byte.valueOf(children.get(\"" + getID() + "\").asText()));\n");
break;
case "boolean":
case "Boolean":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asBoolean());\n");
break;
case "char":
case "Character":
sb.append(ind(indent) + "String chars = children.get(\"" + getID() + "\").asText();\n");
sb.append(ind(indent) + "if (chars.length() == 1) {\n");
sb.append(ind(indent + 2) + "element.set" + getID() + "(chars.charAt(0))\n");
sb.append(ind(indent) + "} else {\n");
sb.append(ind(indent + 2) + "throw new DeserializationException(\"unable to deserialize char '\" + chars + \"'\");\n");
sb.append(ind(indent) + "}\n");
break;
case "String":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asText());\n");
break;
case "java.time.Instant":
sb.append(ind(indent) + "element.set" + getID() + "(java.time.Instant.parse(children.get(\"" + getID() + "\").asText()));\n");
break;
case "java.time.Period":
sb.append(ind(indent) + "element.set" + getID() + "(java.time.Period.parse(children.get(\"" + getID() + "\").asText()));\n");
break;
default:
// assume that the type is an enum. there is no way of checking this here
sb.append(ind(indent) + "element.set" + getID() + "Enum.valueOf(" + type + ".getClass(), children.get(\"" + getID() + "\".asText())));\n");
// sb.append("throw new DeserializationException(\"Unable to deserialize child node of type \"" + getTypeUse() + "\"\")")
}
}
public void Program.writeUID(StringBuilder sb) {
sb.append("aspect UID {\n");
sb.append(ind(1) + "class UIDProvider {\n");
sb.append(ind(2) + "private static long nextUID = 0;\n");
sb.append(ind(2) + "public static String getUID() {\n");
sb.append(ind(3) + "return String.valueOf(nextUID++);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append("\n");
sb.append(ind(1) + "protected String ASTNode.__uid = null;\n");
sb.append("\n");
sb.append(ind(1) + "protected String ASTNode.__uid() {\n");
sb.append(ind(2) + "String customUID = serializationID();\n");
sb.append(ind(2) + "if (customUID == null) {\n");
sb.append(ind(3) + "if (__uid == null) {\n");
sb.append(ind(4) + "__uid = UIDProvider.getUID();\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "return __uid;\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "return customUID;\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append("\n");
sb.append(ind(1) + "protected String ASTNode.serializationID() {\n");
sb.append(ind(2) + "return null;\n");
sb.append(ind(1) + "}\n");
sb.append("}\n");
}
public void NTAComponent.deserialize(StringBuilder sb, int indent) {
// do not serialize NTA
}
public void ListComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "for (" + jsonNodeType + " child : children.get(\"" + getID() + "\")) {\n");
sb.append(ind(indent + 1) + "element.add" + getID() + "(" + getTypeUse().decl().getID() + ".deserialize(child));\n");
sb.append(ind(indent) + "}\n");
}
public void OneRelationComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "element.set" + getID() + "(" + ofTypeDecl().getID() + ".createRefDirection(relations.get(\"" + getID() + "\").asText()));\n");
sb.append(ind(indent - 1) + "} else {\n");
sb.append(ind(indent) + "throw new DeserializationException(\"deserializer of missing mandatory relation child " + getID() + "\");\n");
}
public void OptionalRelationComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "element.set" + getID() + "(" + ofTypeDecl().getID() + ".createRefDirection(relations.get(\"" + getID() + "\").asText()));\n");
}
public void ManyRelationComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "for (" + jsonNodeType + " child : relations.get(\"" + getID() + "\")) {\n");
sb.append(ind(indent + 1) + "element.add" + getID() + "(" + ofTypeDecl().getID() + ".createRefDirection(child.asText()));\n");
sb.append(ind(indent) + "}\n");
}
}
aspect PrettyPrint { aspect PrettyPrint {
public String Relation.prettyPrint() { public String Relation.prettyPrint() {
return "rel " return "rel "
......
...@@ -2,16 +2,14 @@ package org.jastadd.relast.compiler; ...@@ -2,16 +2,14 @@ package org.jastadd.relast.compiler;
import beaver.Parser; import beaver.Parser;
import org.jastadd.relast.ast.*; import org.jastadd.relast.ast.*;
import org.jastadd.relast.compiler.options.CommandLine; import org.jastadd.relast.compiler.options.*;
import org.jastadd.relast.compiler.options.CommandLine.CommandLineException; import org.jastadd.relast.compiler.options.CommandLine.CommandLineException;
import org.jastadd.relast.compiler.options.FlagOption;
import org.jastadd.relast.compiler.options.Option;
import org.jastadd.relast.compiler.options.StringOption;
import org.jastadd.relast.parser.RelAstParser; import org.jastadd.relast.parser.RelAstParser;
import org.jastadd.relast.scanner.RelAstScanner; import org.jastadd.relast.scanner.RelAstScanner;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
public class Compiler { public class Compiler {
...@@ -21,6 +19,7 @@ public class Compiler { ...@@ -21,6 +19,7 @@ public class Compiler {
private StringOption optionListClass; private StringOption optionListClass;
private StringOption optionJastAddList; private StringOption optionJastAddList;
private StringOption optionGrammarName; private StringOption optionGrammarName;
private EnumOption optionSerializer;
private FlagOption optionResolverHelper; private FlagOption optionResolverHelper;
private CommandLine commandLine; private CommandLine commandLine;
...@@ -45,7 +44,7 @@ public class Compiler { ...@@ -45,7 +44,7 @@ public class Compiler {
} }
if (optionResolverHelper.isSet()) { if (optionResolverHelper.isSet() || optionSerializer.isSet()) {
// get a list of all (abstract or not) non-terminals // get a list of all (abstract or not) non-terminals
List<TypeDecl> nonTerminals = new ArrayList<>(); List<TypeDecl> nonTerminals = new ArrayList<>();
for (TypeDecl typeDecl : p.getTypeDecls()) { for (TypeDecl typeDecl : p.getTypeDecls()) {
...@@ -88,8 +87,21 @@ public class Compiler { ...@@ -88,8 +87,21 @@ public class Compiler {
if (optionWriteToFile.isSet()) { if (optionWriteToFile.isSet()) {
if (optionSerializer.isSet()) {
ASTNode.serializer = true;
switch (optionSerializer.getValue()) {
case "jackson":
writeToFile(grammarName + "Serializer.jadd", p.generateSerializer());
break;
}
}
if (optionResolverHelper.isSet()) { if (optionResolverHelper.isSet()) {
ASTNode.resolverHelper = true; ASTNode.resolverHelper = true;
writeToFile(grammarName + "ResolverStubs.jrag", p.generateResolverStubs());
}
if (optionSerializer.isSet() || optionResolverHelper.isSet()) {
writeToFile(grammarName + "RefResolver.jadd", p.generateRewriteToSuperTypeStub()); writeToFile(grammarName + "RefResolver.jadd", p.generateRewriteToSuperTypeStub());
} }
...@@ -131,6 +143,7 @@ public class Compiler { ...@@ -131,6 +143,7 @@ public class Compiler {
optionGrammarName = addOption(new StringOption("grammarName", "name of the generated grammar and aspect (without file extension)")); optionGrammarName = addOption(new StringOption("grammarName", "name of the generated grammar and aspect (without file extension)"));
optionResolverHelper = addOption(new FlagOption("resolverHelper", "create a subtype for each type containing a string that can be used to resolve the type later")); optionResolverHelper = addOption(new FlagOption("resolverHelper", "create a subtype for each type containing a string that can be used to resolve the type later"));
optionJastAddList = addOption(new StringOption("jastAddList", "set the name of the List type in JastAdd (has to match the option '--List' or its default List)")); optionJastAddList = addOption(new StringOption("jastAddList", "set the name of the List type in JastAdd (has to match the option '--List' or its default List)"));
optionSerializer = addOption(new EnumOption("serializer", "generate a (de-)serializer", Arrays.asList("jackson"), "jackson"));
} }
......
Root ::= A* B*;
A ::= <Name:String> <_impl_Di2:B> <_impl_Bi2:B> <_impl_Bi4:B> <_impl_Bi3:B> <_impl_Bi8:ArrayList<B>> <_impl_Bi9:ArrayList<B>> <_impl_Bi1:B> <_impl_Bi5:B> <_impl_Di3:ArrayList<B>> <_impl_Bi7:ArrayList<B>> <_impl_Bi6:B> <_impl_Di1:B>;
B ::= <Name:String> <_impl_Bi7:A> <_impl_Bi3:ArrayList<A>> <_impl_Bi5:A> <_impl_Bi1:A> <_impl_Bi6:ArrayList<A>> <_impl_Bi9:ArrayList<A>> <_impl_Bi2:A> <_impl_Bi4:A> <_impl_Bi8:A>;
import java.util.ArrayList;
import java.util.Collections;
aspect RelAstAPI {
public boolean ASTNode.violatesLowerBounds() {
return !getLowerBoundsViolations().isEmpty();
}
public java.util.List<Pair<ASTNode, String>> ASTNode.getLowerBoundsViolations() {
ArrayList<Pair<ASTNode, String>> list = new ArrayList<>();
computeLowerBoundsViolations(list);
return list;
}
public void ASTNode.computeLowerBoundsViolations(java.util.List<Pair<ASTNode, String>> list) {
for (int i = 0; i < getNumChildNoTransform(); i++) {
getChildNoTransform(i).computeLowerBoundsViolations(list);
}
}
public class Pair<T1, T2> {
public final T1 _1;
public final T2 _2;
public Pair(T1 _1, T2 _2) {
ASTNode.assertNotNull(_1);
ASTNode.assertNotNull(_2);
this._1 = _1;
this._2 = _2;
}
public boolean equals(Object other) {
if (other instanceof Pair) {
Pair<?,?> p = (Pair<?,?>) other;
return _1.equals(p._1) && _2.equals(p._2);
} else {
return false;
}
}
public int hashCode() {
return 31*_1.hashCode() + _2.hashCode();
}
}
public static void ASTNode.assertNotNull(Object obj) {
if (obj == null) {
throw new NullPointerException();
}
}
}
Root ::= A* B* C;
A:NamedElement;
B:NamedElement;
C:NamedElement ::= D1:D [D2:D] D3:D* <F1:float> <F2:Float>;
D:NamedElement;
abstract NamedElement ::= <Name>;
rel A.Di1 -> B;
rel A.Di2? -> B;
rel A.Di3* -> B;
rel A.Bi1 <-> B.Bi1;
rel A.Bi2 <-> B.Bi2?;
rel A.Bi3 <-> B.Bi3*;
rel A.Bi5? <-> B.Bi5?;
rel A.Bi6? <-> B.Bi6*;
rel A.Bi9* <-> B.Bi9*;
package org.jastadd.relast.tests;
import org.junit.jupiter.api.Test;
import serializer.ast.*;
import java.io.File;
@SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
class Serializer {
@Test
void testDi1() throws SerializationException, DeserializationException {
Root r = new Root();
A a1 = new A("a1");
A a2 = new A("a2");
A a3 = new A("a3");
B b1 = new B("b1");
B b2 = new B("b2");
B b3 = new B("b3");
C c = new C();
c.setName("c");
// non-terminals
c.setD1(new D("d1"));
c.setD2(new D("d2"));
c.addD3(new D("D3-1"));
c.addD3(new D("D3-2"));
c.addD3(new D("D3-3"));
// tokens
c.setF1(42f);
c.setF2(42.13f);
r.setC(c);
// non-containment relations
r.addA(a1);
r.addA(a2);
r.addA(a3);
r.addB(b1);
r.addB(b2);
r.addB(b3);
// Di1
a1.setDi1(b2);
a2.setDi1(b1);
a3.setDi1(b3);
// Di2
a1.setDi2(b2);
a3.setDi2(b1);
// Di3
a1.addDi3(b1);
a1.addDi3(b2);
a1.addDi3(b3);
a2.addDi3(b2);
// Bi1
a1.setBi1(b1);
a2.setBi1(b3);
a3.setBi1(b2);
// Bi2
a1.setBi2(b1);
a2.setBi2(b2);
a3.setBi2(b3);
// Bi3
a1.setBi3(b2);
a2.setBi3(b2);
a3.setBi3(b2);
// Bi5
a1.setBi5(b1);
a2.setBi5(b3);
// Bi6
a2.setBi6(b2);
a3.setBi6(b2);
// Bi9
a1.addBi9(b1);
a1.addBi9(b2);
a2.addBi9(b2);
File f = new File("test.json");
r.serialize(f);
Root copy = Root.deserialize(f);
File f2 = new File("copy.json");
copy.serialize(f2);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment