added LocateError
This commit is contained in:
parent
5173c86ded
commit
a7c195f799
53
errors.go
53
errors.go
@ -1,6 +1,10 @@
|
|||||||
package goparsify
|
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
|
// 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.
|
// 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 {
|
func (e UnparsedInputError) Error() string {
|
||||||
return "left unparsed: " + e.Remaining
|
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())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user