forked from alecthomas/participle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstringer.go
92 lines (78 loc) · 1.68 KB
/
stringer.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
package participle
import (
"bytes"
"fmt"
"strings"
"github.com/alecthomas/participle/lexer"
)
type stringerVisitor struct {
bytes.Buffer
seen map[node]bool
}
func stringer(n node) string {
v := &stringerVisitor{seen: map[node]bool{}}
v.visit(n, 1, false)
return v.String()
}
func (s *stringerVisitor) visit(n node, depth int, disjunctions bool) {
if s.seen[n] || depth <= 0 {
fmt.Fprintf(s, "...")
return
}
s.seen[n] = true
switch n := n.(type) {
case *disjunction:
if disjunctions {
fmt.Fprintf(s, "(")
}
for i, c := range n.nodes {
if i > 0 {
fmt.Fprint(s, " | ")
}
s.visit(c, depth, disjunctions || len(n.nodes) > 1)
}
if disjunctions {
fmt.Fprintf(s, ")")
}
case *strct:
s.visit(n.expr, depth, disjunctions)
case *sequence:
for c, i := n, 0; c != nil && depth-i > 0; c, i = c.next, i+1 {
if c != n {
fmt.Fprint(s, " ")
}
s.visit(c.node, depth-i, disjunctions)
}
case *parseable:
fmt.Fprint(s, n.t.Name())
case *capture:
if _, ok := n.node.(*parseable); ok {
fmt.Fprint(s, n.field.Name)
} else {
if n.node == nil {
fmt.Fprintf(s, "<%s>", strings.ToLower(n.field.Name))
} else {
s.visit(n.node, depth, disjunctions)
}
}
case *reference:
fmt.Fprintf(s, "<%s>", strings.ToLower(n.identifier))
case *optional:
fmt.Fprint(s, "[ ")
s.visit(n.node, depth, disjunctions)
fmt.Fprint(s, " ]")
if n.next != nil {
fmt.Fprint(s, " ")
s.visit(n.next, depth, disjunctions)
}
case *repetition:
fmt.Fprint(s, "( ")
s.visit(n.node, depth, disjunctions)
fmt.Fprint(s, " )")
case *literal:
fmt.Fprintf(s, "%q", n.s)
if n.t != lexer.EOF && n.s == "" {
fmt.Fprintf(s, ":%s", n.tt)
}
}
}