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 fmt.Sprintf("%s at %s", err.Message, 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) }