72 lines
1.9 KiB
C++
72 lines
1.9 KiB
C++
|
|
/* 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/ParseTreeListener.h"
|
||
|
|
#include "tree/ParseTree.h"
|
||
|
|
#include "tree/ErrorNode.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);
|
||
|
|
}
|
||
|
|
}
|