Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement