-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser_choice.go
90 lines (81 loc) · 1.88 KB
/
parser_choice.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
package joeson
import (
"strings"
)
type choice struct {
*Attr
*rule
choices []Parser
}
func newEmptyChoice() *choice {
ch := &choice{newAttr(), newRule(), []Parser{}}
ch.rule.node = ch
return ch
}
func newChoice(it Ast) *choice {
if a, ok := it.(*NativeArray); ok {
var parsers []Parser
for _, ast := range *a {
parsers = append(parsers, ast.(Parser))
}
ch := &choice{
newAttr(),
newRule(),
parsers,
}
ch.rule.node = ch
return ch
} else {
panic("Choice expects a NativeArray")
}
}
func (ch *choice) isMonoChoice() bool { return len(ch.choices) == 1 }
func (ch *choice) Append(node Parser) { ch.choices = append(ch.choices, node) }
func (ch *choice) getRule() *rule { return ch.rule }
func (ch *choice) handlesChildLabel() bool { return false }
func (ch *choice) prepare() {
for _, choice := range ch.choices {
if !choice.getRule().capture {
ch.getRule().capture = false
return
}
}
ch.getRule().capture = true
}
func (ch *choice) parse(ctx *ParseContext) Ast {
return wrap(func(_ *ParseContext, _ Parser) Ast {
for _, choice := range ch.choices {
pos := ctx.Code.Pos()
result := choice.parse(ctx)
if result == nil {
ctx.Code.SetPos(pos)
} else {
return result
}
}
return nil
}, ch)(ctx)
}
func (ch *choice) String() string {
var b strings.Builder
b.WriteString(Blue("("))
first := true
for _, x := range ch.choices {
if !first {
b.WriteString(Blue(" | "))
}
b.WriteString(String(x))
first = false
}
b.WriteString(Blue(")"))
return b.String()
}
func (ch *choice) forEachChild(f func(Parser) Parser) Parser {
// @defineChildren
// rules: {type:{key:undefined,value:{type:GNode}}}
// choices: {type:[type:GNode]}
// we must first walk through rules, and then only through choices
ch.rules = ForEachChildInRules(ch, f)
ch.choices = ForEachChild_Array(ch.choices, f)
return ch
}