commonMain.tel.schich.parserkombinator.Tracing.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of parser-kombinator Show documentation
Show all versions of parser-kombinator Show documentation
A simple parser combinator framework.
package tel.schich.parserkombinator
import kotlin.jvm.JvmName
expect fun isTracingEnabled(): Boolean
private var suppressTraces = false
private var traceDepth = 0
@JvmName("forTraceChars")
fun forTrace(chars: Set): String =
chars.joinToString(prefix = "{", separator = ", ", postfix = "}") { forTrace(it) }
@JvmName("forTraceStrings")
fun forTrace(strings: Set): String =
strings.joinToString(prefix = "{", separator = ", ", postfix = "}") { forTrace(it, "\"") }
fun forTrace(c: Char): String = "'${forTrace("$c", "'")}'"
fun forTrace(c: String): String = "\"${forTrace(c, "\"")}\""
fun forTrace(s: CharSequence, quote: String) = forTrace(s).replace(quote, "\\$quote")
fun forTrace(s: CharSequence) = s.toString()
.replace("\\", "\\\\")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t")
fun trace(msg: String, parser: Parser): Parser = trace(msg, shallow = false, parser)
fun trace(msg: String, shallow: Boolean, parser: Parser): Parser {
// disappear from parser call stacks
if (!isTracingEnabled()) {
return parser
}
return { input ->
if (suppressTraces) {
parser(input)
} else {
val depth = traceDepth
traceDepth += 1
val prefix = "|\t".repeat(depth) + ">"
println("$prefix $msg")
suppressTraces = shallow
val result = parser(input)
suppressTraces = false
traceDepth -= 1
when (result) {
is ParserResult.Ok -> {
val len = input.length - result.rest.length
val content = input.string.substring(input.offset, input.offset + len)
println("$prefix ✓ (len=$len, content=\"${ forTrace(content, "\"")}\")")
}
is ParserResult.Error -> {
println("$prefix ! ${forTrace(result.message)}")
}
}
result
}
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun Parser.traced(msg: String, shallow: Boolean = false): Parser = trace(msg, shallow, this)