blob: 66cfc91d1de3aa0b7278567508d6ea2c71242b7a (
plain)
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
|
/* Copyright (c) 2012-2017 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.
*/
#include "support/CPPUtils.h"
#include "tree/ErrorNode.h"
#include "tree/ParseTree.h"
#include "tree/ParseTreeListener.h"
#include "IterativeParseTreeWalker.h"
using namespace antlr4::tree;
void IterativeParseTreeWalker::walk(ParseTreeListener* listener,
ParseTree* t) const {
std::vector<ParseTree*> nodeStack;
std::vector<size_t> indexStack;
ParseTree* currentNode = t;
size_t currentIndex = 0;
while (currentNode != nullptr) {
// pre-order visit
if (antlrcpp::is<ErrorNode*>(currentNode)) {
listener->visitErrorNode(dynamic_cast<ErrorNode*>(currentNode));
} else if (antlrcpp::is<TerminalNode*>(currentNode)) {
listener->visitTerminal((TerminalNode*)currentNode);
} else {
enterRule(listener, currentNode);
}
// Move down to first child, if it exists.
if (!currentNode->children.empty()) {
nodeStack.push_back(currentNode);
indexStack.push_back(currentIndex);
currentIndex = 0;
currentNode = currentNode->children[0];
continue;
}
// No child nodes, so walk tree.
do {
// post-order visit
if (!antlrcpp::is<TerminalNode*>(currentNode)) {
exitRule(listener, currentNode);
}
// No parent, so no siblings.
if (nodeStack.empty()) {
currentNode = nullptr;
currentIndex = 0;
break;
}
// Move to next sibling if possible.
if (nodeStack.back()->children.size() > ++currentIndex) {
currentNode = nodeStack.back()->children[currentIndex];
break;
}
// No next sibling, so move up.
currentNode = nodeStack.back();
nodeStack.pop_back();
currentIndex = indexStack.back();
indexStack.pop_back();
} while (currentNode != nullptr);
}
}
|