From 9074eeb877c8098953f3ff000bf5395362b3cbbe Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Tue, 5 May 2020 09:01:26 +0200
Subject: [PATCH] add the option to make the compiler JastAdd-compliant (i.e.,
 support all JastAdd arguments)

---
 build.gradle                                  |   4 +-
 .../org/jastadd/JastAddConfiguration.java     | 147 ++++++++++++++++++
 .../relast/compiler/AbstractCompiler.java     |  68 ++++++++
 .../relast/compiler/CompilerException.java    |  11 ++
 ...java => RelastSourceToSourceCompiler.java} |  62 ++------
 .../org/jastadd/ros2rag/tests/RelAstTest.java |  12 +-
 6 files changed, 249 insertions(+), 55 deletions(-)
 create mode 100644 src/main/java/org/jastadd/JastAddConfiguration.java
 create mode 100644 src/main/java/org/jastadd/relast/compiler/AbstractCompiler.java
 create mode 100644 src/main/java/org/jastadd/relast/compiler/CompilerException.java
 rename src/main/java/org/jastadd/relast/compiler/{Compiler.java => RelastSourceToSourceCompiler.java} (72%)

diff --git a/build.gradle b/build.gradle
index aff97ea..86a6d5b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ apply plugin: "idea"
 
 sourceCompatibility = 1.8
 
