-
Notifications
You must be signed in to change notification settings - Fork 10
/
parse_error_helper.go
77 lines (69 loc) · 2.28 KB
/
parse_error_helper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package config
import (
"bytes"
"fmt"
"strings"
)
type errPos struct {
msg string
c current
pos int
}
var farthestFailure []errPos
// GetFarthestFailure returns the farthest position where the parser had a parse error.
// The farthest position is normally close to the real source for the error.
func GetFarthestFailure() (string, bool) {
if len(farthestFailure) > 0 {
var bb bytes.Buffer
bb.WriteString(fmt.Sprintf("Parsing error at pos %s and [%d] (after: '%s'):\n", farthestFailure[0].c.pos, farthestFailure[0].pos, showNewline(string(farthestFailure[0].c.text))))
for _, e := range farthestFailure {
bb.WriteString(fmt.Sprintf("-> %s\n", e.msg))
}
return bb.String(), true
}
return "", false
}
func showNewline(str string) string {
str = strings.ReplaceAll(str, "\n", "\\n")
return str
}
func pos(c *current) int {
return c.pos.offset + len(c.text)
}
// pushError is used to add potential error states to the farthestFailure slice.
// This function should be used, if there are multiple paths to be considered.
// These potential error states are a valuable source for the error message, if
// the parsing fails.
// The assumption is, that the longest successful parse tree is the most acurate.
func (c *current) pushError(errorMsg string) (bool, error) {
pos := pos(c)
if len(farthestFailure) == 0 || pos > farthestFailure[0].pos {
farthestFailure = []errPos{{msg: errorMsg, c: *c, pos: pos}}
} else {
if pos == farthestFailure[0].pos {
for _, failure := range farthestFailure {
if failure.msg == errorMsg {
return false, nil
}
}
farthestFailure = append(farthestFailure, errPos{msg: errorMsg, c: *c, pos: pos})
}
}
return false, nil
}
// fatalError is used to abort the parsing immediately due to an unrecoverable parse error.
// In most cases this is a missing closing character of a pair, which was opened before.
// Example: a missing closing square bracket or a missing closing double quote.
func (c *current) fatalError(errorMsg string) (bool, error) {
farthestFailure = []errPos{
{
msg: errorMsg,
c: *c,
pos: pos(c),
},
}
var bb bytes.Buffer
bb.WriteString(fmt.Sprintf("Parsing error at pos %s and [%d] (after: '%s'):\n", c.pos, pos(c), showNewline(string(c.text))))
bb.WriteString(fmt.Sprintf("-> %s\n", errorMsg))
panic(bb.String())
}