1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2 * Use of this file is governed by the BSD 3-clause license that
3 * can be found in the LICENSE.txt file in the project root.
6 #include "tree/ErrorNode.h"
8 #include "ParserRuleContext.h"
9 #include "support/CPPUtils.h"
10 #include "tree/TerminalNodeImpl.h"
12 #include "misc/Interval.h"
14 #include "CommonToken.h"
15 #include "misc/Predicate.h"
17 #include "tree/Trees.h"
19 using namespace antlr4;
20 using namespace antlr4::misc;
21 using namespace antlr4::tree;
23 using namespace antlrcpp;
28 std::string Trees::toStringTree(ParseTree *t, bool pretty) {
29 return toStringTree(t, nullptr, pretty);
32 std::string Trees::toStringTree(ParseTree *t, Parser *recog, bool pretty) {
34 return toStringTree(t, std::vector<std::string>(), pretty);
35 return toStringTree(t, recog->getRuleNames(), pretty);
38 std::string Trees::toStringTree(ParseTree *t, const std::vector<std::string> &ruleNames, bool pretty) {
39 std::string temp = antlrcpp::escapeWhitespace(Trees::getNodeText(t, ruleNames), false);
40 if (t->children.empty()) {
45 ss << "(" << temp << ' ';
47 // Implement the recursive walk as iteration to avoid trouble with deep nesting.
48 std::stack<size_t> stack;
49 size_t childIndex = 0;
51 size_t indentationLevel = 1;
52 while (childIndex < run->children.size()) {
56 ParseTree *child = run->children[childIndex];
57 temp = antlrcpp::escapeWhitespace(Trees::getNodeText(child, ruleNames), false);
58 if (!child->children.empty()) {
59 // Go deeper one level.
60 stack.push(childIndex);
66 for (size_t i = 0; i < indentationLevel; ++i) {
70 ss << "(" << temp << " ";
73 while (++childIndex == run->children.size()) {
74 if (stack.size() > 0) {
75 // Reached the end of the current level. See if we can step up from here.
76 childIndex = stack.top();
94 std::string Trees::getNodeText(ParseTree *t, Parser *recog) {
95 return getNodeText(t, recog->getRuleNames());
98 std::string Trees::getNodeText(ParseTree *t, const std::vector<std::string> &ruleNames) {
99 if (ruleNames.size() > 0) {
100 if (is<RuleContext *>(t)) {
101 size_t ruleIndex = dynamic_cast<RuleContext *>(t)->getRuleIndex();
102 std::string ruleName = ruleNames[ruleIndex];
103 size_t altNumber = dynamic_cast<RuleContext *>(t)->getAltNumber();
104 if (altNumber != atn::ATN::INVALID_ALT_NUMBER) {
105 return ruleName + ":" + std::to_string(altNumber);
108 } else if (is<ErrorNode *>(t)) {
109 return t->toString();
110 } else if (is<TerminalNode *>(t)) {
111 Token *symbol = dynamic_cast<TerminalNode *>(t)->getSymbol();
112 if (symbol != nullptr) {
113 std::string s = symbol->getText();
118 // no recog for rule names
119 if (is<RuleContext *>(t)) {
120 return dynamic_cast<RuleContext *>(t)->getText();
123 if (is<TerminalNodeImpl *>(t)) {
124 return dynamic_cast<TerminalNodeImpl *>(t)->getSymbol()->getText();
130 std::vector<ParseTree *> Trees::getAncestors(ParseTree *t) {
131 std::vector<ParseTree *> ancestors;
132 ParseTree *parent = t->parent;
133 while (parent != nullptr) {
134 ancestors.insert(ancestors.begin(), parent); // insert at start
135 parent = parent->parent;
141 static void _findAllNodes(ParseTree *t, size_t index, bool findTokens, std::vector<T> &nodes) {
142 // check this node (the root) first
143 if (findTokens && is<TerminalNode *>(t)) {
144 TerminalNode *tnode = dynamic_cast<TerminalNode *>(t);
145 if (tnode->getSymbol()->getType() == index) {
148 } else if (!findTokens && is<ParserRuleContext *>(t)) {
149 ParserRuleContext *ctx = dynamic_cast<ParserRuleContext *>(t);
150 if (ctx->getRuleIndex() == index) {
155 for (size_t i = 0; i < t->children.size(); i++) {
156 _findAllNodes(t->children[i], index, findTokens, nodes);
160 bool Trees::isAncestorOf(ParseTree *t, ParseTree *u) {
161 if (t == nullptr || u == nullptr || t->parent == nullptr) {
165 ParseTree *p = u->parent;
166 while (p != nullptr) {
175 std::vector<ParseTree *> Trees::findAllTokenNodes(ParseTree *t, size_t ttype) {
176 return findAllNodes(t, ttype, true);
179 std::vector<ParseTree *> Trees::findAllRuleNodes(ParseTree *t, size_t ruleIndex) {
180 return findAllNodes(t, ruleIndex, false);
183 std::vector<ParseTree *> Trees::findAllNodes(ParseTree *t, size_t index, bool findTokens) {
184 std::vector<ParseTree *> nodes;
185 _findAllNodes<ParseTree *>(t, index, findTokens, nodes);
189 std::vector<ParseTree *> Trees::getDescendants(ParseTree *t) {
190 std::vector<ParseTree *> nodes;
192 std::size_t n = t->children.size();
193 for (size_t i = 0 ; i < n ; i++) {
194 auto descentants = getDescendants(t->children[i]);
195 for (auto *entry: descentants) {
196 nodes.push_back(entry);
202 std::vector<ParseTree *> Trees::descendants(ParseTree *t) {
203 return getDescendants(t);
206 ParserRuleContext* Trees::getRootOfSubtreeEnclosingRegion(ParseTree *t, size_t startTokenIndex, size_t stopTokenIndex) {
207 size_t n = t->children.size();
208 for (size_t i = 0; i < n; i++) {
209 ParserRuleContext *r = getRootOfSubtreeEnclosingRegion(t->children[i], startTokenIndex, stopTokenIndex);
215 if (is<ParserRuleContext *>(t)) {
216 ParserRuleContext *r = dynamic_cast<ParserRuleContext *>(t);
217 if (startTokenIndex >= r->getStart()->getTokenIndex() && // is range fully contained in t?
218 (r->getStop() == nullptr || stopTokenIndex <= r->getStop()->getTokenIndex())) {
219 // note: r.getStop()==null likely implies that we bailed out of parser and there's nothing to the right
226 ParseTree * Trees::findNodeSuchThat(ParseTree *t, Ref<Predicate> const& pred) {
231 size_t n = t->children.size();
232 for (size_t i = 0 ; i < n ; ++i) {
233 ParseTree *u = findNodeSuchThat(t->children[i], pred);