38 lines
1.6 KiB
Kotlin
Vendored
38 lines
1.6 KiB
Kotlin
Vendored
//KT-10934 compiler throws UninferredParameterTypeConstructor in when block that covers all types
|
|
|
|
class Parser<TInput, TValue>(val f: (TInput) -> Result<TInput, TValue>) {
|
|
|
|
operator fun invoke(input: TInput): Result<TInput, TValue> = f(input)
|
|
|
|
fun <TIntermediate, TValue2> mapJoin(
|
|
selector: (TValue) -> Parser<TInput, TIntermediate>,
|
|
projector: (TValue, TIntermediate) -> TValue2
|
|
): Parser<TInput, TValue2> {
|
|
return Parser({ input ->
|
|
val res = this(input)
|
|
when (res) {
|
|
is Result.ParseError -> Result.ParseError(res.productionLabel, res.child, res.rest)
|
|
is Result.Value -> {
|
|
val v = res.value
|
|
val res2 = selector(v)(res.rest)
|
|
when (res2) {
|
|
is Result.ParseError -> Result.ParseError(res2.productionLabel, res2.child, res2.rest)
|
|
is Result.Value -> Result.Value(projector(v, res2.value), res2.rest)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/** A parser can return one of two Results */
|
|
sealed class Result<TInput, TValue> {
|
|
|
|
class Value<TInput, TValue>(val value: TValue, val rest: TInput) : Result<TInput, TValue>() {}
|
|
|
|
class ParseError<TInput, TValue>(val productionLabel: String,
|
|
val child: ParseError<TInput, *>?,
|
|
val rest: TInput) : Result<TInput, TValue>() {}
|
|
}
|
|
|
|
fun box() = "OK" |