You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
1.7 KiB
122 lines
1.7 KiB
package ast
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
)
|
|
|
|
type Node struct {
|
|
Parent *Node
|
|
Children []*Node
|
|
Value interface{}
|
|
Kind Kind
|
|
}
|
|
|
|
func NewNode(k Kind, v interface{}, ch ...*Node) *Node {
|
|
n := &Node{
|
|
Kind: k,
|
|
Value: v,
|
|
}
|
|
for _, c := range ch {
|
|
Insert(n, c)
|
|
}
|
|
return n
|
|
}
|
|
|
|
func (a *Node) Equal(b *Node) bool {
|
|
if a.Kind != b.Kind {
|
|
return false
|
|
}
|
|
if a.Value != b.Value {
|
|
return false
|
|
}
|
|
if len(a.Children) != len(b.Children) {
|
|
return false
|
|
}
|
|
for i, c := range a.Children {
|
|
if !c.Equal(b.Children[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (a *Node) String() string {
|
|
var buf bytes.Buffer
|
|
buf.WriteString(a.Kind.String())
|
|
if a.Value != nil {
|
|
buf.WriteString(" =")
|
|
buf.WriteString(fmt.Sprintf("%v", a.Value))
|
|
}
|
|
if len(a.Children) > 0 {
|
|
buf.WriteString(" [")
|
|
for i, c := range a.Children {
|
|
if i > 0 {
|
|
buf.WriteString(", ")
|
|
}
|
|
buf.WriteString(c.String())
|
|
}
|
|
buf.WriteString("]")
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func Insert(parent *Node, children ...*Node) {
|
|
parent.Children = append(parent.Children, children...)
|
|
for _, ch := range children {
|
|
ch.Parent = parent
|
|
}
|
|
}
|
|
|
|
type List struct {
|
|
Not bool
|
|
Chars string
|
|
}
|
|
|
|
type Range struct {
|
|
Not bool
|
|
Lo, Hi rune
|
|
}
|
|
|
|
type Text struct {
|
|
Text string
|
|
}
|
|
|
|
type Kind int
|
|
|
|
const (
|
|
KindNothing Kind = iota
|
|
KindPattern
|
|
KindList
|
|
KindRange
|
|
KindText
|
|
KindAny
|
|
KindSuper
|
|
KindSingle
|
|
KindAnyOf
|
|
)
|
|
|
|
func (k Kind) String() string {
|
|
switch k {
|
|
case KindNothing:
|
|
return "Nothing"
|
|
case KindPattern:
|
|
return "Pattern"
|
|
case KindList:
|
|
return "List"
|
|
case KindRange:
|
|
return "Range"
|
|
case KindText:
|
|
return "Text"
|
|
case KindAny:
|
|
return "Any"
|
|
case KindSuper:
|
|
return "Super"
|
|
case KindSingle:
|
|
return "Single"
|
|
case KindAnyOf:
|
|
return "AnyOf"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|