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

switch to base directory approach

parent 9074eeb8
Branches
Tags
No related merge requests found
build build
src/gen-res/ src/gen-res/
src/gen/ src/gen/
out/ out*/
*.class *.class
...@@ -31,8 +31,8 @@ import org.jastadd.option.ArgumentParser; ...@@ -31,8 +31,8 @@ import org.jastadd.option.ArgumentParser;
import org.jastadd.option.Option; import org.jastadd.option.Option;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.Collection; import java.util.*;
import java.util.LinkedList; import java.util.stream.Collectors;
/** /**
* Tracks JastAdd configuration options. * Tracks JastAdd configuration options.
...@@ -46,22 +46,52 @@ public class JastAddConfiguration extends org.jastadd.Configuration { ...@@ -46,22 +46,52 @@ public class JastAddConfiguration extends org.jastadd.Configuration {
*/ */
final boolean unknownOptions; final boolean unknownOptions;
private boolean isJastAddCompliant;
public boolean isJastAddCompliant() {
return isJastAddCompliant;
}
/** /**
* Parse options from an argument list. * Parse options from an argument list.
* *
* @param args Command-line arguments to build configuration from * @param args Command-line arguments to build configuration from
* @param err output stream to print configuration warnings to * @param err output stream to print configuration warnings to
*/ */
public JastAddConfiguration(String[] args, PrintStream err, Collection<Option<?>> extraOptions) { public JastAddConfiguration(String[] args, PrintStream err, boolean isJastAddCompliant, Collection<Option<?>> extraOptions) {
ArgumentParser argParser = new ArgumentParser(); ArgumentParser argParser = new ArgumentParser();
argParser.addOptions(allJastAddOptions()); this.isJastAddCompliant = isJastAddCompliant;
argParser.addOptions(extraOptions); if (isJastAddCompliant) {
Collection<Option<?>> jastAddOptions = allJastAddOptions();
argParser.addOptions(jastAddOptions);
// if the JastAdd options are supported, we have to check for duplicates!
Set<String> jastAddOptionNames = jastAddOptions.stream().map(o -> o.name()).collect(Collectors.toSet());
for (Option option : extraOptions) {
if (jastAddOptionNames.contains(option.name())) {
System.err.println("Unable to add option '" + option.name() + "', because there is a JastAdd option with the same name.");
} else {
argParser.addOption(option);
}
}
} else {
argParser.addOptions(extraOptions);
}
unknownOptions = !argParser.parseArgs(args, err); unknownOptions = !argParser.parseArgs(args, err);
filenames = argParser.getFilenames(); filenames = argParser.getFilenames();
} }
/**
* @return all files
*/
@Override
public Collection<String> getFiles() {
return Collections.unmodifiableCollection(filenames);
}
private Collection<Option<?>> allJastAddOptions() { private Collection<Option<?>> allJastAddOptions() {
Collection<Option<?>> allOptions = new LinkedList<Option<?>>(); Collection<Option<?>> allOptions = new LinkedList<>();
allOptions.add(ASTNodeOption); allOptions.add(ASTNodeOption);
allOptions.add(ListOption); allOptions.add(ListOption);
allOptions.add(OptOption); allOptions.add(OptOption);
......
...@@ -31,13 +31,8 @@ public abstract class AbstractCompiler { ...@@ -31,13 +31,8 @@ public abstract class AbstractCompiler {
options = new ArrayList<>(); options = new ArrayList<>();
initOptions(); initOptions();
if (jastAddCompliant) { configuration = new JastAddConfiguration(args, System.err, jastAddCompliant, options);
configuration = new JastAddConfiguration(args, System.err, options);
} else {
commandLine = new ArgumentParser();
commandLine.addOptions(options);
commandLine.parseArgs(args, System.err);
}
return compile(); return compile();
} }
......
...@@ -10,16 +10,18 @@ import org.jastadd.relast.scanner.RelAstScanner; ...@@ -10,16 +10,18 @@ import org.jastadd.relast.scanner.RelAstScanner;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.DirectoryStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
public class RelastSourceToSourceCompiler extends AbstractCompiler { public class RelastSourceToSourceCompiler extends AbstractCompiler {
protected ValueOption optionOutputDir; protected ValueOption optionOutputBaseDir;
protected ValueOption optionInputDir; protected ValueOption optionInputBaseDir;
public RelastSourceToSourceCompiler(String name, boolean jastAddCompliant) { public RelastSourceToSourceCompiler(String name, boolean jastAddCompliant) {
super(name, jastAddCompliant); super(name, jastAddCompliant);
...@@ -34,96 +36,109 @@ public class RelastSourceToSourceCompiler extends AbstractCompiler { ...@@ -34,96 +36,109 @@ public class RelastSourceToSourceCompiler extends AbstractCompiler {
} }
} }
protected static boolean isGrammarFile(String fileName) {
String extension = fileName.subSequence(fileName.lastIndexOf("."), fileName.length()).toString();
return extension.equals(".relast") || extension.equals(".ast");
}
@Override @Override
protected void initOptions() { protected void initOptions() {
optionOutputDir = addOption(new ValueOption("outputDir", "target directory for the generated files.")); optionOutputBaseDir = addOption(new ValueOption("outputBaseDir", "base directory for generated files"));
optionInputDir = addOption(new ValueOption("inputDir", "input directory.")); optionInputBaseDir = addOption(new ValueOption("inputBaseDir", "base directory for input files"));
} }
@Override @Override
protected int compile() throws CompilerException { protected int compile() throws CompilerException {
Path inputPath; final Path inputBasePath;
if (optionInputDir.isMatched()) { if (optionInputBaseDir.isMatched()) {
inputPath = Paths.get(optionInputDir.value()); inputBasePath = Paths.get(optionInputBaseDir.value()).toAbsolutePath();
} else { } else {
inputPath = Paths.get("."); inputBasePath = Paths.get(".").toAbsolutePath();
printMessage("No input dir is set. Assuming current directory '" + inputPath.toAbsolutePath().toString() + "'."); printMessage("No input base dir is set. Assuming current directory '" + inputBasePath.toAbsolutePath().toString() + "'.");
} }
if (!inputPath.toFile().exists()) { if (!inputBasePath.toFile().exists()) {
printMessage("Input path '" + inputPath.toAbsolutePath().toString() + "' does not exist. Exiting..."); printMessage("Input path '" + inputBasePath.toAbsolutePath().toString() + "' does not exist. Exiting...");
System.exit(-1); System.exit(-1);
} else if (!inputPath.toFile().isDirectory()) { } else if (!inputBasePath.toFile().isDirectory()) {
printMessage("Input path '" + inputPath.toAbsolutePath().toString() + "' is not a directory. Exiting..."); printMessage("Input path '" + inputBasePath.toAbsolutePath().toString() + "' is not a directory. Exiting...");
System.exit(-1); System.exit(-1);
} }
Path outputPath; final Path outputBasePath;
if (optionOutputDir.isMatched()) { if (optionOutputBaseDir.isMatched()) {
outputPath = Paths.get(optionOutputDir.value()); outputBasePath = Paths.get(optionOutputBaseDir.value()).toAbsolutePath();
} else { } else {
outputPath = Paths.get("./gen/"); throw new CompilerException("No output base dir is set.");
printMessage("No output dir is set. Assuming '" + outputPath.toAbsolutePath().toString() + "'.");
} }
if (outputPath.toFile().exists() && !outputPath.toFile().isDirectory()) { if (outputBasePath.toFile().exists() && !outputBasePath.toFile().isDirectory()) {
printMessage("Output path '" + inputPath.toAbsolutePath().toString() + "' exists, but is not a directory. Exiting..."); printMessage("Output path '" + inputBasePath.toAbsolutePath().toString() + "' exists, but is not a directory. Exiting...");
} }
printMessage("Running RelAST Preprocessor"); printMessage("Running RelAST Preprocessor");
Program program = parseProgram(inputPath); // gather all files
Collection<Path> inputFiles = new ArrayList<>();
getConfiguration().getFiles().forEach(name -> relativizeFileName(inputBasePath, Paths.get(name)).ifPresent(path -> inputFiles.add(path)));
Program program = parseProgram(inputFiles);
printMessage("Writing output files"); printMessage("Writing output files");
for (GrammarFile grammarFile : program.getGrammarFileList()) { for (GrammarFile grammarFile : program.getGrammarFileList()) {
// TODO decide and document what the file name should be, the full path or a simple name? // TODO decide and document what the file name should be, the full path or a simple name?
writeToFile(outputPath + grammarFile.getFileName() + "/Grammar.relast", grammarFile.generateAbstractGrammar()); writeToFile(outputBasePath.resolve(inputBasePath.relativize(Paths.get(grammarFile.getFileName()))), grammarFile.generateAbstractGrammar());
} }
writeToFile(outputPath + "/Grammar.relast", program.generateAbstractGrammar());
return 0; return 0;
} }
private Optional<Path> relativizeFileName(Path inputBasePath, Path filePath) {
if (filePath.isAbsolute()) {
if (filePath.startsWith(inputBasePath)) {
return Optional.of(filePath.relativize(inputBasePath));
} else {
printMessage("Path '" + filePath + "' is not contained in the base path '" + inputBasePath + "'.");
return Optional.empty();
}
} else {
return Optional.of(inputBasePath.resolve(filePath));
}
}
private void printMessage(String message) { private void printMessage(String message) {
System.out.println(message); System.out.println(message);
} }
private void writeToFile(String filename, String str) throws CompilerException { private void writeToFile(Path path, String str) throws CompilerException {
try { try (PrintWriter writer = new PrintWriter(path.toFile())) {
PrintWriter writer = new PrintWriter(filename);
writer.print(str); writer.print(str);
writer.close();
} catch (Exception e) { } catch (Exception e) {
throw new CompilerException("Could not write to file " + filename, e); throw new CompilerException("Could not write to file " + path, e);
} }
} }
private Program parseProgram(Path inputPath) throws CompilerException { private Program parseProgram(Collection<Path> inputFiles) throws CompilerException {
Program program = new Program(); Program program = new Program();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(inputPath, "*.relast")) { RelAstParser parser = new RelAstParser();
RelAstParser parser = new RelAstParser(); inputFiles.stream().filter(path -> isGrammarFile(path.toString())).forEach(
stream.forEach(path -> { path -> {
try (BufferedReader reader = Files.newBufferedReader(path)) { try (BufferedReader reader = Files.newBufferedReader(path)) {
RelAstScanner scanner = new RelAstScanner(reader); RelAstScanner scanner = new RelAstScanner(reader);
GrammarFile inputGrammar = (GrammarFile) parser.parse(scanner); GrammarFile inputGrammar = (GrammarFile) parser.parse(scanner);
inputGrammar.dumpTree(System.out); inputGrammar.setFileName(path.toString());
program.addGrammarFile(inputGrammar); program.addGrammarFile(inputGrammar);
inputGrammar.treeResolveAll(); inputGrammar.treeResolveAll();
} catch (IOException | Parser.Exception e) { } catch (IOException | Parser.Exception e) {
printMessage("Could not parse grammar file " + path); printMessage("Could not parse grammar file " + path);
e.printStackTrace(); e.printStackTrace();
}
} }
}); );
} catch (IOException e) {
printMessage("Unable to iterate over input path '" + inputPath.toAbsolutePath().toString() + "'. Exiting...");
e.printStackTrace();
System.exit(-1);
}
return program; return program;
} }
} }
...@@ -29,8 +29,9 @@ public class RelAstTest { ...@@ -29,8 +29,9 @@ public class RelAstTest {
} }
String[] args = { String[] args = {
"--outputDir=" + outputDir, "--outputBaseDir=" + outputDir,
"--inputDir=" + inputDir "--inputBaseDir=" + inputDir,
"Example.relast"
}; };
new RelastSourceToSourceCompiler("testCompiler", jastAddCompliant).run(args); new RelastSourceToSourceCompiler("testCompiler", jastAddCompliant).run(args);
...@@ -38,7 +39,7 @@ public class RelAstTest { ...@@ -38,7 +39,7 @@ public class RelAstTest {
@Test @Test
void transformMinimalExample() throws CompilerException { void transformMinimalExample() throws CompilerException {
transform(false,"src/test/resources/in", "src/test/resources/out"); transform(false,"src/test/resources/in", "src/test/resources/out-simple");
transform(true,"src/test/resources/in", "src/test/resources/out"); transform(true,"src/test/resources/in", "src/test/resources/out-compliant");
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment