Skip to content
Snippets Groups Projects
Commit 06a0e684 authored by René Schöne's avatar René Schöne
Browse files

WIP dumpAst (and some cleanup of grammar2uml)

parent 77995fb3
No related branches found
No related tags found
No related merge requests found
......@@ -19,7 +19,8 @@ buildscript {
dependencies {
implementation project(':grammar2uml') // just to test SimpleMain
implementation project(':relast.preprocessor')
implementation fileTree(include: ['plantuml.jar'], dir: '../libs')
// implementation project(':relast.preprocessor')
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.9.6'
implementation group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '2.11.2'
......@@ -39,7 +40,7 @@ try {
version = oldProps['version']
} catch (e) {
// this happens, if either the properties file is not present, or cannot be read from
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.")
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.", e)
}
task newVersion() {
......@@ -73,116 +74,80 @@ test {
maxHeapSize = '1G'
}
//task relast(type: JavaExec) {
// group = 'Build'
// main = "-jar"
//
// doFirst {
// delete "src/gen/jastadd/*.ast"
// delete "src/gen/jastadd/Grammar2Uml.jadd"
// delete "src/gen/jastadd/Grammar2UmlRefResolver.jadd"
// delete "src/gen/jastadd/Grammar2UmlResolverStubs.jrag"
// mkdir "src/gen/jastadd/"
// }
//
// args = [
// "../libs/relast.jar",
// "../relast.preprocessor/src/main/jastadd/RelAst.relast",
// "./src/main/jastadd/Grammar2Uml.relast",
File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast')
task relast(type: JavaExec) {
group = 'Build'
main = "-jar"
doFirst {
delete "src/gen/jastadd/*.ast"
delete "src/gen/jastadd/DumpAst2.jadd"
delete "src/gen/jastadd/DumpAstlRefResolver.jadd"
delete "src/gen/jastadd/DumpAstlResolverStubs.jrag"
mkdir "src/gen/jastadd/"
}
args = [
"../libs/relast.jar",
dumpAstGrammar,
// "./src/main/jastadd/MustacheNodes.relast",
// "--listClass=java.util.ArrayList",
// "--jastAddList=JastAddList",
// "--useJastAddNames",
// "--file",
// "--resolverHelper",
// "--grammarName=./src/gen/jastadd/Grammar2Uml"
// ]
//
//// inputs.files file("../libs/relast.jar"),
//// file("../relast.preprocessor/src/main/jastadd/RelAST.relast"),
//// file("./src/main/jastadd/Grammar2Uml.relast")
//// file("./src/main/jastadd/MustacheNodes.relast")
//// outputs.files file("./src/gen/jastadd/Grammar2Uml.ast"),
//// file("./src/gen/jastadd/Grammar2Uml.jadd"),
//// file("./src/gen/jastadd/Grammar2UmlRefResolver.jadd"),
//// file('./src/gen/jastadd/Grammar2UmlResolverStubs.jrag')
//}
//
//jastadd {
// configureModuleBuild()
// modules {
// //noinspection GroovyAssignabilityCheck
// module("Grammar2Uml") {
//
// java {
// basedir ".."
// include "relast.preprocessor/main/**/*.java"
// include "relast.preprocessor/gen/**/*.java"
// include "dumpAst2uml/src/main/**/*.java"
// include "dumpAst2uml/src/gen/**/*.java"
// }
//
// jastadd {
// basedir ".."
// include "relast.preprocessor/src/main/jastadd/**/*.ast"
// include "relast.preprocessor/src/main/jastadd/**/*.jadd"
// include "relast.preprocessor/src/main/jastadd/**/*.jrag"
// include "dumpAst2uml/src/main/jastadd/**/*.ast"
// include "dumpAst2uml/src/main/jastadd/**/*.jadd"
// include "dumpAst2uml/src/main/jastadd/**/*.jrag"
// include "dumpAst2uml/src/gen/jastadd/**/*.ast"
// include "dumpAst2uml/src/gen/jastadd/**/*.jadd"
// include "dumpAst2uml/src/gen/jastadd/**/*.jrag"
// }
//
// scanner {
// basedir ".."
// include "dumpAst2uml/src/main/jastadd/scanner/Header.flex", [-5]
// include "relast.preprocessor/src/main/jastadd/scanner/Preamble.flex", [-4]
// include "relast.preprocessor/src/main/jastadd/scanner/Macros.flex", [-3]
// include "dumpAst2uml/src/main/jastadd/scanner/Macros.flex", [-3]
// include "relast.preprocessor/src/main/jastadd/scanner/RulesPreamble.flex", [-2]
// include "dumpAst2uml/src/main/jastadd/scanner/MappingContent.flex", [-1]
// include "dumpAst2uml/src/main/jastadd/scanner/Keywords.flex"
// include "relast.preprocessor/src/main/jastadd/scanner/Keywords.flex"
// include "relast.preprocessor/src/main/jastadd/scanner/Symbols.flex", [1]
// include "relast.preprocessor/src/main/jastadd/scanner/RulesPostamble.flex", [2]
// }
//
// parser {
// basedir ".."
// include "dumpAst2uml/src/main/jastadd/parser/Preamble.parser"
// include "relast.preprocessor/src/main/jastadd/parser/RelAst.parser"
// include "dumpAst2uml/src/main/jastadd/parser/Grammar2Uml.parser"
// }
// }
// }
//
// cleanGen.doFirst {
// delete "src/gen/java/org"
// delete "src/gen-res/BuildInfo.properties"
// }
//
// preprocessParser.doFirst {
//
// args += ["--no-beaver-symbol"]
//
// }
//
// module = "Grammar2Uml"
//
// astPackage = 'org.jastadd.dumpAst2uml.ast'
//
// parser.name = 'Grammar2UmlParser'
//
// genDir = 'src/gen/java'
//
// buildInfoDir = 'src/gen-res'
//
// scanner.genDir = "src/gen/java/org/jastadd/dumpAst2uml/scanner"
// parser.genDir = "src/gen/java/org/jastadd/dumpAst2uml/parser"
//
// jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
//}
//
//generateAst.dependsOn relast
"--listClass=java.util.ArrayList",
"--jastAddList=JastAddList",
"--useJastAddNames",
"--file",
"--resolverHelper",
"--grammarName=./src/gen/jastadd/DumpAst2"
]
inputs.files(file("../libs/relast.jar"),
dumpAstGrammar)
outputs.files(file("./src/gen/jastadd/DumpAst2.ast"),
file("./src/gen/jastadd/DumpAst.jadd"),
file("./src/gen/jastadd/DumpAstRefResolver.jadd"),
file('./src/gen/jastadd/DumpAstResolverStubs.jrag'))
}
jastadd {
configureModuleBuild()
modules {
//noinspection GroovyAssignabilityCheck
module("DumpAst2Uml") {
java {
basedir ".."
include "dumpAst2uml/src/main/**/*.java"
include "dumpAst2uml/src/gen/**/*.java"
}
jastadd {
basedir ".."
include "dumpAst2uml/src/main/jastadd/**/*.ast"
include "dumpAst2uml/src/main/jastadd/**/*.jadd"
include "dumpAst2uml/src/main/jastadd/**/*.jrag"
include "dumpAst2uml/src/gen/jastadd/**/*.ast"
include "dumpAst2uml/src/gen/jastadd/**/*.jadd"
include "dumpAst2uml/src/gen/jastadd/**/*.jrag"
}
}
}
cleanGen.doFirst {
delete "src/gen/java/org"
delete "src/gen-res/BuildInfo.properties"
}
preprocessParser.doFirst {
args += ["--no-beaver-symbol"]
}
module = "DumpAst2Uml"
astPackage = 'org.jastadd.dumpAst2uml.ast'
genDir = 'src/gen/java'
buildInfoDir = 'src/gen-res'
jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
}
generateAst.dependsOn relast
DumpAst ::= DumpNode* <PackageName> ;
DumpNode ::= <Name> <Object:Object> DumpChildNode* DumpToken* DumpRelation* ;
InnerDumpNode ;
rel InnerDumpNode.DumpNode -> DumpNode ;
abstract DumpChildNode ::= <Name> ;
DumpNormalChildNode : DumpChildNode ;
rel DumpNormalChildNode.DumpNode -> DumpNode ;
DumpListChildNode : DumpChildNode ::= InnerDumpNode* ;
//DumpOptChildNode : DumpChildNode ;
//rel DumpOptChildNode.DumpNode? -> DumpNode ;
abstract DumpToken ::= <Name> ;
DumpReferenceToken : DumpToken ;
rel DumpReferenceToken.Value -> DumpNode ;
DumpValueToken : DumpToken ::= <Value:Object> ;
abstract DumpRelation ::= <Name> <Bidirectional:boolean> ;
DumpNormalRelation : DumpRelation ;
rel DumpNormalRelation.DumpNode -> DumpNode ;
DumpListRelation : DumpRelation ::= InnerDumpNode* ;
//DumpOptRelation : DumpRelation ;
//rel DumpOptRelation.DumpNode? -> DumpNode ;
aspect Generation {
public class Dumper {
public static DumpBuilder read(Object obj) {
return new DumpBuilder(obj);
}
}
class DumpBuilder {
private Object target;
private String packageName;
private DumpAst result;
protected DumpBuilder(Object target) {
this.target = target;
}
public DumpBuilder ignoreTypes(String... regexes) {
// TODO
return this;
}
public DumpBuilder skinParam(String option) {
// TODO
return this;
}
protected DumpAst build() {
if (result == null) {
result = new DumpAst();
result.setPackageName(this.packageName == null ? this.target.getClass().getPackage().getName() : this.packageName);
try {
result.transform(new TransformationTransferInformation(), this.target);
} catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException("Could not transform :(", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not transform :(", e);
}
}
return result;
}
public DumpBuilder dumpAsSource(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
writer.write(content);
}
return this;
}
public DumpBuilder dumpAsPNG(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
net.sourceforge.plantuml.SourceStringReader reader = new net.sourceforge.plantuml.SourceStringReader(content);
reader.outputImage(java.nio.file.Files.newOutputStream(destination));
return this;
}
}
// --- transform --- (need to be a method, because it alters the AST while traversing the object structure)
// maybe return type is unncessary
protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj) throws java.lang.reflect.InvocationTargetException, IllegalAccessException {
if (obj == null) {
return null;
}
if (tti.transformed.containsKey(obj)) {
return tti.transformed.get(obj);
}
DumpNode node = new DumpNode();
node.setObject(obj);
tti.transformed.put(obj, node);
this.addDumpNode(node);
if (node.isAstNode()) {
// only caching node.analyseClass does not help, since we want to do this only once per class of a node
ClassAnalysisResult car = tti.classAnalysisResults.computeIfAbsent(node.getClass(), clz -> node.analyseClass());
// -- singleChild --
for (java.lang.reflect.Method method : car.singleChildMethods) {
Object target = method.invoke(obj);
if (target != null) {
DumpNormalChildNode normalChild = new DumpNormalChildNode();
normalChild.setName(car.names.get(method));
normalChild.setDumpNode(transform(tti, target));
node.addDumpChildNode(normalChild);
}
}
// -- listChild --
for (java.lang.reflect.Method method : car.listChildMethods) {
Iterable<?> targetList = (Iterable<?>) method.invoke(obj);
DumpListChildNode listChild = new DumpNormalChildNode();
listChild.setName(car.names.get(method));
for (Object target : targetList) {
if (target != null) {
listChild.addInnerDumpNode(new InnerDumpNode(transform(tti, target)));
}
}
node.addDumpChildNode(listChild);
}
// -- singleRelation --
for (java.lang.reflect.Method method : car.singleRelationMethods) {
Object target = method.invoke(obj);
if (target != null) {
DumpNormalRelation normalChild = new DumpNormalRelation();
normalChild.setName(car.names.get(method));
normalChild.setDumpNode(transform(tti, target));
node.addDumpRelation(normalChild);
}
}
// -- listChild --
for (java.lang.reflect.Method method : car.listChildMethods) {
Iterable<?> targetList = (Iterable<?>) method.invoke(obj);
DumpListRelation listChild = new DumpNormalRelation();
listChild.setName(car.names.get(method));
for (Object target : targetList) {
if (target != null) {
listChild.addInnerDumpNode(new InnerDumpNode(transform(tti, target)));
}
}
node.addDumpRelation(listChild);
}
// -- token --
for (java.lang.reflect.Method method : car.tokenMethods) {
Object target = method.invoke(obj);
if (target != null) {
DumpNode targetNode = transform(tti, target);
DumpToken token;
if (targetNode.isAstNode()) {
token = new DumpReferenceToken();
token.setValue(targetNode);
} else {
// maybe ignore empty string values here
token = new DumpValueToken();
token.setValue(target);
}
token.setName(car.names.get(method));
node.addDumpToken(token);
}
}
}
return node;
}
syn ClassAnalysisResult DumpNode.analyseClass() {
// TODO
return null;
}
syn boolean DumpNode.isAstNode() {
// TODO
return false;
}
class TransformationTransferInformation {
java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>();
java.util.Map<Class<?>, ClassAnalysisResult> classAnalysisResults = new java.util.HashMap<>();
}
class ClassAnalysisResult {
java.lang.reflect.Method[] singleChildMethods;
java.lang.reflect.Method[] listChildMethods;
java.lang.reflect.Method[] singleRelationMethods;
java.lang.reflect.Method[] listRelationMethods;
java.lang.reflect.Method[] tokenMethods;
java.util.Map<java.lang.reflect.Method, String> names;
}
syn String DumpAst.toPlantUml() {
StringBuilder sb = new StringBuilder();
com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() {
@Override
public com.github.mustachejava.Binding createBinding(String name, final com.github.mustachejava.TemplateContext tc, com.github.mustachejava.Code code) {
return new com.github.mustachejava.reflect.GuardedBinding(this, name, tc, code) {
@Override
protected synchronized com.github.mustachejava.util.Wrapper getWrapper(String name, java.util.List<Object> scopes) {
com.github.mustachejava.util.Wrapper wrapper = super.getWrapper(name, scopes);
if (wrapper instanceof com.github.mustachejava.reflect.MissingWrapper) {
throw new com.github.mustachejava.MustacheException(name + " not found in " + tc);
}
return wrapper;
}
};
}
};
com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory();
mf.setObjectHandler(roh);
com.github.mustachejava.Mustache m = mf.compile("dumpAst.mustache");
m.execute(new java.io.PrintWriter(new AppendableWriter(sb)), this);
return sb.toString();
}
public class AppendableWriter extends java.io.Writer {
private final StringBuilder sb;
public AppendableWriter(StringBuilder sb) {
this.sb = sb;
}
@Override
public void write(char[] chars, int off, int len) {
sb.append(chars, off, len);
}
@Override
public void write(String str) {
sb.append(str);
}
@Override
public void flush() {}
@Override
public void close() {}
}
}
\ No newline at end of file
aspect Navigation {
// --- isList ---
syn boolean DumpChildNode.isList() = false;
eq DumpListChildNode.isList() = true;
syn boolean DumpRelation.isList() = false;
eq DumpListRelation.isList() = true;
// --- isDumpValueToken ---
syn boolean DumpToken.isDumpValueToken() = false;
eq DumpValueToken.isDumpValueToken() = true;
}
\ No newline at end of file
aspect Printing {
// --- outerNodeName ---
inh String InnerDumpNode.outerNodeName();
inh String DumpChildNode.outerNodeName();
inh String DumpRelation.outerNodeName();
inh String DumpReferenceToken.outerNodeName();
eq DumpNode.getChild().outerNodeName() = name();
// --- innerNodeName ---
syn String InnerDumpNode.innerNodeName() = getDumpNode().name();
syn String DumpNormalChildNode.innerNodeName() = getDumpNode().name();
syn String DumpNormalRelation.innerNodeName() = getDumpNode().name();
syn String DumpReferenceToken.innerNodeName() = getValue().name();
// --- name ---
syn String DumpNode.name() = getName(); // might change in the future
// --- label ---
syn String DumpChildNode.label() = getName();
syn String DumpRelation.label() = getName();
syn String DumpToken.label() = getName();
}
package org.jastadd.dumpAst2uml.compiler;
import beaver.Parser;
import org.jastadd.dumpAst2uml.ast.*;
import org.jastadd.grammar2uml.ast.*;
import org.jastadd.grammar2uml.parser.Grammar2UmlParser;
import org.jastadd.grammar2uml.scanner.Grammar2UmlScanner;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import static org.jastadd.dumpAst2uml.compiler.SimpleMain.Kind.*;
/**
* Testing Relast2Uml without parser.
*
......@@ -24,11 +28,72 @@ import java.util.Set;
public class SimpleMain {
public static void main(String[] args) {
// testing();
// printing();
createManualAST();
}
private static void createManualAST() {
DumpAst dumpAst = new DumpAst();
dumpAst.setPackageName("foo");
DumpNode a = new DumpNode();
a.setName("a");
dumpAst.addDumpNode(a);
DumpNode b = new DumpNode();
b.setName("b");
dumpAst.addDumpNode(b);
DumpNode c = new DumpNode();
c.setName("c");
dumpAst.addDumpNode(c);
DumpNode d = new DumpNode();
d.setName("d");
dumpAst.addDumpNode(d);
DumpNode e = new DumpNode();
e.setName("e");
dumpAst.addDumpNode(e);
DumpNode f = new DumpNode();
f.setName("f");
dumpAst.addDumpNode(f);
DumpNode g = new DumpNode();
g.setName("g");
dumpAst.addDumpNode(g);
DumpNode h = new DumpNode();
h.setName("h");
dumpAst.addDumpNode(h);
DumpListChildNode listNode = new DumpListChildNode();
listNode.setName("list");
listNode.addInnerDumpNode(new InnerDumpNode(b));
listNode.addInnerDumpNode(new InnerDumpNode(c));
a.addDumpChildNode(listNode);
a.addDumpChildNode(new DumpNormalChildNode("opt", d));
a.addDumpChildNode(new DumpNormalChildNode("normal", e));
DumpListRelation listRelation = new DumpListRelation();
listRelation.setName("listRel");
listRelation.addInnerDumpNode(new InnerDumpNode(f));
listRelation.addInnerDumpNode(new InnerDumpNode(g));
b.addDumpRelation(listRelation);
c.addDumpRelation(new DumpNormalRelation("relOpt", false, g));
c.addDumpRelation(new DumpNormalRelation("biRelOpt", true, h));
d.addDumpRelation(new DumpNormalRelation("relNormal", false, c));
e.addDumpToken(new DumpReferenceToken("ref", h));
h.addDumpToken(new DumpValueToken("intValue", 4));
DumpListRelation biListRelation = new DumpListRelation();
biListRelation.setName("biRelList");
biListRelation.setBidirectional(true);
biListRelation.addInnerDumpNode(new InnerDumpNode(f));
biListRelation.addInnerDumpNode(new InnerDumpNode(g));
h.addDumpRelation(biListRelation);
String content = dumpAst.toPlantUml();
System.out.println(content);
}
private static void printing() {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
System.setProperty("mustache.debug", "true");
Grammar2Uml model = new Grammar2Uml();
......@@ -48,6 +113,7 @@ public class SimpleMain {
}
static final String MORE_INDENT = "| ";
static final String AST_NODE_ANNOTATION = "org.jastadd.grammar2uml.ast" + ".ASTNodeAnnotation";
private static void traverseInitial(Object obj) {
traverse(obj, new HashSet<>(), "");
......@@ -61,75 +127,93 @@ public class SimpleMain {
System.out.println(indent + "|> " + obj.toString());
System.out.println(indent + "| isAstNode(obj) = " + isAstNode(obj));
printChildren(obj, seen, indent);
printTokens(obj, seen, indent);
// printTokens(obj, seen, indent);
}
private static boolean isAstNode(Object obj) {
Class<?> clazz = obj.getClass();
for (Constructor<?> constructor : clazz.getConstructors()) {
if (constructor.isAnnotationPresent(ASTNodeAnnotation.Constructor.class)) {
if (hasConstructionAnnotationClass(constructor)) {
return true;
}
}
return false;
}
static void printChildren(Object obj, Set<Object> seen, String indent) {
Class<?> clazz = obj.getClass();
for (Method method : clazz.getMethods()) {
final String name;
final String kind;
if (method.isAnnotationPresent(ASTNodeAnnotation.Child.class)) {
name = method.getAnnotation(ASTNodeAnnotation.Child.class).name();
kind = "";
} else if (method.isAnnotationPresent(ASTNodeAnnotation.ListChild.class)) {
name = method.getAnnotation(ASTNodeAnnotation.ListChild.class).name();
kind = "list-";
} else if (method.isAnnotationPresent(ASTNodeAnnotation.OptChild.class)) {
name = method.getAnnotation(ASTNodeAnnotation.OptChild.class).name();
kind = "opt-";
} else {
name = null;
kind = null;
}
if (kind != null) {
try {
Object child = method.invoke(obj);
System.out.println(indent + "| " + kind + "child (" + name + ") = " + child);
traverse(child, seen, indent + MORE_INDENT);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
private static boolean hasConstructionAnnotationClass(Constructor<?> constructor) {
// ASTNodeAnnotation.Constructor.class;
for (Annotation annotation : constructor.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName();
if (canonicalName.startsWith(AST_NODE_ANNOTATION) && annotation.annotationType().getSimpleName().equals("Constructor")) {
return true;
}
}
return false;
}
enum Kind {child, list, opt, tokenOrRelation, token, relation, other}
static class NameAndKind {
String name;
Kind kind;
static NameAndKind of(String name, Kind kind) {
NameAndKind result = new NameAndKind();
result.name = name;
result.kind = kind;
return result;
}
}
private static NameAndKind analyzeMethod(Method method) {
for (Annotation annotation : method.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName();
if (canonicalName.startsWith(AST_NODE_ANNOTATION)) {
String simpleName = annotation.annotationType().getSimpleName();
switch (simpleName) {
case "Child": return NameAndKind.of(invokeName(annotation), Kind.child);
case "ListChild": return NameAndKind.of(invokeName(annotation), Kind.list);
case "OptChild": return NameAndKind.of(invokeName(annotation), Kind.opt);
case "Token": return NameAndKind.of(invokeName(annotation), tokenOrRelation);
}
}
}
return NameAndKind.of(null, Kind.other);
}
static void printTokens(Object obj, Set<Object> seen, String indent) {
private static String invokeName(Annotation annotation) {
try {
return (String) annotation.annotationType().getMethod("name").invoke(annotation);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
return "<error>";
}
}
static void printChildren(Object obj, Set<Object> seen, String indent) {
Class<?> clazz = obj.getClass();
for (Method method : clazz.getMethods()) {
if (method.isAnnotationPresent(ASTNodeAnnotation.Token.class)) {
Method methodToInvoke = null;
String name = method.getAnnotation(ASTNodeAnnotation.Token.class).name();
NameAndKind nameAndKind = analyzeMethod(method);
String name = nameAndKind.name;
Kind kind = nameAndKind.kind;
Method methodToInvoke = method;
if (kind == tokenOrRelation) {
// heuristic for relations
if (name.startsWith("_impl_")) {
try {
methodToInvoke = clazz.getMethod("get" + name.substring(6));
name = name.substring(6);
kind = relation;
} catch (NoSuchMethodException e) {
// this is probably not a relation
}
}
final String kind;
if (methodToInvoke == null) {
methodToInvoke = method;
kind = "token";
} else {
kind = "relation";
if (kind == tokenOrRelation) {
kind = token;
}
}
if (kind != other) {
try {
Object value = methodToInvoke.invoke(obj);
System.out.println(indent + "| " + kind + " (" + name + ") = " + value);
traverse(value, seen, indent + MORE_INDENT);
Object child = methodToInvoke.invoke(obj);
System.out.println(indent + "| " + kind + " child (" + name + ") = " + child);
traverse(child, seen, indent + MORE_INDENT);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
......@@ -137,6 +221,39 @@ public class SimpleMain {
}
}
// static void printTokens(Object obj, Set<Object> seen, String indent) {
// Class<?> clazz = obj.getClass();
// for (Method method : clazz.getMethods()) {
// if (method.isAnnotationPresent(ASTNodeAnnotation.Token.class)) {
// Method methodToInvoke = null;
// String name = method.getAnnotation(ASTNodeAnnotation.Token.class).name();
// // heuristic for relations
// if (name.startsWith("_impl_")) {
// try {
// methodToInvoke = clazz.getMethod("get" + name.substring(6));
// name = name.substring(6);
// } catch (NoSuchMethodException e) {
// // this is probably not a relation
// }
// }
// final String kind;
// if (methodToInvoke == null) {
// methodToInvoke = method;
// kind = "token";
// } else {
// kind = "relation";
// }
// try {
// Object value = methodToInvoke.invoke(obj);
// System.out.println(indent + "| " + kind + " (" + name + ") = " + value);
// traverse(value, seen, indent + MORE_INDENT);
// } catch (IllegalAccessException | InvocationTargetException e) {
// e.printStackTrace();
// }
// }
// }
// }
private static Program parseProgram(Path path) {
try (BufferedReader reader = Files.newBufferedReader(path)) {
Grammar2UmlScanner scanner = new Grammar2UmlScanner(reader);
......
@startuml
{{#DumpNodes}}
object {{name}} {
{{! tokens }}
{{#DumpTokens}}
{{#isDumpValueToken}}
{{label}} = {{Value}}
{{/isDumpValueToken}}
{{/DumpTokens}}
}
{{#DumpTokens}}
{{^isDumpValueToken}}
{{outerNodeName}} ..> {{innerNodeName}} : {{label}}
{{/isDumpValueToken}}
{{/DumpTokens}}
{{! child nodes }}
{{#DumpChildNodes}}
{{#isList}}
{{#InnerDumpNodes}}
{{outerNodeName}} *-- {{innerNodeName}} : {{label}}
{{/InnerDumpNodes}}
{{/isList}}
{{^isList}}
{{outerNodeName}} *-- {{innerNodeName}} : {{label}}
{{/isList}}
{{/DumpChildNodes}}
{{! relations }}
{{#DumpRelations}}
{{#isList}}
{{#InnerDumpNodes}}
{{outerNodeName}} {{#Bidirectional}}<{{/Bidirectional}}--> {{innerNodeName}} : {{label}}
{{/InnerDumpNodes}}
{{/isList}}
{{^isList}}
{{outerNodeName}} {{#Bidirectional}}<{{/Bidirectional}}--> {{innerNodeName}} : {{label}}
{{/isList}}
{{/DumpRelations}}
{{/DumpNodes}}
@enduml
#Sat Sep 05 18:50:58 CEST 2020
version=0.2
......@@ -38,7 +38,7 @@ try {
version = oldProps['version']
} catch (e) {
// this happens, if either the properties file is not present, or cannot be read from
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.")
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.", e)
}
task newVersion() {
......@@ -72,6 +72,10 @@ test {
maxHeapSize = '1G'
}
File preprocessorGrammar = file('../relast.preprocessor/src/main/jastadd/RelAst.relast')
File grammar2umlGrammar = file('./src/main/jastadd/Grammar2Uml.relast')
File intermediateGrammar = file('./src/main/jastadd/MustacheNodes.relast')
task relast(type: JavaExec) {
group = 'Build'
main = "-jar"
......@@ -86,9 +90,9 @@ task relast(type: JavaExec) {
args = [
"../libs/relast.jar",
"../relast.preprocessor/src/main/jastadd/RelAst.relast",
"./src/main/jastadd/Grammar2Uml.relast",
"./src/main/jastadd/MustacheNodes.relast",
preprocessorGrammar,
grammar2umlGrammar,
intermediateGrammar,
"--listClass=java.util.ArrayList",
"--jastAddList=JastAddList",
"--useJastAddNames",
......@@ -97,14 +101,14 @@ task relast(type: JavaExec) {
"--grammarName=./src/gen/jastadd/Grammar2Uml"
]
// inputs.files file("../libs/relast.jar"),
// file("../relast.preprocessor/src/main/jastadd/RelAST.relast"),
// file("./src/main/jastadd/Grammar2Uml.relast")
// file("./src/main/jastadd/MustacheNodes.relast")
// outputs.files file("./src/gen/jastadd/Grammar2Uml.ast"),
// file("./src/gen/jastadd/Grammar2Uml.jadd"),
// file("./src/gen/jastadd/Grammar2UmlRefResolver.jadd"),
// file('./src/gen/jastadd/Grammar2UmlResolverStubs.jrag')
inputs.files(file("../libs/relast.jar"),
preprocessorGrammar,
grammar2umlGrammar,
intermediateGrammar)
outputs.files(file("./src/gen/jastadd/Grammar2Uml.ast"),
file("./src/gen/jastadd/Grammar2Uml.jadd"),
file("./src/gen/jastadd/Grammar2UmlRefResolver.jadd"),
file('./src/gen/jastadd/Grammar2UmlResolverStubs.jrag'))
}
jastadd {
......
......@@ -16,5 +16,6 @@ aspect Navigation {
// --- containedFileName ---
eq Grammar2Uml.getChild().containedFileName() = getFileName();
eq Program.getChild().containedFileName() = null;
eq Grammar.getChild().containedFileName() = null;
eq MGrammar2Uml.getChild().containedFileName() = null;
}
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment