import kotlin.text.*
class ParseException: Exception("A parse exception has occurred")
class Context<E>(private val list: List<E>) {
companion object {
fun fromString(string: String): Context<Char> = Context<Char>(string.toList())
}
var index: Int = 0
val next: E get() = list.elementAtOrNull(index) ?: throw ParseException()
val atEnd: Boolean get() = index >= list.size
infix fun <T> parse(parser: Parser<E, T>): T = parser(this)
}
typealias Parser<E, T> = Context<E>.() -> T
typealias ParserS = Context<Char>.() -> String
typealias Transform<I, O> = (I) -> O
infix fun <E, T1, T2> Transform<T1, T2>.lift(parser: Parser<E, T1>): Parser<E, T2> {
val transform = this
return { transform(parser(this)) }
}
fun <E> eof(): Parser<E, Unit> = { if (!this.atEnd) throw ParseException() }
fun <E> satisfy(test: (E) -> Boolean): Parser<E, E> = {
val elem = next
if (test(elem)) {
index += 1
elem
} else {
throw ParseException()
}
}
fun char(test: (Char) -> Boolean): ParserS {
val check = satisfy(test)
return { check(this).toString() }
}
fun char(c: Char): ParserS = char { it == c }
operator fun ParserS.plus(parser2: ParserS): ParserS {
val parser1 = this
return {
val s1 = parser1(this)
val s2 = parser2(this)
s1 + s2
}
}
infix fun <E, T> Parser<E, T>.or(parser2: Parser<E, T>): Parser<E, T> {
val parser1 = this
return {
try {
parser1(this)
} catch(e: ParseException) {
parser2(this)
}
}
}
fun <E, T> count(from: Int, to: Int, parser: Parser<E, T>): Parser<E, List<T>> = {
val results: MutableList<T> = mutableListOf()
while (results.size < from) {
results.add(parser(this))
}
while (results.size < to) {
try {
results.add(parser(this))
} catch (e: ParseException) {
break
}
}
results
}
fun join(strings: List<String>): String = strings.joinToString(separator = "")
fun <E, T> count(range: IntRange, parser: Parser<E, T>): Parser<E, List<T>> = count(range.start, range.endInclusive, parser)
fun <E, T> count(to: Int, parser: Parser<E, T>): Parser<E, List<T>> = count(to, to, parser)
fun <E, T> atLeast(from: Int, parser: Parser<E, T>): Parser<E, List<T>> = count(from, Int.MAX_VALUE, parser)
fun <E, T> many1(parser: Parser<E, T>): Parser<E, List<T>> = atLeast(1, parser)
fun <E, T> many(parser: Parser<E, T>): Parser<E, List<T>> = atLeast(0, parser)
fun countS(from: Int, to: Int, parser: ParserS): ParserS = ::join lift count(from, to, parser)
fun manyS(parser: ParserS): ParserS = ::join lift many(parser)
fun many1S(parser: ParserS): ParserS = ::join lift atLeast(1, parser)
infix fun <E, T1, T2> Parser<E, T1>.followedBy(parser2: Parser<E, T2>): Parser<E, T1> {
val parser1 = this
return {
val result = this parse parser1
this parse parser2
result
}
}
Comments
0 B
|👍
/👎
0 B
|👍
/👎