task processor, add locations to parser combinator

This commit is contained in:
alexander.nutz
2024-04-03 07:17:27 +02:00
parent 56546094c5
commit 25086a3c7e
2 changed files with 86 additions and 12 deletions

View File

@@ -0,0 +1,70 @@
package blitz.async
import blitz.collections.SynchronizedList
import blitz.logic.then
abstract class Processor {
protected val tasks = SynchronizedList(mutableListOf<Task>())
fun tick() {
for (task in tasks) {
if (task.counter >= task.priority) {
task.fn()
task.counter = 0
} else {
task.counter ++
}
}
}
abstract fun add(task: Task)
abstract fun remove(task: Task)
/** priority 0 means every tick; 1 means every second tick; 2 means every third tick, ... */
data class Task(
internal val priority: Int = 0, // every tick
internal val fn: () -> Unit
) {
internal var counter: Int = 0
}
companion object {
fun singleThread(): Processor =
SingleThreadProcessor()
fun manualTick(): Processor =
object : Processor() {
override fun add(task: Task) {
tasks.add(task)
}
override fun remove(task: Task) {
tasks.remove(task)
}
}
}
}
internal class SingleThreadProcessor: Processor() {
private fun createThread() = Thread { while (true) { tick() } }
private var thread: Thread? = null
override fun add(task: Task) {
tasks.add(task)
if (thread == null) {
thread = createThread()
thread!!.start()
}
}
override fun remove(task: Task) {
tasks.remove(task)
tasks.isEmpty().then {
runCatching { thread?.interrupt() }
thread = null
}
}
}

View File

@@ -1,11 +1,10 @@
package blitz.parse.comb package blitz.parse.comb
import blitz.str.collectToString import blitz.str.collectToString
import kotlin.math.max
@JvmInline data class Parsable(
value class Parsable( val str: String,
val str: String val loc: Int? = null
) )
typealias Parser<T> = (Parsable) -> Pair<Parsable, T>? typealias Parser<T> = (Parsable) -> Pair<Parsable, T>?
@@ -26,21 +25,24 @@ infix fun <T> Parser<T>.or(other: Parser<T>): Parser<T> = {
} }
fun Parsable.spaces(): Parsable { fun Parsable.spaces(): Parsable {
return Parsable(str.trimStart(' ')) val new = str.trimStart(' ')
return Parsable(new, loc?.let { it + str.length - new.length })
} }
fun Parsable.whitespaces(): Parsable { fun Parsable.whitespaces(): Parsable {
return Parsable(str.trimStart()) val new = str.trimStart()
return Parsable(new, loc?.let { it + str.length - new.length })
} }
fun Parsable.require(what: String): Parsable? { fun Parsable.require(what: String): Parsable? {
if (str.startsWith(what)) if (str.startsWith(what))
return Parsable(str.substring(what.length)) return Parsable(str.substring(what.length), loc?.let { it + what.length })
return null return null
} }
fun <T> Parsable.untilRequire(c: String, map: (String) -> T?): Pair<Parsable, T>? { fun <T> Parsable.untilRequire(c: String, map: (String) -> T?): Pair<Parsable, T>? {
return map(str.substringBefore(c))?.let { Parsable(str.substringAfter(c)) to it } val before = str.substringBefore(c)
return map(before)?.let { Parsable(str.substringAfter(c), loc?.let { it + before.length }) to it }
} }
fun <T> Parsable.asLongAs(vararg li: Char, map: (String) -> T?): Pair<Parsable, T>? { fun <T> Parsable.asLongAs(vararg li: Char, map: (String) -> T?): Pair<Parsable, T>? {
@@ -52,7 +54,7 @@ fun <T> Parsable.asLongAs(vararg li: Char, map: (String) -> T?): Pair<Parsable,
break break
} }
val out = str.substring(o.size) val out = str.substring(o.size)
return map(o.iterator().collectToString())?.let { Parsable(out) to it } return map(o.iterator().collectToString())?.let { Parsable(out, loc?.plus(o.size)) to it }
} }
fun <T> Parsable.map(parser: Parser<T>): Pair<Parsable, T>? = fun <T> Parsable.map(parser: Parser<T>): Pair<Parsable, T>? =
@@ -89,17 +91,19 @@ fun <T> Pair<Parsable, T>.require(what: String): Pair<Parsable, T>? =
fun <T> Parsable.array(sep: String, map: (Parsable) -> Pair<Parsable, T>?): Pair<Parsable, List<T>> { fun <T> Parsable.array(sep: String, map: (Parsable) -> Pair<Parsable, T>?): Pair<Parsable, List<T>> {
val out = mutableListOf<T>() val out = mutableListOf<T>()
var loc = loc
var curr = str var curr = str
fun step() = fun step() =
map(Parsable(curr))?.also { map(Parsable(curr, loc))?.also {
curr = it.first.str curr = it.first.str
loc = it.first.loc
} }
while (true) { while (true) {
val r = step() ?: break val r = step() ?: break
out.add(r.second) out.add(r.second)
curr = (Parsable(curr).require(sep) ?: break).str curr = (Parsable(curr, loc).require(sep) ?: break).str
} }
return Parsable(curr) to out return Parsable(curr, loc) to out
} }