218 lines
6.7 KiB
Java
218 lines
6.7 KiB
Java
package interpreter;
|
|
|
|
import environment.RuntimeEnvironment;
|
|
import error.CriticalLispException;
|
|
import error.ErrorManager;
|
|
import interpreter.LispInterpreter.LanguageFile;
|
|
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.InputStream;
|
|
import java.io.PrintStream;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.function.Function;
|
|
|
|
import static util.Path.getPathPrefix;
|
|
|
|
public class LispInterpreterBuilderImpl implements LispInterpreterBuilder {
|
|
|
|
private static LispInterpreterBuilder uniqueInstance = new LispInterpreterBuilderImpl();
|
|
|
|
public static LispInterpreterBuilder getInstance() {
|
|
return uniqueInstance;
|
|
}
|
|
|
|
private String inputName;
|
|
private InputStream inputStream;
|
|
private PrintStream outputStream;
|
|
private PrintStream errorOutputStream;
|
|
private Runnable terminationFunction;
|
|
private Runnable errorTerminationFunction;
|
|
private List<LanguageFile> languageFiles;
|
|
private Function<String, String> promptDecorator;
|
|
private Function<String, String> valueOutputDecorator;
|
|
private Function<String, String> warningOutputDecorator;
|
|
private Function<String, String> errorOutputDecorator;
|
|
private Function<String, String> criticalOutputDecorator;
|
|
private RuntimeEnvironment environment;
|
|
private boolean isInteractive;
|
|
private boolean isFileBased;
|
|
protected boolean isBuilt;
|
|
|
|
protected LispInterpreterBuilderImpl() {
|
|
this.environment = RuntimeEnvironment.getInstance();
|
|
this.inputName = "";
|
|
this.isInteractive = true;
|
|
this.isFileBased = false;
|
|
this.isBuilt = false;
|
|
this.languageFiles = new ArrayList<>();
|
|
this.promptDecorator = s -> s;
|
|
this.valueOutputDecorator = s -> s;
|
|
this.warningOutputDecorator = s -> s;
|
|
this.errorOutputDecorator = s -> s;
|
|
this.criticalOutputDecorator = s -> s;
|
|
}
|
|
|
|
@Override
|
|
public void setInput(InputStream inputStream, String inputName) {
|
|
this.inputStream = inputStream;
|
|
this.inputName = inputName;
|
|
}
|
|
|
|
@Override
|
|
public void setOutput(PrintStream outputStream) {
|
|
this.outputStream = outputStream;
|
|
}
|
|
|
|
@Override
|
|
public void setErrorOutput(PrintStream errorOutputStream) {
|
|
this.errorOutputStream = errorOutputStream;
|
|
}
|
|
|
|
@Override
|
|
public void setTerminationFunction(Runnable terminationFunction) {
|
|
this.terminationFunction = terminationFunction;
|
|
}
|
|
|
|
@Override
|
|
public void setErrorTerminationFunction(Runnable errorTerminationFunction) {
|
|
this.errorTerminationFunction = errorTerminationFunction;
|
|
}
|
|
|
|
@Override
|
|
public void setNotInteractive() {
|
|
this.isInteractive = false;
|
|
}
|
|
|
|
@Override
|
|
public void useFile(String fileName) {
|
|
this.isFileBased = true;
|
|
this.inputName = fileName;
|
|
this.setNotInteractive();
|
|
}
|
|
|
|
@Override
|
|
public void setLanguageFileNames(String... languageFileNames) {
|
|
ClassLoader classLoader = getClass().getClassLoader();
|
|
languageFiles = new ArrayList<>();
|
|
|
|
for (String fileName : languageFileNames)
|
|
languageFiles.add(new LanguageFile(classLoader.getResourceAsStream(fileName), fileName));
|
|
}
|
|
|
|
@Override
|
|
public void setPromptDecorator(Function<String, String> decorator) {
|
|
this.promptDecorator = decorator;
|
|
}
|
|
|
|
@Override
|
|
public void setValueOutputDecorator(Function<String, String> decorator) {
|
|
this.valueOutputDecorator = decorator;
|
|
}
|
|
|
|
@Override
|
|
public void setWarningOutputDecorator(Function<String, String> decorator) {
|
|
this.warningOutputDecorator = decorator;
|
|
}
|
|
|
|
@Override
|
|
public void setErrorOutputDecorator(Function<String, String> decorator) {
|
|
this.errorOutputDecorator = decorator;
|
|
}
|
|
|
|
@Override
|
|
public void setCriticalOutputDecorator(Function<String, String> decorator) {
|
|
this.criticalOutputDecorator = decorator;
|
|
}
|
|
|
|
@Override
|
|
public LispInterpreter build() {
|
|
if (!isBuilt)
|
|
return buildInterpreter();
|
|
else
|
|
throw new InterpreterAlreadyBuiltException();
|
|
}
|
|
|
|
private LispInterpreter buildInterpreter() {
|
|
configureRuntimeEnvironment();
|
|
LispInterpreter lispInterpreter = createInterpreter();
|
|
lispInterpreter.interpretLanguageFiles(languageFiles);
|
|
isBuilt = true;
|
|
|
|
return lispInterpreter;
|
|
}
|
|
|
|
private void configureRuntimeEnvironment() {
|
|
ErrorManager errorManager = new ErrorManager();
|
|
|
|
environment.setOutput(outputStream);
|
|
environment.setErrorOutput(errorOutputStream);
|
|
environment.setErrorManager(errorManager);
|
|
environment.setTerminationFunction(terminationFunction);
|
|
environment.setErrorTerminationFunction(errorTerminationFunction);
|
|
environment.setPromptDecorator(promptDecorator);
|
|
environment.setValueOutputDecorator(valueOutputDecorator);
|
|
environment.setWarningOutputDecorator(warningOutputDecorator);
|
|
environment.setErrorOutputDecorator(errorOutputDecorator);
|
|
environment.setCriticalOutputDecorator(criticalOutputDecorator);
|
|
configurePath();
|
|
configureInput(errorManager);
|
|
}
|
|
|
|
private void configurePath() {
|
|
if (isFileBased)
|
|
environment.setPath(getPathPrefix(inputName));
|
|
else
|
|
environment.setPath("");
|
|
}
|
|
|
|
private void configureInput(ErrorManager errorManager) {
|
|
environment.setInputName(inputName);
|
|
|
|
try {
|
|
environment.setInput(getInputStream());
|
|
} catch (FileNotFoundException e) {
|
|
errorManager.handle(new LispFileNotFoundException(e));
|
|
}
|
|
}
|
|
|
|
private InputStream getInputStream() throws FileNotFoundException {
|
|
return isFileBased ? new FileInputStream(inputName) : inputStream;
|
|
}
|
|
|
|
private LispInterpreter createInterpreter() {
|
|
if (isFileBased)
|
|
return new FileLispInterpreter();
|
|
else if (isInteractive)
|
|
return new InteractiveLispInterpreter();
|
|
|
|
return new LispInterpreter();
|
|
}
|
|
|
|
public static class InterpreterAlreadyBuiltException extends CriticalLispException {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
@Override
|
|
public String getMessage() {
|
|
return "Refusing to build more than one interpreter.";
|
|
}
|
|
}
|
|
|
|
public static class LispFileNotFoundException extends CriticalLispException {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
private String message;
|
|
|
|
public LispFileNotFoundException(FileNotFoundException e) {
|
|
this.message = e.getMessage();
|
|
}
|
|
|
|
@Override
|
|
public String getMessage() {
|
|
return message;
|
|
}
|
|
}
|
|
}
|