-mainClassName = 'org.jastadd.relast.compiler.Compiler'
+mainClassName = 'org.jastadd.relast.compiler.JastAddExtensionCompiler'
 
 repositories {
     jcenter()
@@ -45,7 +45,7 @@ test {
 
 jar {
     manifest {
-        attributes "Main-Class": 'org.jastadd.relast.compiler.Compiler'
+        attributes "Main-Class": 'org.jastadd.relast.compiler.JastAddExtensionCompiler'
     }
 
     from {
diff --git a/src/main/java/org/jastadd/JastAddConfiguration.java b/src/main/java/org/jastadd/JastAddConfiguration.java
new file mode 100644
index 0000000..0620a16
--- /dev/null
+++ b/src/main/java/org/jastadd/JastAddConfiguration.java
@@ -0,0 +1,147 @@
+/* Copyright (c) 2013-2015, Jesper Öqvist <jesper.oqvist@cs.lth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Lund University nor the names of its
+ *       contributors may be used to endorse or promote products derived from
+ *       this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jastadd;
+
+import org.jastadd.option.ArgumentParser;
+import org.jastadd.option.Option;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * Tracks JastAdd configuration options.
+ *
+ * @author Jesper Öqvist <jesper.oqvist@cs.lth.se>
+ */
+public class JastAddConfiguration extends org.jastadd.Configuration {
+
+  /**
+   * Indicates if there were unknown command-line options
+   */
+  final boolean unknownOptions;
+
+  /**
+   * Parse options from an argument list.
+   *
+   * @param args Command-line arguments to build configuration from
+   * @param err  output stream to print configuration warnings to
+   */
+  public JastAddConfiguration(String[] args, PrintStream err, Collection<Option<?>> extraOptions) {
+    ArgumentParser argParser = new ArgumentParser();
+    argParser.addOptions(allJastAddOptions());
+    argParser.addOptions(extraOptions);
+    unknownOptions = !argParser.parseArgs(args, err);
+    filenames = argParser.getFilenames();
+  }
+
+  private Collection<Option<?>> allJastAddOptions() {
+    Collection<Option<?>> allOptions = new LinkedList<Option<?>>();
+    allOptions.add(ASTNodeOption);
+    allOptions.add(ListOption);
+    allOptions.add(OptOption);
+    allOptions.add(jjtreeOption);
+    allOptions.add(grammarOption);
+    allOptions.add(generateAnnotations);
+    allOptions.add(defaultMapOption);
+    allOptions.add(defaultSetOption);
+    allOptions.add(lazyMapsOption);
+    allOptions.add(privateOption);
+    allOptions.add(rewriteOption);
+    allOptions.add(beaverOption);
+    allOptions.add(lineColumnNumbersOption);
+    allOptions.add(visitCheckOption);
+    allOptions.add(traceVisitCheckOption);
+    allOptions.add(cacheCycleOption);
+    allOptions.add(componentCheckOption);
+    allOptions.add(inhEqCheckOption);
+    allOptions.add(suppressWarningsOption);
+    allOptions.add(refineLegacyOption);
+    allOptions.add(licenseOption);
+    allOptions.add(debugOption);
+    allOptions.add(outputDirOption);
+    allOptions.add(staticStateOption);
+    allOptions.add(tracingOption);
+    allOptions.add(flushOption);
+    allOptions.add(packageNameOption);
+    allOptions.add(versionOption);
+    allOptions.add(helpOption);
+    allOptions.add(printNonStandardOptionsOption);
+    allOptions.add(indentOption);
+    allOptions.add(minListSizeOption);
+    allOptions.add(cacheOption);
+    allOptions.add(incrementalOption);
+
+    // New since 2.1.11.
+    allOptions.add(dotOption);
+    allOptions.add(ASTNodeSuperOption);
+    allOptions.add(generateImplicitsOption);
+
+    // New since 2.1.12.
+    allOptions.add(stateClassNameOption);
+
+    // New since 2.2.1:
+    allOptions.add(safeLazyOption);
+
+    // New since 2.2.3:
+    allOptions.add(statisticsOption);
+
+    // New since 2.2.4:
+    allOptions.add(emptyContainerSingletons);
+    allOptions.add(concurrentOption);
+    allOptions.add(numThreadsOption);
+    allOptions.add(concurrentMap);
+
+    // New since 2.3.4
+    allOptions.add(optimizeImports);
+
+    // Deprecated in 2.1.5.
+    allOptions.add(doxygenOption);
+    allOptions.add(cacheAllOption);
+    allOptions.add(noCachingOption);
+    allOptions.add(cacheNoneOption);
+    allOptions.add(cacheImplicitOption);
+    allOptions.add(ignoreLazyOption);
+    allOptions.add(fullFlushOption);
+
+    // Deprecated in 2.1.9.
+    allOptions.add(docOption);
+    allOptions.add(java1_4Option); // Disabled in 2.1.10.
+    allOptions.add(noLazyMapsOption);
+    allOptions.add(noVisitCheckOption);
+    allOptions.add(noCacheCycleOption);
+    allOptions.add(noRefineLegacyOption);
+    allOptions.add(noComponentCheckOption);
+    allOptions.add(noInhEqCheckOption);
+    allOptions.add(noStaticOption);
+    allOptions.add(deterministicOption);
+
+    return allOptions;
+  }
+
+}
diff --git a/src/main/java/org/jastadd/relast/compiler/AbstractCompiler.java b/src/main/java/org/jastadd/relast/compiler/AbstractCompiler.java
new file mode 100644
index 0000000..cb4a839
--- /dev/null
+++ b/src/main/java/org/jastadd/relast/compiler/AbstractCompiler.java
@@ -0,0 +1,68 @@
+package org.jastadd.relast.compiler;
+
+import org.jastadd.JastAddConfiguration;
+import org.jastadd.option.ArgumentParser;
+import org.jastadd.option.Option;
+
+import java.util.ArrayList;
+
+public abstract class AbstractCompiler {
+
+  private final boolean jastAddCompliant;
+  protected ArrayList<Option<?>> options;
+  private String name;
+  private ArgumentParser commandLine;
+
+  private JastAddConfiguration configuration;
+
+  public AbstractCompiler(String name, boolean jastaddCompliant) {
+    this.name = name;
+    this.jastAddCompliant = jastaddCompliant;
+  }
+
+  public JastAddConfiguration getConfiguration() throws CompilerException {
+    if (configuration == null) {
+      throw new CompilerException("Configuration only supported for JastAdd-compliant compilers!");
+    }
+    return configuration;
+  }
+
+  public int run(String[] args) throws CompilerException {
+
+    options = new ArrayList<>();
+    initOptions();
+    if (jastAddCompliant) {
+      configuration = new JastAddConfiguration(args, System.err, options);
+    } else {
+      commandLine = new ArgumentParser();
+      commandLine.addOptions(options);
+      commandLine.parseArgs(args, System.err);
+    }
+    return compile();
+  }
+
+  abstract int compile() throws CompilerException;
+
+  protected void initOptions() {
+    // there are no options by default
+  }
+
+  protected <OptionType extends Option<?>> OptionType addOption(OptionType option) {
+    options.add(option);
+    return option;
+  }
+
+  protected int error(String message) {
+    System.err.println("Error: " + message);
+    System.err.println();
+    System.err.println("Usage: java -jar " + name + ".jar [--option1] [--option2=value] ...  <filename1> <filename2> ... ");
+    System.err.println("Options:");
+    commandLine.printHelp(System.err);
+    return 1;
+  }
+
+  public String getName() {
+    return name;
+  }
+}
+
diff --git a/src/main/java/org/jastadd/relast/compiler/CompilerException.java b/src/main/java/org/jastadd/relast/compiler/CompilerException.java
new file mode 100644
index 0000000..6949c30
--- /dev/null
+++ b/src/main/java/org/jastadd/relast/compiler/CompilerException.java
@@ -0,0 +1,11 @@
+package org.jastadd.relast.compiler;
+
+public class CompilerException extends Exception {
+  public CompilerException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public CompilerException(String message) {
+    super(message);
+  }
+}
diff --git a/src/main/java/org/jastadd/relast/compiler/Compiler.java b/src/main/java/org/jastadd/relast/compiler/RelastSourceToSourceCompiler.java
similarity index 72%
rename from src/main/java/org/jastadd/relast/compiler/Compiler.java
rename to src/main/java/org/jastadd/relast/compiler/RelastSourceToSourceCompiler.java
index 4f82148..e8f86a0 100644
--- a/src/main/java/org/jastadd/relast/compiler/Compiler.java
+++ b/src/main/java/org/jastadd/relast/compiler/RelastSourceToSourceCompiler.java
@@ -1,8 +1,6 @@
 package org.jastadd.relast.compiler;
 
 import beaver.Parser;
-import org.jastadd.option.ArgumentParser;
-import org.jastadd.option.Option;
 import org.jastadd.option.ValueOption;
 import org.jastadd.relast.ast.GrammarFile;
 import org.jastadd.relast.ast.Program;
@@ -16,37 +14,34 @@ import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
 
-public class Compiler {
+public class RelastSourceToSourceCompiler extends AbstractCompiler {
 
-  private ValueOption optionOutputDir;
-  private ValueOption optionInputDir;
 
-  private ArrayList<Option<?>> options;
-  private ArgumentParser commandLine;
+  protected ValueOption optionOutputDir;
+  protected ValueOption optionInputDir;
 
-  public Compiler() {
-    options = new ArrayList<>();
-    addOptions();
+  public RelastSourceToSourceCompiler(String name, boolean jastAddCompliant) {
+    super(name, jastAddCompliant);
   }
 
   public static void main(String[] args) {
     try {
-      new Compiler().run(args);
+      new RelastSourceToSourceCompiler("relast-preprocessor", true).run(args);
     } catch (CompilerException e) {
       System.err.println(e.getMessage());
       System.exit(-1);
     }
   }
 
-  public int run(String[] args) throws CompilerException {
-    options = new ArrayList<>();
-    addOptions();
-    commandLine = new ArgumentParser();
-    commandLine.addOptions(options);
-    boolean unknownOptions = !commandLine.parseArgs(args, System.err);
+  @Override
+  protected void initOptions() {
+    optionOutputDir = addOption(new ValueOption("outputDir", "target directory for the generated files."));
+    optionInputDir = addOption(new ValueOption("inputDir", "input directory."));
+  }
 
+  @Override
+  protected int compile() throws CompilerException {
     Path inputPath;
     if (optionInputDir.isMatched()) {
       inputPath = Paths.get(optionInputDir.value());
@@ -63,7 +58,7 @@ public class Compiler {
       System.exit(-1);
     }
 
-    Path outputPath; // should not be used, but otherwise there is a compiler warning
+    Path outputPath;
     if (optionOutputDir.isMatched()) {
       outputPath = Paths.get(optionOutputDir.value());
     } else {
@@ -77,10 +72,6 @@ public class Compiler {
 
     printMessage("Running RelAST Preprocessor");
 
-    if (unknownOptions) {
-      printMessage("Some options were unsupported!");
-    }
-
     Program program = parseProgram(inputPath);
 
     printMessage("Writing output files");
@@ -108,16 +99,6 @@ public class Compiler {
     }
   }
 
-  private void addOptions() {
-    optionOutputDir = addOption(new ValueOption("outputDir", "target directory for the generated files."));
-    optionInputDir = addOption(new ValueOption("inputDir", "input directory."));
-  }
-
-  private <OptionType extends Option<?>> OptionType addOption(OptionType option) {
-    options.add(option);
-    return option;
-  }
-
   private Program parseProgram(Path inputPath) throws CompilerException {
     Program program = new Program();
 
@@ -144,20 +125,5 @@ public class Compiler {
 
     return program;
   }
-
-  protected int error(String message) {
-    System.err.println("Error: " + message);
-    System.err.println();
-    System.err.println("Usage: java -jar relast.jar [--option1] [--option2=value] ...  <filename1> <filename2> ... ");
-    System.err.println("Options:");
-    commandLine.printHelp(System.err);
-    return 1;
-  }
-
-  public static class CompilerException extends Exception {
-    CompilerException(String message, Throwable cause) {
-      super(message, cause);
-    }
-  }
 }
 
diff --git a/src/test/java/org/jastadd/ros2rag/tests/RelAstTest.java b/src/test/java/org/jastadd/ros2rag/tests/RelAstTest.java
index becda3f..fdc383d 100644
--- a/src/test/java/org/jastadd/ros2rag/tests/RelAstTest.java
+++ b/src/test/java/org/jastadd/ros2rag/tests/RelAstTest.java
@@ -1,6 +1,7 @@
 package org.jastadd.ros2rag.tests;
 
-import org.jastadd.relast.compiler.Compiler;
+import org.jastadd.relast.compiler.CompilerException;
+import org.jastadd.relast.compiler.RelastSourceToSourceCompiler;
 import org.junit.jupiter.api.Test;
 
 import java.io.File;
@@ -11,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class RelAstTest {
 
-  void transform(String inputDir, String outputDir) throws Compiler.CompilerException {
+  void transform(boolean jastAddCompliant, String inputDir, String outputDir) throws CompilerException {
 
     System.out.println("Running test in directory '" + Paths.get(".").toAbsolutePath() + "'.");
     assertTrue(Paths.get(inputDir).toFile().exists(), "input directory does not exist");
@@ -32,11 +33,12 @@ public class RelAstTest {
         "--inputDir=" + inputDir
     };
 
-    new Compiler().run(args);
+    new RelastSourceToSourceCompiler("testCompiler", jastAddCompliant).run(args);
   }
 
   @Test
-  void transformMinimalExample() throws Compiler.CompilerException {
-    transform("src/test/resources/in", "src/test/resources/out");
+  void transformMinimalExample() throws CompilerException {
+    transform(false,"src/test/resources/in", "src/test/resources/out");
+    transform(true,"src/test/resources/in", "src/test/resources/out");
   }
 }
-- 
GitLab