-
Notifications
You must be signed in to change notification settings - Fork 16
/
trees.go
142 lines (121 loc) · 3.6 KB
/
trees.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
package antlr
import "fmt"
/** A set of utility routines useful for all kinds of ANTLR trees. */
// TreesStringTree prints out a whole tree in LISP form. [getNodeText] is used on the
// node payloads to get the text for the nodes. Detects parse trees and extracts data appropriately.
func TreesStringTree(tree Tree, ruleNames []string, recog Recognizer) string {
if recog != nil {
ruleNames = recog.GetRuleNames()
}
s := TreesGetNodeText(tree, ruleNames, nil)
s = EscapeWhitespace(s, false)
c := tree.GetChildCount()
if c == 0 {
return s
}
res := "(" + s + " "
if c > 0 {
s = TreesStringTree(tree.GetChild(0), ruleNames, nil)
res += s
}
for i := 1; i < c; i++ {
s = TreesStringTree(tree.GetChild(i), ruleNames, nil)
res += " " + s
}
res += ")"
return res
}
func TreesGetNodeText(t Tree, ruleNames []string, recog Parser) string {
if recog != nil {
ruleNames = recog.GetRuleNames()
}
if ruleNames != nil {
switch t2 := t.(type) {
case RuleNode:
t3 := t2.GetRuleContext()
altNumber := t3.GetAltNumber()
if altNumber != ATNInvalidAltNumber {
return fmt.Sprintf("%s:%d", ruleNames[t3.GetRuleIndex()], altNumber)
}
return ruleNames[t3.GetRuleIndex()]
case ErrorNode:
return fmt.Sprint(t2)
case TerminalNode:
if t2.GetSymbol() != nil {
return t2.GetSymbol().GetText()
}
}
}
// no recognition for rule names
payload := t.GetPayload()
if p2, ok := payload.(Token); ok {
return p2.GetText()
}
return fmt.Sprint(t.GetPayload())
}
// TreesGetChildren returns am ordered list of all children of this node
//
//goland:noinspection GoUnusedExportedFunction
func TreesGetChildren(t Tree) []Tree {
list := make([]Tree, 0)
for i := 0; i < t.GetChildCount(); i++ {
list = append(list, t.GetChild(i))
}
return list
}
// TreesgetAncestors returns a list of all ancestors of this node. The first node of list is the root
// and the last node is the parent of this node.
//
//goland:noinspection GoUnusedExportedFunction
func TreesgetAncestors(t Tree) []Tree {
ancestors := make([]Tree, 0)
t = t.GetParent()
for t != nil {
f := []Tree{t}
ancestors = append(f, ancestors...)
t = t.GetParent()
}
return ancestors
}
//goland:noinspection GoUnusedExportedFunction
func TreesFindAllTokenNodes(t ParseTree, ttype int) []ParseTree {
return TreesfindAllNodes(t, ttype, true)
}
//goland:noinspection GoUnusedExportedFunction
func TreesfindAllRuleNodes(t ParseTree, ruleIndex int) []ParseTree {
return TreesfindAllNodes(t, ruleIndex, false)
}
func TreesfindAllNodes(t ParseTree, index int, findTokens bool) []ParseTree {
nodes := make([]ParseTree, 0)
treesFindAllNodes(t, index, findTokens, &nodes)
return nodes
}
func treesFindAllNodes(t ParseTree, index int, findTokens bool, nodes *[]ParseTree) {
// check this node (the root) first
t2, ok := t.(TerminalNode)
t3, ok2 := t.(ParserRuleContext)
if findTokens && ok {
if t2.GetSymbol().GetTokenType() == index {
*nodes = append(*nodes, t2)
}
} else if !findTokens && ok2 {
if t3.GetRuleIndex() == index {
*nodes = append(*nodes, t3)
}
}
// check children
for i := 0; i < t.GetChildCount(); i++ {
treesFindAllNodes(t.GetChild(i).(ParseTree), index, findTokens, nodes)
}
}
//goland:noinspection GoUnusedExportedFunction
func TreesDescendants(t ParseTree) []ParseTree {
nodes := []ParseTree{t}
for i := 0; i < t.GetChildCount(); i++ {
nodes = append(nodes, TreesDescendants(t.GetChild(i).(ParseTree))...)
}
return nodes
}