-
-
Notifications
You must be signed in to change notification settings - Fork 187
/
context.go
109 lines (96 loc) · 2.82 KB
/
context.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
package participle
import (
"reflect"
"github.com/alecthomas/participle/v2/lexer"
)
type contextFieldSet struct {
tokens []lexer.Token
strct reflect.Value
field structLexerField
fieldValue []reflect.Value
}
// Context for a single parse.
type parseContext struct {
*lexer.PeekingLexer
deepestError error
deepestErrorDepth int
lookahead int
caseInsensitive map[rune]bool
apply []*contextFieldSet
allowTrailing bool
}
func newParseContext(lex *lexer.PeekingLexer, lookahead int, caseInsensitive map[rune]bool) *parseContext {
return &parseContext{
PeekingLexer: lex,
caseInsensitive: caseInsensitive,
lookahead: lookahead,
}
}
func (p *parseContext) DeepestError(err error) error {
if p.PeekingLexer.Cursor() >= p.deepestErrorDepth {
return err
}
if p.deepestError != nil {
return p.deepestError
}
return err
}
// Defer adds a function to be applied once a branch has been picked.
func (p *parseContext) Defer(tokens []lexer.Token, strct reflect.Value, field structLexerField, fieldValue []reflect.Value) {
p.apply = append(p.apply, &contextFieldSet{tokens, strct, field, fieldValue})
}
// Apply deferred functions.
func (p *parseContext) Apply() error {
for _, apply := range p.apply {
if err := setField(apply.tokens, apply.strct, apply.field, apply.fieldValue); err != nil {
return err
}
}
p.apply = nil
return nil
}
// Branch accepts the branch as the correct branch.
func (p *parseContext) Accept(branch *parseContext) {
p.apply = append(p.apply, branch.apply...)
p.PeekingLexer = branch.PeekingLexer
if branch.deepestErrorDepth >= p.deepestErrorDepth {
p.deepestErrorDepth = branch.deepestErrorDepth
p.deepestError = branch.deepestError
}
}
// Branch starts a new lookahead branch.
func (p *parseContext) Branch() *parseContext {
branch := &parseContext{}
*branch = *p
branch.apply = nil
branch.PeekingLexer = p.PeekingLexer.Clone()
return branch
}
func (p *parseContext) MaybeUpdateError(err error) {
if p.PeekingLexer.Cursor() >= p.deepestErrorDepth {
p.deepestError = err
p.deepestErrorDepth = p.PeekingLexer.Cursor()
}
}
// Stop returns true if parsing should terminate after the given "branch" failed to match.
//
// Additionally, "err" should be the branch error, if any. This will be tracked to
// aid in error reporting under the assumption that the deepest occurring error is more
// useful than errors further up.
func (p *parseContext) Stop(err error, branch *parseContext) bool {
if branch.PeekingLexer.Cursor() >= p.deepestErrorDepth {
p.deepestError = err
p.deepestErrorDepth = maxInt(branch.PeekingLexer.Cursor(), branch.deepestErrorDepth)
}
if branch.PeekingLexer.Cursor() > p.PeekingLexer.Cursor()+p.lookahead {
p.Accept(branch)
return true
}
return false
}
func maxInt(a, b int) int {
if a > b {
return a
}
return b
}