Convert the interpreter to kotlin
This commit is contained in:
parent
d376c30d7a
commit
eaf80390be
|
@ -1,7 +1,6 @@
|
|||
package function
|
||||
|
||||
import java.lang.annotation.Retention
|
||||
import java.lang.annotation.RetentionPolicy.RUNTIME
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
import kotlin.annotation.AnnotationTarget.CLASS
|
||||
import kotlin.annotation.AnnotationTarget.FILE
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package interpreter;
|
||||
|
||||
import sexpression.SExpression;
|
||||
|
||||
public class FileLispInterpreter extends LispInterpreter {
|
||||
|
||||
private SExpression lastSExpression;
|
||||
|
||||
public FileLispInterpreter() {
|
||||
this.lastSExpression = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SExpression evaluateNextSExpression() {
|
||||
return this.lastSExpression = super.evaluateNextSExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void printSExpression(SExpression sExpression) {}
|
||||
|
||||
@Override
|
||||
protected void applyFinishingTouches() {
|
||||
if (lastSExpression != null)
|
||||
super.printSExpression(lastSExpression);
|
||||
|
||||
super.applyFinishingTouches();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package interpreter
|
||||
|
||||
import sexpression.SExpression
|
||||
|
||||
class FileLispInterpreter : LispInterpreter() {
|
||||
|
||||
private var lastSExpression: SExpression? = null
|
||||
|
||||
override fun printSExpression(sExpression: SExpression) {
|
||||
lastSExpression = sExpression
|
||||
}
|
||||
|
||||
override fun applyFinishingTouches() {
|
||||
if (lastSExpression != null)
|
||||
super.printSExpression(lastSExpression!!)
|
||||
|
||||
super.applyFinishingTouches()
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package interpreter;
|
||||
|
||||
public class InteractiveLispInterpreter extends LispInterpreter {
|
||||
|
||||
public static final String PROMPT = "~ ";
|
||||
|
||||
@Override
|
||||
protected void prompt() {
|
||||
environment.getOutput().print(environment.decoratePrompt(PROMPT));
|
||||
environment.getOutput().flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evaluateAndPrintNextSExpression() {
|
||||
environment.getOutput().println();
|
||||
super.evaluateAndPrintNextSExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyFinishingTouches() {
|
||||
environment.getOutput().println(environment.decoratePrompt(""));
|
||||
environment.getOutput().flush();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package interpreter
|
||||
|
||||
import environment.RuntimeEnvironment.decoratePrompt
|
||||
import environment.RuntimeEnvironment.output
|
||||
import sexpression.SExpression
|
||||
|
||||
class InteractiveLispInterpreter : LispInterpreter() {
|
||||
|
||||
override fun prompt() = output?.run {
|
||||
print(decoratePrompt(PROMPT))
|
||||
flush()
|
||||
}
|
||||
|
||||
override fun printSExpression(sExpression: SExpression) = output?.run {
|
||||
println()
|
||||
super.printSExpression(sExpression)
|
||||
}
|
||||
|
||||
override fun applyFinishingTouches() = output?.run {
|
||||
println(decoratePrompt(""))
|
||||
flush()
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal const val PROMPT = "~ "
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
package interpreter;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import error.LispException;
|
||||
import parser.LispParser;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
|
||||
public class LispInterpreter {
|
||||
|
||||
protected RuntimeEnvironment environment;
|
||||
private LispParser parser;
|
||||
|
||||
public LispInterpreter() {
|
||||
this.environment = RuntimeEnvironment.INSTANCE;
|
||||
}
|
||||
|
||||
public void interpretLanguageFiles(List<LanguageFile> languageFiles) {
|
||||
for (LanguageFile file : languageFiles) {
|
||||
LispParser languageParser = new LispParser(file.getInputStream(), file.getName());
|
||||
|
||||
while (!languageParser.isEof())
|
||||
eval(languageParser.nextSExpression());
|
||||
}
|
||||
}
|
||||
|
||||
public void interpret() {
|
||||
createParser();
|
||||
|
||||
for (prompt(); !parser.isEof(); prompt())
|
||||
evaluateAndPrintNextSExpression();
|
||||
|
||||
applyFinishingTouches();
|
||||
}
|
||||
|
||||
private void createParser() {
|
||||
parser = new LispParser(environment.getInput(), environment.getInputName());
|
||||
}
|
||||
|
||||
protected void prompt() {}
|
||||
|
||||
protected void evaluateAndPrintNextSExpression() {
|
||||
try {
|
||||
evaluateAndPrintNextSExpressionWithException();
|
||||
} catch (LispException e) {
|
||||
environment.getErrorManager().handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void evaluateAndPrintNextSExpressionWithException() {
|
||||
printSExpression(evaluateNextSExpression());
|
||||
}
|
||||
|
||||
protected SExpression evaluateNextSExpression() {
|
||||
SExpression sExpression = parser.nextSExpression();
|
||||
|
||||
return eval(sExpression);
|
||||
}
|
||||
|
||||
protected void printSExpression(SExpression sExpression) {
|
||||
String result = environment.decorateValueOutput(String.valueOf(sExpression));
|
||||
environment.getOutput().println(result);
|
||||
environment.getOutput().flush();
|
||||
}
|
||||
|
||||
protected void applyFinishingTouches() {
|
||||
environment.getOutput().println();
|
||||
environment.getOutput().flush();
|
||||
}
|
||||
|
||||
public static class LanguageFile {
|
||||
|
||||
private InputStream inputStream;
|
||||
private String name;
|
||||
|
||||
public LanguageFile(InputStream inputStream, String name) {
|
||||
this.inputStream = inputStream;
|
||||
this.name = "lang:" + name;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package interpreter
|
||||
|
||||
import environment.RuntimeEnvironment.decorateValueOutput
|
||||
import environment.RuntimeEnvironment.errorManager
|
||||
import environment.RuntimeEnvironment.input
|
||||
import environment.RuntimeEnvironment.inputName
|
||||
import environment.RuntimeEnvironment.output
|
||||
import error.LispException
|
||||
import function.builtin.EVAL.eval
|
||||
import parser.LispParser
|
||||
import sexpression.SExpression
|
||||
import java.io.InputStream
|
||||
|
||||
open class LispInterpreter {
|
||||
|
||||
private lateinit var parser: LispParser
|
||||
|
||||
fun interpretLanguageFiles(languageFiles: List<LanguageFile>) {
|
||||
for (file in languageFiles)
|
||||
LispParser(file.inputStream, file.name).forEach { eval(it) }
|
||||
}
|
||||
|
||||
fun interpret() {
|
||||
parser = LispParser(input!!, inputName!!)
|
||||
prompt()
|
||||
|
||||
while (!parser.isEof()) {
|
||||
evaluateAndPrintNextSExpression()
|
||||
prompt()
|
||||
}
|
||||
|
||||
applyFinishingTouches()
|
||||
}
|
||||
|
||||
protected open fun prompt(): Unit? = null
|
||||
|
||||
protected open fun evaluateAndPrintNextSExpression() = try {
|
||||
printSExpression(eval(parser.nextSExpression()))
|
||||
} catch (e: LispException) {
|
||||
errorManager?.run { handle(e) }
|
||||
}
|
||||
|
||||
protected open fun printSExpression(sExpression: SExpression) = output?.run {
|
||||
println(decorateValueOutput(sExpression.toString()))
|
||||
flush()
|
||||
}
|
||||
|
||||
protected open fun applyFinishingTouches() = output?.run {
|
||||
println()
|
||||
flush()
|
||||
}
|
||||
|
||||
class LanguageFile(val inputStream: InputStream, name: String) {
|
||||
val name: String = "lang:$name"
|
||||
}
|
||||
}
|
|
@ -151,13 +151,10 @@ object LispInterpreterBuilder {
|
|||
|
||||
private fun getInputStream() = if (isFileBased) FileInputStream(inputName) else inputStream
|
||||
|
||||
private fun createInterpreter(): LispInterpreter {
|
||||
if (isFileBased)
|
||||
return FileLispInterpreter()
|
||||
else if (isInteractive)
|
||||
return InteractiveLispInterpreter()
|
||||
|
||||
return LispInterpreter()
|
||||
private fun createInterpreter() = when {
|
||||
isFileBased -> FileLispInterpreter()
|
||||
isInteractive -> InteractiveLispInterpreter()
|
||||
else -> LispInterpreter()
|
||||
}
|
||||
|
||||
class LispFileNotFoundException(val e: FileNotFoundException) : CriticalLispException() {
|
||||
|
|
|
@ -10,13 +10,15 @@ import java.io.InputStream
|
|||
/**
|
||||
* Converts a stream of bytes into internal representations of Lisp s-expressions.
|
||||
*/
|
||||
class LispParser(inputStream: InputStream, fileName: String) {
|
||||
class LispParser(inputStream: InputStream, fileName: String) : AbstractIterator<SExpression>() {
|
||||
|
||||
private val scanner: LispScanner = LispScanner(inputStream, fileName)
|
||||
private var nextToken: Token? = null
|
||||
private var delayedException: LispException? = null
|
||||
private var isNextTokenStored: Boolean = false
|
||||
|
||||
override fun computeNext() = if (isEof()) done() else setNext(nextSExpression())
|
||||
|
||||
fun isEof(): Boolean {
|
||||
if (!isNextTokenStored)
|
||||
storeNextToken()
|
||||
|
@ -32,7 +34,7 @@ class LispParser(inputStream: InputStream, fileName: String) {
|
|||
|
||||
isNextTokenStored = false
|
||||
|
||||
return nextToken!!.parseSExpression({ scanner.nextToken })
|
||||
return nextToken!!.parseSExpression { scanner.nextToken }
|
||||
}
|
||||
|
||||
private fun storeNextToken() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package interpreter
|
||||
|
||||
import environment.RuntimeEnvironment
|
||||
import interpreter.InteractiveLispInterpreter.PROMPT
|
||||
import interpreter.InteractiveLispInterpreter.Companion.PROMPT
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
|
|
|
@ -17,12 +17,10 @@ class LispCommentRemovingInputStreamTest {
|
|||
private fun createLispInputStream(inputString: String) =
|
||||
LispCommentRemovingInputStream(createInputStreamFromString(inputString))
|
||||
|
||||
private fun readInputStreamIntoString(inputStream: LispInputStream) = StringBuilder().let {
|
||||
private fun readInputStreamIntoString(inputStream: LispInputStream) = StringBuilder().apply {
|
||||
for (c in inputStream)
|
||||
it.append(c.toChar())
|
||||
|
||||
it.toString()
|
||||
}
|
||||
append(c.toChar())
|
||||
}.toString()
|
||||
|
||||
@Test
|
||||
fun `no bytes in gives no bytes out`() {
|
||||
|
|
Loading…
Reference in New Issue