54 lines
1.4 KiB
Go
54 lines
1.4 KiB
Go
package parsekit
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
// Error is used as the error type when parsing errors occur.
|
|
// The error includes some context information to allow for useful
|
|
// error messages to the user.
|
|
type Error struct {
|
|
Message string
|
|
Cursor Cursor
|
|
}
|
|
|
|
func (err *Error) Error() string {
|
|
if err == nil {
|
|
callerPanic(1, "parsekit.Error.Error(): method called with nil error at {caller}")
|
|
}
|
|
return err.Message
|
|
}
|
|
|
|
// Full returns the current error message, including information about
|
|
// the position in the input where the error occurred.
|
|
func (err *Error) Full() string {
|
|
if err == nil {
|
|
callerPanic(1, "parsekit.Error.Full(): method called with nil error at {caller}")
|
|
}
|
|
return fmt.Sprintf("%s at %s", err, err.Cursor)
|
|
}
|
|
|
|
func callerFunc(depth int) string {
|
|
// No error handling, because we call this method ourselves with safe depth values.
|
|
pc, _, _, _ := runtime.Caller(depth + 1)
|
|
caller := runtime.FuncForPC(pc)
|
|
parts := strings.Split(caller.Name(), ".")
|
|
funcName := parts[len(parts)-1]
|
|
return funcName
|
|
}
|
|
|
|
func callerFilepos(depth int) string {
|
|
// No error handling, because we call this method ourselves with safe depth values.
|
|
_, file, line, _ := runtime.Caller(depth + 1)
|
|
return fmt.Sprintf("%s:%d", file, line)
|
|
}
|
|
|
|
func callerPanic(depth int, f string, args ...interface{}) {
|
|
filepos := callerFilepos(depth + 1)
|
|
m := fmt.Sprintf(f, args...)
|
|
m = strings.Replace(m, "{caller}", filepos, 1)
|
|
panic(m)
|
|
}
|