Initial commit

This commit is contained in:
Chad Retz 2017-03-02 16:23:08 -06:00
commit 87b866c600
5 changed files with 111 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/gradlew
/gradlew.bat
/.gradle
/.idea
/build
/gradle

25
build.gradle Normal file
View File

@ -0,0 +1,25 @@
group 'asmble'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.0'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'java'
apply plugin: 'kotlin'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
testCompile group: 'junit', name: 'junit', version: '4.11'
}

2
settings.gradle Normal file
View File

@ -0,0 +1,2 @@
rootProject.name = 'asmble'

View File

@ -0,0 +1,72 @@
package asmble.ast
import asmble.util.Either
sealed class SExpr {
data class Multi(val vals: List<SExpr> = emptyList()) : SExpr()
data class Symbol(val contents: String = "", val quoted: Boolean = false) : SExpr()
companion object {
data class ParseError(val charOffset: Int, val msg: String)
fun parse(str: CharSequence): Either<Multi, ParseError> {
val state = ParseState(str)
var ret = emptyList<SExpr>()
while (!state.isEof) {
ret += state.nextSExpr()
if (state.err != null) return Either.Right(ParseError(state.offset, state.err!!))
}
if (ret.size == 1 && ret[0] is Multi) return Either.Left(ret[0] as Multi)
else return Either.Left(Multi(ret))
}
private class ParseState(val str: CharSequence, var offset: Int = 0, var err: String? = null) {
fun nextSExpr(): SExpr {
skipWhitespace()
if (isEof) return Multi()
// What type of expr do we have here?
when (str[offset]) {
'(' -> {
offset++
var ret = Multi()
while (err == null && !isEof && str[offset] != ')') {
ret = ret.copy(ret.vals + nextSExpr())
}
if (err == null) {
if (str[offset] == ')') offset++ else err = "EOF when expected ')'"
}
return ret
}
'"' -> {
offset++
// Anything can be escaped (for now)
var retStr = ""
while (!isEof && str[offset] != '"') {
if (str[offset] == '\\') {
++offset
if (isEof) {
err = "EOF when expected char to unescape"
break
}
}
retStr += str[offset]
offset++
}
if (err == null && str[offset] != '"') err = "EOF when expected '\"'"
return Symbol(retStr, true)
}
else -> {
// Go until next quote or whitespace or parens
val origOffset = offset
while (!isEof && str[offset] != '(' && str[offset] != ')' &&
str[offset] != '"' && !str[offset].isWhitespace()) offset++
return Symbol(str.substring(origOffset, offset))
}
}
}
fun skipWhitespace() { while (!isEof && str[offset].isWhitespace()) offset++ }
val isEof: Boolean inline get() = offset >= str.length
}
}
}

View File

@ -0,0 +1,6 @@
package asmble.util
sealed class Either<out L, out R> {
data class Left<out T>(val v: T) : Either<T, Nothing>()
data class Right<out T>(val v: T) : Either<Nothing, T>()
}