diff --git a/relast2uml.base/build.gradle b/relast2uml.base/build.gradle index 86db1feb51a3cf8fb7e4fddddba40c694ac8ea9f..ddeda5fc43e9cb33b34100a7ae6f333bdcc8940f 100644 --- a/relast2uml.base/build.gradle +++ b/relast2uml.base/build.gradle @@ -17,6 +17,8 @@ buildscript { } dependencies { + 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' diff --git a/relast2uml.base/src/main/jastadd/Navigation.jrag b/relast2uml.base/src/main/jastadd/Navigation.jrag index 09c9ae19da6a995a0c24e27afff0d0739604b1c7..052410f4447c25aca0770fe97c1ba4d7cc1e9efa 100644 --- a/relast2uml.base/src/main/jastadd/Navigation.jrag +++ b/relast2uml.base/src/main/jastadd/Navigation.jrag @@ -9,68 +9,11 @@ aspect Navigation { eq Relast2Uml.getChild().relast2uml() = this; eq MRelast2Uml.getChild().relast2uml() = getRelast2Uml(); - // --- containedFile (first equation should be in preprocessor) --- - eq Program.getChild().containedFile() = null; + // --- containedFile --- eq Relast2Uml.getChild().containedFile() = null; - // --- isTypeDecl (should be in preprocessor) --- - syn boolean Declaration.isTypeDecl() = false; - eq TypeDecl.isTypeDecl() = true; - - // --- asTypeDecl (should be in preprocessor) --- - syn TypeDecl Declaration.asTypeDecl() = null; - eq TypeDecl.asTypeDecl() = this; - - // --- isTypeComponent (should be in preprocessor) --- - syn boolean Component.isTypeComponent() = false; - eq TypeComponent.isTypeComponent() = true; - - // --- asTypeComponent (should be in preprocessor) --- - syn TypeComponent Component.asTypeComponent() = null; - eq TypeComponent.asTypeComponent() = this; - - // --- isNormalComponent (should be in preprocessor) --- - syn boolean Component.isNormalComponent() = false; - eq NormalComponent.isNormalComponent() = true; - - // --- asNormalComponent (should be in preprocessor) --- - syn NormalComponent Component.asNormalComponent() = null; - eq NormalComponent.asNormalComponent() = this; - - // --- isListComponent (should be in preprocessor) --- - syn boolean Component.isListComponent() = false; - eq ListComponent.isListComponent() = true; - - // --- asListComponent (should be in preprocessor) --- - syn ListComponent Component.asListComponent() = null; - eq ListComponent.asListComponent() = this; - - // --- isDirectedRelation (should be in preprocessor) --- - syn boolean Relation.isDirectedRelation() = false; - eq DirectedRelation.isDirectedRelation() = true; - - // --- asDirectedRelation (should be in preprocessor) --- - syn DirectedRelation Relation.asDirectedRelation() = null; - eq DirectedRelation.asDirectedRelation() = this; - - // --- asBidirectionalRelation (should be in preprocessor) --- - syn BidirectionalRelation Relation.asBidirectionalRelation() = null; - eq BidirectionalRelation.asBidirectionalRelation() = this; - - // --- isListRole (should be in preprocessor) --- - syn boolean Role.isListRole() = false; - eq ListRole.isListRole() = true; - - // --- containedFileName (should replace containedFile in preprocessor) --- - inh String ASTNode.containedFileName(); - eq GrammarFile.getChild().containedFileName() = getFileName(); + // --- containedFileName --- eq Relast2Uml.getChild().containedFileName() = getFileName(); eq Program.getChild().containedFileName() = null; eq MRelast2Uml.getChild().containedFileName() = null; - - // --- allTokenComponents --- - coll java.util.Set<TokenComponent> Program.allTokenComponents() [new java.util.HashSet<>()] root Program; - TokenComponent contributes this - to Program.allTokenComponents() - for program(); } diff --git a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/Compiler.java b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/Compiler.java index 1e76de88a4e7d1cce18e7e33ca191abb7bfec17f..a90e48ff9f722303c95cbba82d6272f202794408 100644 --- a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/Compiler.java +++ b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/Compiler.java @@ -1,11 +1,14 @@ package org.jastadd.relast2uml.compiler; import beaver.Parser; -import org.jastadd.relast2uml.ast.*; -import org.jastadd.relast2uml.compiler.options.CommandLine; -import org.jastadd.relast2uml.compiler.options.FlagOption; -import org.jastadd.relast2uml.compiler.options.Option; -import org.jastadd.relast2uml.compiler.options.StringOption; +import org.jastadd.option.BooleanOption; +import org.jastadd.option.ValueOption; +import org.jastadd.relast.compiler.AbstractCompiler; +import org.jastadd.relast.compiler.CompilerException; +import org.jastadd.relast2uml.ast.ErrorMessage; +import org.jastadd.relast2uml.ast.GrammarFile; +import org.jastadd.relast2uml.ast.Program; +import org.jastadd.relast2uml.ast.Relast2Uml; import org.jastadd.relast2uml.parser.Relast2UmlParser; import org.jastadd.relast2uml.scanner.Relast2UmlScanner; @@ -13,93 +16,22 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.MissingResourceException; import java.util.ResourceBundle; -public class Compiler { +public class Compiler extends AbstractCompiler { - private StringOption optionOutputFile; - private StringOption optionInputRelast2Uml; - private FlagOption optionDefaultFolders; - private FlagOption optionHelp; - private FlagOption optionVersion; - private FlagOption optionVerbose; - - private ArrayList<Option<?>> options; - private CommandLine commandLine; + private ValueOption optionOutputFile; + private ValueOption optionInputRelast2Uml; + private BooleanOption optionDefaultFolders; + private BooleanOption optionHelp; + private BooleanOption optionVersion; + private BooleanOption optionVerbose; public Compiler() { - options = new ArrayList<>(); - addOptions(); - } - - public void run(String[] args) throws CommandLine.CommandLineException, CompilerException { - System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager"); - System.setProperty("mustache.debug", "true"); - options = new ArrayList<>(); - addOptions(); - commandLine = new CommandLine(options); - commandLine.parse(args); - - if (optionHelp.isSet()) { - printUsage(); - return; - } - - if (optionVersion.isSet()) { - System.out.println(readVersion()); - return; - } - - if (optionVerbose.isSet()) { - try { - run(); - } catch (CompilerException e) { - e.printStackTrace(); - throw e; - } - } else { - run(); - } - } - - private void run() throws CompilerException { - printMessage("Running relast2uml " + readVersion()); - - String output; - if (optionOutputFile.isSet()) { - output = optionOutputFile.getValue(); - } else { - output = "uml.md"; - System.out.println("No output output file is set. Assuming '" + output + "'."); - } - try { - Files.createDirectories(Paths.get(output).toAbsolutePath().getParent()); - } catch (IOException e) { - throw new CompilerException("Error creating output dir " + Paths.get(output).getParent().toAbsolutePath(), e); - } - - if (anyRequiredOptionIsUnset()) { - throw new CompilerException("Aborting due to missing values for required options."); - } - if (commandLine.getArguments().isEmpty()) { - throw new CompilerException("No input grammars specified!"); - } - - Relast2Uml relast2uml = parseProgram(); - - if (!relast2uml.errors().isEmpty()) { - System.err.println("Errors:"); - for (ErrorMessage e : relast2uml.errors()) { - System.err.println(e); - } - System.exit(1); - } - - printMessage("Writing output file " + output); - writeToFile(output, relast2uml.generateAspect()); + super("relast2uml", false); } /** @@ -122,23 +54,12 @@ public class Compiler { } } - private boolean anyRequiredOptionIsUnset() { - boolean foundError = false; - for (Option<?> option : options) { - if (option.hasArgument() == Option.HasArgument.YES && !option.isSet()) { - System.err.println("Option '" + option.getName() + - "' (" + option.getDescription() + ") is required but unset!"); - foundError = true; - } - } - return foundError; - } - - public static void main(String[] args) { + System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager"); + System.setProperty("mustache.debug", "true"); try { new Compiler().run(args); - } catch (CommandLine.CommandLineException | CompilerException e) { + } catch (CompilerException e) { System.err.println(e.getMessage()); System.exit(-1); } @@ -158,38 +79,42 @@ public class Compiler { } } - private void addOptions() { - optionOutputFile = addOption(new StringOption( - "output", "target file to be generated.", "uml.md").makeOptional()); - optionInputRelast2Uml = addOption(new StringOption( - "inputRelast2Uml", "relast2uml definition file.").makeOptional()); - optionDefaultFolders = addOption(new FlagOption( - "defaultFolders", "Creates a default folder per grammar file.")); - optionHelp = addOption(new FlagOption( - "help", "Print usage and exit.")); - optionVersion = addOption(new FlagOption( - "help", "Print version and exit.")); - optionVerbose = addOption(new FlagOption( - "verbose", "Print more messages while compiling.")); - } - - private <OptionType extends Option<?>> OptionType addOption(OptionType option) { - options.add(option); - return option; + protected void initOptions() { + optionOutputFile = addOption( + new ValueOption("output", "target file to be generated.") + .defaultValue("uml.md") + .acceptAnyValue() + .needsValue(false)); + optionInputRelast2Uml = addOption( + new ValueOption("inputRelast2Uml", "relast2uml definition file.") + .needsValue(true)); + optionDefaultFolders = addOption( + new BooleanOption("defaultFolders", + "Creates a default folder per grammar file.") + .defaultValue(false)); + optionHelp = addOption( + new BooleanOption("help", "Print usage and exit.") + .defaultValue(false)); + optionVersion = addOption( + new BooleanOption("help", "Print version and exit.") + .defaultValue(false)); + optionVerbose = addOption( + new BooleanOption("verbose", "Print more messages while compiling.") + .defaultValue(false)); } private Relast2Uml parseProgram() throws CompilerException { Program program = new Program(); Relast2Uml relast2Uml; - for (String inputGrammarFileName : commandLine.getArguments()) { + for (String inputGrammarFileName : getConfiguration().getFiles()) { printMessage("Parsing " + inputGrammarFileName); GrammarFile inputGrammar; try (BufferedReader reader = Files.newBufferedReader(Paths.get(inputGrammarFileName))) { Relast2UmlScanner scanner = new Relast2UmlScanner(reader); Relast2UmlParser parser = new Relast2UmlParser(); inputGrammar = (GrammarFile) parser.parse(scanner); - if (optionVerbose.isSet()) { + if (optionVerbose.value()) { inputGrammar.dumpTree(System.out); } program.addGrammarFile(inputGrammar); @@ -199,8 +124,8 @@ public class Compiler { } } - if (optionInputRelast2Uml.isSet()) { - String inputRelast2UmlFileName = optionInputRelast2Uml.getValue(); + if (optionInputRelast2Uml.isMatched()) { + String inputRelast2UmlFileName = optionInputRelast2Uml.value(); try (BufferedReader reader = Files.newBufferedReader(Paths.get(inputRelast2UmlFileName))) { Relast2UmlScanner scanner = new Relast2UmlScanner(reader); Relast2UmlParser parser = new Relast2UmlParser(); @@ -216,7 +141,7 @@ public class Compiler { } relast2Uml.setProgram(program); relast2Uml.treeResolveAll(); - if (optionDefaultFolders.isSet()) { + if (optionDefaultFolders.value()) { for (GrammarFile grammarFile : program.getGrammarFileList()) { relast2Uml.addFolder(grammarFile.defaultFolder()); } @@ -224,18 +149,49 @@ public class Compiler { return relast2Uml; } - protected void printUsage() { - System.out.println("Usage: java -jar relast2uml.jar [--option1] [--option2=value] ... <filename1> <filename2> ... "); - System.out.println("Options:"); - System.out.print(commandLine.printOptionHelp()); - } + @Override + protected int compile() throws CompilerException { + if (optionVersion.value()) { + System.out.println(readVersion()); + return 0; + } + if (optionHelp.value()) { + getConfiguration().printHelp(System.out); + return 0; + } - public static class CompilerException extends Exception { - CompilerException(String message) { - super(message); + printMessage("Running relast2uml " + readVersion()); + + String output; + if (optionOutputFile.isMatched()) { + output = optionOutputFile.value(); + } else { + output = "uml.md"; + System.out.println("No output output file is set. Assuming '" + output + "'."); } - CompilerException(String message, Throwable cause) { - super(message, cause); + Path parent = Paths.get(optionOutputFile.value()).toAbsolutePath().getParent(); + try { + Files.createDirectories(parent); + } catch (IOException e) { + throw new CompilerException("Error creating output dir " + parent, e); + } + + if (getConfiguration().getFiles().isEmpty()) { + throw new CompilerException("No input grammars specified!"); } + + Relast2Uml relast2uml = parseProgram(); + + if (!relast2uml.errors().isEmpty()) { + System.err.println("Errors:"); + for (ErrorMessage e : relast2uml.errors()) { + System.err.println(e); + } + System.exit(1); + } + + printMessage("Writing output file " + output); + writeToFile(output, relast2uml.generateAspect()); + return 0; } } diff --git a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/CommandLine.java b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/CommandLine.java deleted file mode 100644 index eddfb81facc83470c2dcfa00a719389a8b89c833..0000000000000000000000000000000000000000 --- a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/CommandLine.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.jastadd.relast2uml.compiler.options; - -import java.util.*; - -public class CommandLine { - private final Collection<Option<?>> options; - private final Map<String, Option<?>> mapping; - private final List<String> arguments; - - public CommandLine(Collection<Option<?>> options) { - this.options = options; - this.mapping = new HashMap<>(); - for (Option<?> option : options) { - mapping.put(option.getName(), option); - } - this.arguments = new ArrayList<>(); - } - - public void parse(String[] args) throws CommandLineException { - int i = 0; - while (i < args.length) { - if (args[i].startsWith(Option.PREFIX)) { - int argumentIndex = args[i].indexOf("="); - String name; - String argument = null; - if (argumentIndex > 0) { - name = args[i].substring(2, argumentIndex); - argument = args[i].substring(argumentIndex + 1); - } else { - name = args[i].substring(2); - } - Option<?> option = mapping.get(name); - if (option == null) { - throw new CommandLineException("Option " + Option.PREFIX + name + " not found"); - } - match(option, argument); - } else { - arguments.add(args[i]); - } - i++; - } - } - - public void match(Option<?> option, String argument) throws CommandLineException { - try { - switch (option.hasArgument()) { - case NO: - if (argument == null) { - option.match(null); - } else { - throw new CommandLineException("Option " + option + " is not allowed to have an argument"); - } - break; - case OPTIONAL: - option.match(argument); - break; - case YES: - if (argument != null) { - option.match(argument); - } else { - throw new CommandLineException("Option " + option + " requires an argument"); - } - break; - } - } catch (Option.IllegalMatchException e) { - throw new CommandLineException("Invalid value for option " + option + ": " + e.getMessage()); - } - } - - public List<String> getArguments() { - return arguments; - } - - public String printOptionHelp() { - StringBuilder sb = new StringBuilder(); - int longestOption = 0; - for (Option<?> option : options) { - if (longestOption < option.getName().length()) { - longestOption = option.getName().length(); - } - } - for (Option<?> option : new TreeSet<>(options)) { - String s = String.format(" %s%-" + (longestOption + 6) + "s %s%n", - Option.PREFIX, option.getName(), option.getDescription()); - sb.append(s); - } - return sb.toString(); - } - - public static class CommandLineException extends Exception { - private static final long serialVersionUID = 1L; - - public CommandLineException(String message) { - super(message); - } - } -} diff --git a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/EnumOption.java b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/EnumOption.java deleted file mode 100644 index 57974d26ee6c9df1cd8a6be9fd8c2596fdcdfe21..0000000000000000000000000000000000000000 --- a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/EnumOption.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.jastadd.relast2uml.compiler.options; - -import java.util.Collection; -import java.util.TreeSet; - -public class EnumOption extends Option<String> { - private final TreeSet<String> allowedValues; - private final String defaultValue; - private String value; - private boolean isSet; - - public EnumOption(String name, String description, Collection<String> allowedValues, String defaultValue) { - super(name, description); - this.allowedValues = new TreeSet<>(allowedValues); - this.defaultValue = defaultValue; - this.value = defaultValue; - this.isSet = false; - } - - public boolean addAllowedValue(String allowedValue) { - return allowedValues.add(allowedValue); - } - - @Override - public String getValue() { - return value; - } - - @Override - public Option.HasArgument hasArgument() { - return Option.HasArgument.OPTIONAL; - } - - @Override - public void match(String argument) throws IllegalMatchException { - if (argument == null) { - isSet = true; - value = defaultValue; - } else if (allowedValues.contains(argument)) { - isSet = true; - value = argument; - } else { - throw new IllegalMatchException(argument - + " is not allowed, allowed values are " + allowedValues); - } - } - - @Override - public boolean isSet() { - return isSet; - } - - @Override - public String getDescription() { - String allowedValuesStr = allowedValues.toString(); - allowedValuesStr = allowedValuesStr.substring(1); - allowedValuesStr = allowedValuesStr.substring(0, allowedValuesStr.length() - 1); - return super.getDescription() + " (allowed values: " + allowedValuesStr + ")"; - } -} diff --git a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/FlagOption.java b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/FlagOption.java deleted file mode 100644 index 3824360a6390e00e2af1f6727c60329d11f2b8a2..0000000000000000000000000000000000000000 --- a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/FlagOption.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.jastadd.relast2uml.compiler.options; - -public class FlagOption extends Option<Boolean> { - private boolean value; - - public FlagOption(String name, String description) { - super(name, description); - value = false; - } - - @Override - public Boolean getValue() { - return value; - } - - @Override - public Option.HasArgument hasArgument() { - return Option.HasArgument.NO; - } - - @Override - public void match(String string) throws IllegalMatchException { - value = true; - } - - @Override - public boolean isSet() { - return getValue(); - } -} diff --git a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/Option.java b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/Option.java deleted file mode 100644 index 5a62857f61ab4fc7762323cad8ba0855f5d7014b..0000000000000000000000000000000000000000 --- a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/Option.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.jastadd.relast2uml.compiler.options; - -abstract public class Option<ValueType> implements Comparable<Option<?>> { - public final static String PREFIX = "--"; - private final String name; - private final String description; - - public Option(String name, String description) { - this.name = name; - this.description = description; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - @Override - public int compareTo(Option<?> o) { - return name.compareTo(o.name); - } - - @Override - public boolean equals(Object other) { - if (other instanceof Option) { - return compareTo((Option<?>) other) == 0; - } - return false; - } - - @Override - public String toString() { - return PREFIX + name; - } - - abstract public boolean isSet(); - - abstract public ValueType getValue(); - - abstract public HasArgument hasArgument(); - - abstract public void match(String input) throws IllegalMatchException; - - public enum HasArgument { - NO, - OPTIONAL, - YES - } - - public static class IllegalMatchException extends Exception { - private static final long serialVersionUID = 1L; - - public IllegalMatchException(String message) { - super(message); - } - } -} diff --git a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/StringOption.java b/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/StringOption.java deleted file mode 100644 index baa92bc9e44fafa5a036e63c2062696a32d76a7c..0000000000000000000000000000000000000000 --- a/relast2uml.base/src/main/java/org/jastadd/relast2uml/compiler/options/StringOption.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.jastadd.relast2uml.compiler.options; - -public class StringOption extends Option<String> { - private HasArgument hasArgument; - private String value; - private boolean isSet; - - public StringOption(String name, String description) { - this(name, description, ""); - } - - public StringOption(String name, String description, String defaultValue) { - super(name, description); - value = defaultValue; - isSet = false; - hasArgument = HasArgument.YES; - } - - public StringOption makeOptional() { - hasArgument = HasArgument.OPTIONAL; - return this; - } - - @Override - public String getValue() { - return value; - } - - @Override - public Option.HasArgument hasArgument() { - return hasArgument; - } - - @Override - public void match(String value) { - this.value = value; - isSet = true; - } - - @Override - public boolean isSet() { - return isSet; - } -} diff --git a/relast2uml.base/src/test/java/org/jastadd/relast2uml/test/CompilerTest.java b/relast2uml.base/src/test/java/org/jastadd/relast2uml/test/CompilerTest.java index 14de18e22bd30cb474cf9548c92641066667cd8f..08174e4053964ff5154671bb8afe764d7f14c314 100644 --- a/relast2uml.base/src/test/java/org/jastadd/relast2uml/test/CompilerTest.java +++ b/relast2uml.base/src/test/java/org/jastadd/relast2uml/test/CompilerTest.java @@ -1,12 +1,11 @@ package org.jastadd.relast2uml.test; +import org.jastadd.relast.compiler.CompilerException; import org.jastadd.relast2uml.compiler.Compiler; -import org.jastadd.relast2uml.compiler.options.CommandLine; import org.junit.jupiter.api.Test; import java.io.File; import java.nio.file.Paths; -import java.util.Objects; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -18,7 +17,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; */ public class CompilerTest { - void transform(String inputGrammar, String inputRelast2Uml, String output) throws CommandLine.CommandLineException, Compiler.CompilerException { + @SuppressWarnings("SameParameterValue") + void transform(String inputGrammar, String inputRelast2Uml, String output) throws CompilerException { System.out.println("Running test in directory '" + Paths.get(".").toAbsolutePath() + "'."); assertTrue(Paths.get(inputGrammar).toFile().exists(), "input grammar does not exist"); @@ -43,7 +43,7 @@ public class CompilerTest { } @Test - void transformMinimalExample() throws CommandLine.CommandLineException, Compiler.CompilerException { + void transformMinimalExample() throws CompilerException { transform("src/test/resources/Example.relast", "src/test/resources/Example.relast2uml", "src/test/resources/uml.md"); } }