-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
125 lines (112 loc) · 3.02 KB
/
errors.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package parser
import (
"fmt"
"github.com/di-wu/parser/op"
"reflect"
"strings"
)
// InitError is an error that occurs on instantiating new structures.
type InitError struct {
// The error message. This should provide an intuitive message or advice on
// how to solve this error.
Message string
}
func (e *InitError) Error() string {
return fmt.Sprintf("parser: %s", e.Message)
}
// ExpectError is an error that occurs on when an invalid/unsupported value is
// passed to the Parser.Expect function.
type ExpectError struct {
Message string
}
func (e *ExpectError) Error() string {
return fmt.Sprintf("expect: %s", e.Message)
}
// ExpectedParseError creates an ExpectedParseError error based on the given
// start and end cursor. Resets the parser tot the start cursor.
func (p *Parser) ExpectedParseError(expected interface{}, start, end *Cursor) *ExpectedParseError {
if end == nil {
end = start
}
defer p.Jump(start)
return &ExpectedParseError{
Expected: expected,
String: p.Slice(start, end),
Conflict: *end,
}
}
// ExpectedParseError indicates that the parser Expected a different value than
// the Actual value present in the buffer.
type ExpectedParseError struct {
// The value that was expected.
Expected interface{}
// The value it actually got.
String string
// The position of the conflicting value.
Conflict Cursor
}
func Stringer(i interface{}) string {
i = ConvertAliases(i)
if reflect.TypeOf(i).Kind() == reflect.Func {
return "func"
}
switch v := i.(type) {
case rune:
return fmt.Sprintf("'%s'", string(v))
case string:
return fmt.Sprintf("%q", v)
case op.Not:
return fmt.Sprintf("!%s", Stringer(v.Value))
case op.Ensure:
return fmt.Sprintf("?%s", Stringer(v.Value))
case op.And:
and := make([]string, len(v))
for i, v := range v {
and[i] = Stringer(v)
}
return fmt.Sprintf("and[%s]", strings.Join(and, " "))
case op.Or:
or := make([]string, len(v))
for i, v := range v {
or[i] = Stringer(v)
}
return fmt.Sprintf("or[%s]", strings.Join(or, " "))
case op.XOr:
xor := make([]string, len(v))
for i, v := range v {
xor[i] = Stringer(v)
}
return fmt.Sprintf("xor[%s]", strings.Join(xor, " "))
case op.Range:
if v.Max == -1 {
switch v.Min {
case 0:
return fmt.Sprintf("%s*", Stringer(v.Value))
case 1:
return fmt.Sprintf("%s+", Stringer(v.Value))
}
}
return fmt.Sprintf("%s{%d:%d}", Stringer(v.Value), v.Min, v.Max)
default:
return fmt.Sprintf("%v", v)
}
}
func (e *ExpectedParseError) Error() string {
got := e.String
if len(e.String) == 1 {
got = fmt.Sprintf("'%s'", string([]rune(e.String)[0]))
} else {
got = fmt.Sprintf("%q", e.String)
}
return fmt.Sprintf(
"parse conflict [%02d:%03d]: expected %T %s but got %s",
e.Conflict.row, e.Conflict.column, e.Expected, Stringer(e.Expected), got,
)
}
// UnsupportedType indicates the type of the value is unsupported.
type UnsupportedType struct {
Value interface{}
}
func (e *UnsupportedType) Error() string {
return fmt.Sprintf("parse: value of type %T are not supported", e.Value)
}