diff --git a/dumpAst2uml/.gitignore b/dumpAst2uml/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..87b4cdd3d7c6a41502ca98703abeeb69a1d536fb --- /dev/null +++ b/dumpAst2uml/.gitignore @@ -0,0 +1,5 @@ +build +src/gen-res/ +src/gen/ +out/ +*.class diff --git a/dumpAst2uml/build.gradle b/dumpAst2uml/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..7690a02f55330f0f0c199bbf94cdfcd285912e72 --- /dev/null +++ b/dumpAst2uml/build.gradle @@ -0,0 +1,188 @@ +apply plugin: 'jastadd' +apply plugin: 'application' +apply plugin: 'idea' + +sourceCompatibility = 1.8 + +mainClassName = 'org.jastadd.dumpAst2uml.compiler.Compiler' + +repositories { + jcenter() +} + +buildscript { + repositories.jcenter() + dependencies { + classpath 'org.jastadd:jastaddgradle:1.13.3' + } +} + +dependencies { + implementation project(':grammar2uml') // just to test SimpleMain + 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' + runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4' + api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' + + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0' + testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0' + testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.12.1' +} + +def versionFile = 'src/main/resources/dumpAst2umlVersion.properties' +def oldProps = new Properties() + +try { + file(versionFile).withInputStream { stream -> oldProps.load(stream) } + 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.") +} + +task newVersion() { + doFirst { + def props = new Properties() + props['version'] = value + props.store(file(versionFile).newWriter(), null) + } +} + +jar { + manifest { + attributes "Main-Class": mainClassName + } + + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + } + + archiveBaseName = 'dumpAst2uml' +} + +File genSrc = file("src/gen/java") +sourceSets.main.java.srcDir genSrc +idea.module.generatedSourceDirs += genSrc + +test { + useJUnitPlatform() + + 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", +// "./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 diff --git a/dumpAst2uml/src/main/java/org/jastadd/dumpAst2uml/compiler/SimpleMain.java b/dumpAst2uml/src/main/java/org/jastadd/dumpAst2uml/compiler/SimpleMain.java new file mode 100644 index 0000000000000000000000000000000000000000..1ccafbacb5e000da51f5fffb936ef63c6574116b --- /dev/null +++ b/dumpAst2uml/src/main/java/org/jastadd/dumpAst2uml/compiler/SimpleMain.java @@ -0,0 +1,153 @@ +package org.jastadd.dumpAst2uml.compiler; + +import beaver.Parser; +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.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.HashSet; +import java.util.Set; + +/** + * Testing Relast2Uml without parser. + * + * @author rschoene - Initial contribution + */ +public class SimpleMain { + + public static void main(String[] args) { +// testing(); + createManualAST(); + } + + private static void createManualAST() { + System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager"); + System.setProperty("mustache.debug", "true"); + Grammar2Uml model = new Grammar2Uml(); + Path path = Paths.get("grammar2uml", "src", "test", "resources", "Example.relast"); + System.out.println("path.toFile().getAbsolutePath() = " + path.toFile().getAbsolutePath()); + Program program = parseProgram(path); + model.setProgram(program); + + Folder folder1 = new Folder(); + folder1.setName("Folder1"); + folder1.addType(program.resolveTypeDecl("Wert")); + folder1.addType(program.resolveTypeDecl("Quelle")); + model.addFolder(folder1); + + model.treeResolveAll(); + traverseInitial(model.toMustache()); + } + + static final String MORE_INDENT = "| "; + + private static void traverseInitial(Object obj) { + traverse(obj, new HashSet<>(), ""); + } + + private static void traverse(Object obj, Set<Object> seen, String indent) { + if (seen.contains(obj)) { + return; + } + seen.add(obj); + System.out.println(indent + "|> " + obj.toString()); + System.out.println(indent + "| isAstNode(obj) = " + isAstNode(obj)); + printChildren(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)) { + 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(); + } + } + } + } + + 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); + Grammar2UmlParser parser = new Grammar2UmlParser(); + GrammarFile grammarFile = (GrammarFile) parser.parse(scanner); + Program program = new Program(); + program.addGrammarFile(grammarFile); + return program; + } catch (IOException | Parser.Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/settings.gradle b/settings.gradle index eb0d566fd20cf8b162d936b2b7ec901310be1418..3278510c64b72f36f4d307f08eea5f134a2d99d9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,3 +2,4 @@ rootProject.name = 'relast2uml' include 'relast.preprocessor' include 'grammar2uml' +include 'dumpAst2uml'