Commit f930689b authored by Johannes Mey's avatar Johannes Mey
Browse files

support multiple ast files and some style alignment

parent d03c0988
package org.jastadd.relast.compiler;
import org.jastadd.relast.ast.*;
import static org.jastadd.relast.compiler.Utils.filterToList;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Pattern;
import beaver.Parser;
import org.jastadd.relast.ast.*;
import org.jastadd.relast.compiler.options.CommandLine;
import org.jastadd.relast.compiler.options.EnumOption;
import org.jastadd.relast.compiler.options.CommandLine.CommandLineException;
import org.jastadd.relast.compiler.options.FlagOption;
import org.jastadd.relast.compiler.options.Option;
import org.jastadd.relast.compiler.options.StringOption;
import org.jastadd.relast.compiler.options.CommandLine.CommandLineException;
import beaver.Parser;
import org.jastadd.relast.parser.RelAstParser;
import org.jastadd.relast.scanner.RelAstScanner;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Compiler {
protected ArrayList<Option<?>> options;
protected FlagOption optionWriteToFile;
protected FlagOption optionPrintAST;
protected StringOption optionListClass;
protected CommandLine commandLine;
public Compiler(String args[]) throws CommandLineException {
options = new ArrayList<>();
addOptions();
commandLine = new CommandLine(options);
commandLine.parse(args);
if (commandLine.getArguments().size() != 1) {
error("specify one input file");
}
String filename = commandLine.getArguments().get(0);
Program p = parseProgram(filename);
if (!p.errors().isEmpty()) {
if (optionPrintAST.isSet()) {
System.out.println(p.dumpTree());
}
System.err.println("Errors:");
for (ErrorMessage e: p.errors()) {
System.err.println(e);
}
System.exit(1);
} else {
if (optionListClass.isSet()) {
System.out.println("ListClass is set to " + optionListClass.getValue());
p.listClass = optionListClass.getValue();
}
if (optionWriteToFile.isSet()) {
File file = new File(filename);
String absPath = file.getAbsolutePath();
String absPathExclExt = absPath.substring(0, absPath.lastIndexOf('.'));
writeToFile(absPathExclExt + "Gen.ast", p.generateAbstractGrammar());
writeToFile(absPathExclExt + "Gen.jadd", p.generateAspect());
} else if (optionPrintAST.isSet()) {
System.out.println(p.dumpTree());
} else {
System.out.println(p.generateAbstractGrammar());
System.out.println(p.generateAspect());
}
}
}
protected void writeToFile(String filename, String str) {
try {
PrintWriter writer = new PrintWriter(filename);
writer.print(str);
writer.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
protected void addOptions() {
optionWriteToFile = addOption(new FlagOption("file", "write output to files <filename>Gen.ast and <filename>Gen.jadd"));
optionPrintAST = addOption(new FlagOption("ast", "print AST"));
optionListClass = addOption(new StringOption("listClass", "determine the class name of the nonterminal reference list"));
}
protected <OptionType extends Option<?>> OptionType addOption(OptionType option) {
options.add(option);
return option;
}
private Program parseProgram(String file) {
FileReader reader = null;
try {
reader = new FileReader(file);
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
System.exit(1);
}
return parse(reader, file);
}
private Program parse(Reader reader, String file) {
RelAstScanner scanner = new RelAstScanner(reader);
RelAstParser parser = new RelAstParser();
try {
return (Program) parser.parse(scanner);
} catch (IOException e) {
error(e.getMessage());
} catch (Parser.Exception e) {
System.err.println("Parse error in file " + file);
System.err.println(e.getMessage());
System.exit(1);
}
return null;
}
protected void error(String message) {
System.err.println("Error: " + message);
System.err.println();
System.err.println("Usage: java -jar relast-compiler.jar <filename> [--option1] [--option2=value] ... ");
System.err.println("Options:");
System.err.print(commandLine.printOptionHelp());
System.exit(1);
}
public static void main(String[] args) {
try {
new Compiler(args);
} catch (CommandLineException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
private ArrayList<Option<?>> options;
private FlagOption optionWriteToFile;
private FlagOption optionPrintAST;
private StringOption optionListClass;
private CommandLine commandLine;
public Compiler(String[] args) throws CommandLineException {
options = new ArrayList<>();
addOptions();
commandLine = new CommandLine(options);
commandLine.parse(args);
if (commandLine.getArguments().size() < 1) {
error("specify at least one input file");
}
List<String> filenames = commandLine.getArguments();
Program p = parseProgram(filenames);
if (!p.errors().isEmpty()) {
if (optionPrintAST.isSet()) {
System.out.println(p.dumpTree());
}
System.err.println("Errors:");
for (ErrorMessage e : p.errors()) {
System.err.println(e);
}
System.exit(1);
} else {
if (optionListClass.isSet()) {
System.out.println("ListClass is set to " + optionListClass.getValue());
ASTNode.listClass = optionListClass.getValue();
}
if (optionWriteToFile.isSet()) {
File file = new File(filenames.get(0));
String absPath = file.getAbsolutePath();
String absPathExclExt = absPath.substring(0, absPath.lastIndexOf('.'));
writeToFile(absPathExclExt + "Gen.ast", p.generateAbstractGrammar());
writeToFile(absPathExclExt + "Gen.jadd", p.generateAspect());
} else if (optionPrintAST.isSet()) {
System.out.println(p.dumpTree());
} else {
System.out.println(p.generateAbstractGrammar());
System.out.println(p.generateAspect());
}
}
}
public static void main(String[] args) {
try {
new Compiler(args);
} catch (CommandLineException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
private void writeToFile(String filename, String str) {
try {
PrintWriter writer = new PrintWriter(filename);
writer.print(str);
writer.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
private void addOptions() {
optionWriteToFile = addOption(new FlagOption("file", "write output to files <filename>Gen.ast and <filename>Gen.jadd"));
optionPrintAST = addOption(new FlagOption("ast", "print AST"));
optionListClass = addOption(new StringOption("listClass", "determine the class name of the nonterminal reference list"));
}
private <OptionType extends Option<?>> OptionType addOption(OptionType option) {
options.add(option);
return option;
}
private Program parseProgram(List<String> fileNames) {
Program program = new Program();
for (String fileName : fileNames) {
FileReader reader = null;
try {
reader = new FileReader(fileName);
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
System.exit(1);
}
parse(program, reader, fileName);
}
return program;
}
private void parse(Program program, Reader reader, String file) {
RelAstScanner scanner = new RelAstScanner(reader);
RelAstParser parser = new RelAstParser();
try {
Program newProgram = (Program) parser.parse(scanner);
for (TypeDecl typeDecl : newProgram.getTypeDeclList()) {
program.addTypeDecl(typeDecl);
}
for (Relation relation : newProgram.getRelationList()) {
program.addRelation(relation);
}
} catch (IOException e) {
error(e.getMessage());
} catch (Parser.Exception e) {
System.err.println("Parse error in file " + file);
System.err.println(e.getMessage());
System.exit(1);
}
}
protected void 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:");
System.err.print(commandLine.printOptionHelp());
System.exit(1);
}
}
package org.jastadd.relast.compiler;
import static java.util.stream.Collectors.toList;
import java.util.*;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toList;
public class Utils {
public static <T> List<T> filterToList(Collection<T> collection, Predicate<T> predicate) {
return collection.stream().filter(predicate).collect(toList());
}
public static <T> List<T> filterToList(Collection<T> collection, Predicate<T> predicate) {
return collection.stream().filter(predicate).collect(toList());
}
public static <T> Set<T> asSet(T... t) {
return new HashSet<T>(Arrays.asList(t));
}
public static <T> Set<T> asSet(T... t) {
return new HashSet<T>(Arrays.asList(t));
}
}
package org.jastadd.relast.compiler.options;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
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++;
}
}
private final Collection<Option<?>> options;
private final Map<String, Option<?>> mapping;
private final List<String> arguments;
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);
}
}
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);
}
}
}
......@@ -4,57 +4,57 @@ 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 + ")";
}
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