summaryrefslogtreecommitdiff
path: root/errors.go
diff options
context:
space:
mode:
authorÖzgür Kesim <oec@codeblau.de>2019-11-29 06:49:16 +0100
committerÖzgür Kesim <oec@codeblau.de>2019-11-29 06:49:16 +0100
commita7c195f79968b20cc7cf7b3a9f9fbb22459cb348 (patch)
treee539b51fbaad7070d9440e1abe9ae02e3796807c /errors.go
parent5173c86ded407b4990903e275be1f286345006ec (diff)
added LocateError
Diffstat (limited to 'errors.go')
-rw-r--r--errors.go53
1 files changed, 52 insertions, 1 deletions
diff --git a/errors.go b/errors.go
index e684e14..07f6565 100644
--- a/errors.go
+++ b/errors.go
@@ -1,6 +1,10 @@
package goparsify
-import "fmt"
+import (
+ "bufio"
+ "fmt"
+ "strings"
+)
// Error represents a parse error. These will often be set, the parser will back up a little and
// find another viable path. In general when combining errors the longest error should be returned.
@@ -24,3 +28,50 @@ type UnparsedInputError struct {
func (e UnparsedInputError) Error() string {
return "left unparsed: " + e.Remaining
}
+
+// LocalError locates the error position in the input string s and returns the
+// error description along with a cursor to the input.
+func (e *Error) LocateError(s string) string {
+ if len(s) < e.Pos() {
+ return e.Error()
+ }
+
+ pos := e.Pos()
+
+ // find the line.
+ var (
+ lino, prev, off int
+ line, indent []byte
+ )
+ byline := bufio.NewScanner(strings.NewReader(s))
+ for byline.Scan() {
+ lino++
+ line = byline.Bytes()
+ prev = off
+ off += len(line) + 1
+ // log.Printf("lino:%3d len:%4d prev:%4d pos:%4d off:%4d rel:%4d line: %s",
+ // lino, len(line), prev, pos, off, (pos - prev), string(line))
+ if prev <= pos && pos <= off {
+ break
+ }
+ }
+ indent = make([]byte, len(line[:pos-prev]))
+ for i, c := range indent {
+ if c != '\t' {
+ indent[i] = ' '
+ }
+ }
+ off = pos - prev
+ if off > 40 {
+ indent = indent[off-30:]
+ line = line[off-30:]
+ line[0] = '.'
+ line[1] = '.'
+ line[2] = '.'
+ }
+ if len(line) > 70 {
+ line = line[:70]
+ line[69], line[68], line[67] = '.', '.', '.'
+ }
+ return fmt.Sprintf("Parsing error in line %d:\n%s\n%s^\n%v\n", lino, string(line), string(indent), e.Error())
+}