diff --git a/src/main/java/org/jastadd/relast/compiler/Compiler.java b/src/main/java/org/jastadd/relast/compiler/Compiler.java index 4dd39ba0e3a228e919048771d8b61942629d3a67..50e92e5f69ef1900fba30c31c94840489da7647e 100644 --- a/src/main/java/org/jastadd/relast/compiler/Compiler.java +++ b/src/main/java/org/jastadd/relast/compiler/Compiler.java @@ -1,142 +1,148 @@ 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); + } } diff --git a/src/main/java/org/jastadd/relast/compiler/Utils.java b/src/main/java/org/jastadd/relast/compiler/Utils.java index 12baf95e9989afab7ff110cd1754e5c6537e4742..8e2ef0c8bcb8266fe5789b2608f4a6f78c47548a 100644 --- a/src/main/java/org/jastadd/relast/compiler/Utils.java +++ b/src/main/java/org/jastadd/relast/compiler/Utils.java @@ -1,16 +1,16 @@ 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)); + } } diff --git a/src/main/java/org/jastadd/relast/compiler/options/CommandLine.java b/src/main/java/org/jastadd/relast/compiler/options/CommandLine.java index 21ca600898aecdf372fac272390148a97d349c95..c3f02bf56d4fb4c779e489cfaa7fb150c6ea68cb 100644 --- a/src/main/java/org/jastadd/relast/compiler/options/CommandLine.java +++ b/src/main/java/org/jastadd/relast/compiler/options/CommandLine.java @@ -1,101 +1,97 @@ 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); + } + } } diff --git a/src/main/java/org/jastadd/relast/compiler/options/EnumOption.java b/src/main/java/org/jastadd/relast/compiler/options/EnumOption.java index 7c03a32399a6f4314d9a43644f850391e20b36d4..92b5149a9c3d36cf2053f0a7d0a2cadfd52129ec 100644 --- a/src/main/java/org/jastadd/relast/compiler/options/EnumOption.java +++ b/src/main/java/org/jastadd/relast/compiler/options/EnumOption.java @@ -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 + 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/src/main/java/org/jastadd/relast/compiler/options/FlagOption.java b/src/main/java/org/jastadd/relast/compiler/options/FlagOption.java index 44ac1127c476755f41146fba9406997b6ef27205..80c2f0cb0313cc05ca9b05795fc3acc3ebd5d849 100644 --- a/src/main/java/org/jastadd/relast/compiler/options/FlagOption.java +++ b/src/main/java/org/jastadd/relast/compiler/options/FlagOption.java @@ -1,30 +1,30 @@ package org.jastadd.relast.compiler.options; public class FlagOption extends Option<Boolean> { - private boolean value; - - public FlagOption(String name, String description) { - super(name, description); - value = false; - } + private boolean value; - @Override - public Boolean getValue() { - return value; - } + public FlagOption(String name, String description) { + super(name, description); + value = false; + } - @Override - public Option.HasArgument hasArgument() { - return Option.HasArgument.NO; - } - - @Override - public void match(String string) throws IllegalMatchException { - value = true; - } + @Override + public Boolean getValue() { + return value; + } - @Override - public boolean isSet() { - return getValue(); - } + @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/src/main/java/org/jastadd/relast/compiler/options/Option.java b/src/main/java/org/jastadd/relast/compiler/options/Option.java index 537ea9a4805e9af50dc51b523a422c38413ae29e..b1789a5945aa1a414386f9f1536551e7b8f1ce81 100644 --- a/src/main/java/org/jastadd/relast/compiler/options/Option.java +++ b/src/main/java/org/jastadd/relast/compiler/options/Option.java @@ -1,56 +1,59 @@ package org.jastadd.relast.compiler.options; abstract public class Option<ValueType> implements Comparable<Option<?>> { - public final static String PREFIX = "--"; - public static enum HasArgument { - NO, - OPTIONAL, - YES - } - - 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 static class IllegalMatchException extends Exception { - private static final long serialVersionUID = 1L; - public IllegalMatchException(String message) { - super(message); - } - } + 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/src/main/java/org/jastadd/relast/compiler/options/StringOption.java b/src/main/java/org/jastadd/relast/compiler/options/StringOption.java index 087a2b4cd34830205a0d13ec117393bc969896dd..a1298aeaadc259e5ecca3f1ffbade77de9a8315b 100644 --- a/src/main/java/org/jastadd/relast/compiler/options/StringOption.java +++ b/src/main/java/org/jastadd/relast/compiler/options/StringOption.java @@ -1,37 +1,37 @@ package org.jastadd.relast.compiler.options; public class StringOption extends Option<String> { - 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; - } + private String value; + private boolean isSet; - @Override - public String getValue() { - return value; - } - - @Override - public Option.HasArgument hasArgument() { - return Option.HasArgument.YES; - } - - @Override - public void match(String value) throws IllegalMatchException { - this.value = value; - isSet = true; - } + public StringOption(String name, String description) { + this(name, description, ""); + } - @Override - public boolean isSet() { - return isSet; - } + public StringOption(String name, String description, String defaultValue) { + super(name, description); + value = defaultValue; + isSet = false; + } + + @Override + public String getValue() { + return value; + } + + @Override + public Option.HasArgument hasArgument() { + return Option.HasArgument.YES; + } + + @Override + public void match(String value) { + this.value = value; + isSet = true; + } + + @Override + public boolean isSet() { + return isSet; + } }