-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add log
helper for parser debugging
#104
Comments
I just spent 9 hours on an airplane debugging parboiled2 parsers (Trying to parse Scala source), here's what I came up with: run(println("Hello Before!")) ~ (...) ~ run(println("Hello After!"))
capture(...) ~> ((x: String) => println("Hello! " + x)) Short forms for these two would be very nice. It would be great if we could define them ourselves (meta-rules?) because the way I debug things varies depending on what's going wrong. FWIW, the
Being able to log as well as scala-parser-combinators would be really nice. That means being able to do
There's a lot of possible configurations you'd want to set up your logger to do, because the amount of verbosity that you have to cut through varies greatly depending on what you're doing. I don't think a one-size-fits-all solution would work And of course using |
Ok, thanks!
// print log message before trying another another rule
def log(marker: String) = rule {
@tailrec
def position(i: Int = 0, line: Int = 1, col: Int = 1): Position =
if (i >= cursor) Position(index, line, col)
else if (i >= input.length || input.charAt(i) != '\n') position(i + 1, line, col + 1)
else position(i + 1, line + 1, 1)
val Position(_, line, col) = position(cursor)
println(s"$marker at pos $cursor (line $line, col $col)")
println((input getLine line) + '\n' + (" " * (col - 1) + '^'))
}
If def logFailing[I <: HList, O <: HList](marker: String)(rule: => Rule[I, O]): Rule[I, O] =
rule | log(marker) If this doesn't compile yet (haven't tried) we should make it work. The parser will instantiate a function instance every time it comes across a The "indication why it failed" is harder to do. Ideally you'd want something like a local error reporting, that gives you all the error traces underneath the wrapped rule. That's solvable and certainly valuable.
That's easy to write right now. Just write a rule that prints the top value stack element. (e.g. using
The parser runs as regular method invocations, as such you can get an indication of how deep you are in the grammar by simply looking at the current JVM stack depth. val stackTrace = Thread.currentThread().getStackTrace
val ruleDepth = stackTrace.length - stackTrace.indexWhere(_.getMethodName contains "runRule") |
In general, I couldn't get anything like this rule: => Rule[I, O] to work in the general case; only when the things I was passing in were trivial (e.g. a single named parser). It would be great if it would work in the general case where e.g. you have |
I don't think there is a general reason why call-by-name rule passing shouldn't work. |
Sure lemme try getting a minimal repro On Thu, Dec 4, 2014 at 11:49 PM, Mathias [email protected] wrote:
|
Done #116 |
Great! Thanks! |
For what it's worth: @tailrec
private def position(i: Int = 0, line: Int = 1, col: Int = 1): Position =
if (i >= cursor) Position(i, line, col)
else if (i >= input.length || input.charAt(i) != '\n') position(i + 1, line, col + 1)
else position(i + 1, line + 1, 1)
def log(marker: String) = rule {
atomic("") ~> (() => {
val Position(_, line, col) = position(0)
println(s"$marker at pos $cursor (line $line, col $col)")
println((input getLine line) + '\n' + (" " * (col - 1) + '^'));
})
}
|
run(println("marker"))
works but we can do better.Related to #105.
The text was updated successfully, but these errors were encountered: