Convert the interpreter to kotlin
This commit is contained in:
parent
d376c30d7a
commit
eaf80390be
|
@ -1,7 +1,6 @@
|
||||||
package function
|
package function
|
||||||
|
|
||||||
import java.lang.annotation.Retention
|
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||||
import java.lang.annotation.RetentionPolicy.RUNTIME
|
|
||||||
import kotlin.annotation.AnnotationTarget.CLASS
|
import kotlin.annotation.AnnotationTarget.CLASS
|
||||||
import kotlin.annotation.AnnotationTarget.FILE
|
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 getInputStream() = if (isFileBased) FileInputStream(inputName) else inputStream
|
||||||
|
|
||||||
private fun createInterpreter(): LispInterpreter {
|
private fun createInterpreter() = when {
|
||||||
if (isFileBased)
|
isFileBased -> FileLispInterpreter()
|
||||||
return FileLispInterpreter()
|
isInteractive -> InteractiveLispInterpreter()
|
||||||
else if (isInteractive)
|
else -> LispInterpreter()
|
||||||
return InteractiveLispInterpreter()
|
|
||||||
|
|
||||||
return LispInterpreter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LispFileNotFoundException(val e: FileNotFoundException) : CriticalLispException() {
|
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.
|
* 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 val scanner: LispScanner = LispScanner(inputStream, fileName)
|
||||||
private var nextToken: Token? = null
|
private var nextToken: Token? = null
|
||||||
private var delayedException: LispException? = null
|
private var delayedException: LispException? = null
|
||||||
private var isNextTokenStored: Boolean = false
|
private var isNextTokenStored: Boolean = false
|
||||||
|
|
||||||
|
override fun computeNext() = if (isEof()) done() else setNext(nextSExpression())
|
||||||
|
|
||||||
fun isEof(): Boolean {
|
fun isEof(): Boolean {
|
||||||
if (!isNextTokenStored)
|
if (!isNextTokenStored)
|
||||||
storeNextToken()
|
storeNextToken()
|
||||||
|
@ -32,7 +34,7 @@ class LispParser(inputStream: InputStream, fileName: String) {
|
||||||
|
|
||||||
isNextTokenStored = false
|
isNextTokenStored = false
|
||||||
|
|
||||||
return nextToken!!.parseSExpression({ scanner.nextToken })
|
return nextToken!!.parseSExpression { scanner.nextToken }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeNextToken() {
|
private fun storeNextToken() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package interpreter
|
package interpreter
|
||||||
|
|
||||||
import environment.RuntimeEnvironment
|
import environment.RuntimeEnvironment
|
||||||
import interpreter.InteractiveLispInterpreter.PROMPT
|
import interpreter.InteractiveLispInterpreter.Companion.PROMPT
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
|
|
|
@ -17,12 +17,10 @@ class LispCommentRemovingInputStreamTest {
|
||||||
private fun createLispInputStream(inputString: String) =
|
private fun createLispInputStream(inputString: String) =
|
||||||
LispCommentRemovingInputStream(createInputStreamFromString(inputString))
|
LispCommentRemovingInputStream(createInputStreamFromString(inputString))
|
||||||
|
|
||||||
private fun readInputStreamIntoString(inputStream: LispInputStream) = StringBuilder().let {
|
private fun readInputStreamIntoString(inputStream: LispInputStream) = StringBuilder().apply {
|
||||||
for (c in inputStream)
|
for (c in inputStream)
|
||||||
it.append(c.toChar())
|
append(c.toChar())
|
||||||
|
}.toString()
|
||||||
it.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `no bytes in gives no bytes out`() {
|
fun `no bytes in gives no bytes out`() {
|
||||||
|
|
Loading…
Reference in New Issue