Closed Varriount closed 1 year ago
I poked around to see if I can make a proper implementation of this, but it's not trivial: the symbol table does not from survive compilation to run time, so there is no info available to generate a friendly stack trace at the time of the overflow.
I can make this work, but that will require keeping information around for longer then I'd like. Not sure of that is worth the effort at this time.
Any ideas on this?
Hi @Varriount, I got a reasonable implementation for collecting and dumping a backtraces happening at NPeg parse time; its a available in the backtrace
branch. It doesn't only handle retstack overflows, but any exception that is raised from NPeg, so both NPegException
and any other exceptions as well.
The current implementation runs the parse fucntion in a try
block; if an exception happens it will print the NPeg part of the stack and re-raise the original exception.
Ideally I would like to augment the original Nim stacktrace with the NPeg stackframes instead of just printing the trace, but I'm not sure if the current Nim infrastructure allows for this; NPeg would have to prepend its own backtrace to the Exceptions trace: seq[StackTraceEntry]
fields, but these are not exported and I can't seem to find any other way to modify these. Maybe I should whip up a Nim PR for this.
Example:
import npeg
import std/strutils
import npeg
const parser = peg("nodes", data: seq[string]):
nodes <- *(node * (' ' | !1))
node <- extraWord | word
extraWord <- word * extra * dash
ident <- +Alpha
word <- ident:
data.add($0)
dash <- '-':
data.add($0)
extra <- number | dot
number <- +Digit:
raise newException(IOError, "IO failed")
data.add($0 & "(int)")
dot <- '.':
data.add($0 & "(dot)")
var data: seq[string]
assert parser.match("a b1- c.", data).ok
echo data
Output:
/home/ico/sandbox/prjs/npeg/main.nim(30) main
/home/ico/sandbox/prjs/npeg/main.nim(27) flap
/home/ico/sandbox/prjs/npeg/src/npeg.nim(135) match
/home/ico/sandbox/prjs/npeg/src/npeg/patt.nim(90) fn`gensym46
/home/ico/sandbox/prjs/npeg/src/npeg/patt.nim(90) fn
/home/ico/sandbox/prjs/npeg/main.nim(11) nodes <- *(node * (' ' | !1))
/home/ico/sandbox/prjs/npeg/main.nim(12) node <- extraWord | word
/home/ico/sandbox/prjs/npeg/main.nim(13) extraWord <- word * extra * dash
/home/ico/sandbox/prjs/npeg/main.nim(19) extra <- number | dot
/home/ico/sandbox/prjs/npeg/main.nim(20) number <- +Digit
The last 5 lines show the NPeg part of the stacktrace including the regular lineInfo, with the NPeg rule appended for more clarity.
let's see of https://github.com/nim-lang/Nim/pull/20772 gets through, that will allow NPeg stack frames to go on the native Nim exception stack trace.
For now, enable printing the stack trace with -d:npegStacktrace
When NPeg throws a depth error due to an overflow in the return stack, it would be nice to have the exception contain a printout of the stack.
Something like
Rather than just