1package ast
2
3import (
4	"bytes"
5	"fmt"
6)
7
8type Node struct {
9	Parent   *Node
10	Children []*Node
11	Value    interface{}
12	Kind     Kind
13}
14
15func NewNode(k Kind, v interface{}, ch ...*Node) *Node {
16	n := &Node{
17		Kind:  k,
18		Value: v,
19	}
20	for _, c := range ch {
21		Insert(n, c)
22	}
23	return n
24}
25
26func (a *Node) Equal(b *Node) bool {
27	if a.Kind != b.Kind {
28		return false
29	}
30	if a.Value != b.Value {
31		return false
32	}
33	if len(a.Children) != len(b.Children) {
34		return false
35	}
36	for i, c := range a.Children {
37		if !c.Equal(b.Children[i]) {
38			return false
39		}
40	}
41	return true
42}
43
44func (a *Node) String() string {
45	var buf bytes.Buffer
46	buf.WriteString(a.Kind.String())
47	if a.Value != nil {
48		buf.WriteString(" =")
49		buf.WriteString(fmt.Sprintf("%v", a.Value))
50	}
51	if len(a.Children) > 0 {
52		buf.WriteString(" [")
53		for i, c := range a.Children {
54			if i > 0 {
55				buf.WriteString(", ")
56			}
57			buf.WriteString(c.String())
58		}
59		buf.WriteString("]")
60	}
61	return buf.String()
62}
63
64func Insert(parent *Node, children ...*Node) {
65	parent.Children = append(parent.Children, children...)
66	for _, ch := range children {
67		ch.Parent = parent
68	}
69}
70
71type List struct {
72	Not   bool
73	Chars string
74}
75
76type Range struct {
77	Not    bool
78	Lo, Hi rune
79}
80
81type Text struct {
82	Text string
83}
84
85type Kind int
86
87const (
88	KindNothing Kind = iota
89	KindPattern
90	KindList
91	KindRange
92	KindText
93	KindAny
94	KindSuper
95	KindSingle
96	KindAnyOf
97)
98
99func (k Kind) String() string {
100	switch k {
101	case KindNothing:
102		return "Nothing"
103	case KindPattern:
104		return "Pattern"
105	case KindList:
106		return "List"
107	case KindRange:
108		return "Range"
109	case KindText:
110		return "Text"
111	case KindAny:
112		return "Any"
113	case KindSuper:
114		return "Super"
115	case KindSingle:
116		return "Single"
117	case KindAnyOf:
118		return "AnyOf"
119	default:
120		return ""
121	}
122}
123