diff --git a/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj b/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj index 1b95b6cae..b980fd5a7 100644 --- a/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj +++ b/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj @@ -812,6 +812,12 @@ 27B36AC91DACE7AF0069C868 /* RuleContextWithAltNum.h in Headers */ = {isa = PBXBuildFile; fileRef = 27B36AC51DACE7AF0069C868 /* RuleContextWithAltNum.h */; }; 27B36ACA1DACE7AF0069C868 /* RuleContextWithAltNum.h in Headers */ = {isa = PBXBuildFile; fileRef = 27B36AC51DACE7AF0069C868 /* RuleContextWithAltNum.h */; }; 27B36ACB1DACE7AF0069C868 /* RuleContextWithAltNum.h in Headers */ = {isa = PBXBuildFile; fileRef = 27B36AC51DACE7AF0069C868 /* RuleContextWithAltNum.h */; }; + 27D414521DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27D414501DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp */; }; + 27D414531DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27D414501DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp */; }; + 27D414541DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27D414501DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp */; }; + 27D414551DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D414511DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h */; }; + 27D414561DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D414511DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h */; }; + 27D414571DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D414511DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h */; }; 27DB449D1D045537007E790B /* XPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27DB448B1D045537007E790B /* XPath.cpp */; }; 27DB449E1D045537007E790B /* XPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 27DB448C1D045537007E790B /* XPath.h */; }; 27DB449F1D045537007E790B /* XPathElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27DB448D1D045537007E790B /* XPathElement.cpp */; }; @@ -1150,6 +1156,8 @@ 27AC52CF1CE773A80093AAAB /* antlr4-runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "antlr4-runtime.h"; sourceTree = ""; }; 27B36AC41DACE7AF0069C868 /* RuleContextWithAltNum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RuleContextWithAltNum.cpp; sourceTree = ""; }; 27B36AC51DACE7AF0069C868 /* RuleContextWithAltNum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuleContextWithAltNum.h; sourceTree = ""; }; + 27D414501DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IterativeParseTreeWalker.cpp; sourceTree = ""; }; + 27D414511DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IterativeParseTreeWalker.h; sourceTree = ""; }; 27DB448B1D045537007E790B /* XPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XPath.cpp; sourceTree = ""; wrapsLines = 0; }; 27DB448C1D045537007E790B /* XPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPath.h; sourceTree = ""; wrapsLines = 0; }; 27DB448D1D045537007E790B /* XPathElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XPathElement.cpp; sourceTree = ""; wrapsLines = 0; }; @@ -1499,6 +1507,8 @@ 276E5CFB1CDB57AA003FF4B4 /* ErrorNode.h */, 276E5CFC1CDB57AA003FF4B4 /* ErrorNodeImpl.cpp */, 276E5CFD1CDB57AA003FF4B4 /* ErrorNodeImpl.h */, + 27D414501DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp */, + 27D414511DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h */, 276566DF1DA93BFB000869BE /* ParseTree.cpp */, 276E5CFE1CDB57AA003FF4B4 /* ParseTree.h */, 276E5D001CDB57AA003FF4B4 /* ParseTreeListener.h */, @@ -1721,6 +1731,7 @@ 276E5E411CDB57AA003FF4B4 /* NotSetTransition.h in Headers */, 276E5E891CDB57AA003FF4B4 /* RangeTransition.h in Headers */, 27DB44D21D0463DB007E790B /* XPathRuleElement.h in Headers */, + 27D414571DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h in Headers */, 276E601B1CDB57AA003FF4B4 /* ParseTreePattern.h in Headers */, 276E5DFC1CDB57AA003FF4B4 /* LexerCustomAction.h in Headers */, 276E5FE81CDB57AA003FF4B4 /* TokenStreamRewriter.h in Headers */, @@ -1795,6 +1806,7 @@ 276E5EA01CDB57AA003FF4B4 /* SemanticContext.h in Headers */, 276E5F5D1CDB57AA003FF4B4 /* ListTokenSource.h in Headers */, 276E5F8D1CDB57AA003FF4B4 /* ParserInterpreter.h in Headers */, + 27D414561DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h in Headers */, 276E5DDD1CDB57AA003FF4B4 /* LexerActionExecutor.h in Headers */, 276E5F4B1CDB57AA003FF4B4 /* Lexer.h in Headers */, 276E5F631CDB57AA003FF4B4 /* Interval.h in Headers */, @@ -2046,6 +2058,7 @@ 276E5E3F1CDB57AA003FF4B4 /* NotSetTransition.h in Headers */, 276E5E871CDB57AA003FF4B4 /* RangeTransition.h in Headers */, 276E60191CDB57AA003FF4B4 /* ParseTreePattern.h in Headers */, + 27D414551DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.h in Headers */, 276E5DFA1CDB57AA003FF4B4 /* LexerCustomAction.h in Headers */, 276E5FE61CDB57AA003FF4B4 /* TokenStreamRewriter.h in Headers */, 276E5DEE1CDB57AA003FF4B4 /* LexerATNSimulator.h in Headers */, @@ -2263,6 +2276,7 @@ 27B36AC81DACE7AF0069C868 /* RuleContextWithAltNum.cpp in Sources */, 276E5F101CDB57AA003FF4B4 /* DFASerializer.cpp in Sources */, 276E5F2E1CDB57AA003FF4B4 /* FailedPredicateException.cpp in Sources */, + 27D414541DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp in Sources */, 276E5F8B1CDB57AA003FF4B4 /* ParserInterpreter.cpp in Sources */, 276E5D4E1CDB57AA003FF4B4 /* AmbiguityInfo.cpp in Sources */, 276E5F161CDB57AA003FF4B4 /* DFAState.cpp in Sources */, @@ -2402,6 +2416,7 @@ 27B36AC71DACE7AF0069C868 /* RuleContextWithAltNum.cpp in Sources */, 276E5F0F1CDB57AA003FF4B4 /* DFASerializer.cpp in Sources */, 276E5F2D1CDB57AA003FF4B4 /* FailedPredicateException.cpp in Sources */, + 27D414531DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp in Sources */, 276E5F8A1CDB57AA003FF4B4 /* ParserInterpreter.cpp in Sources */, 276E5D4D1CDB57AA003FF4B4 /* AmbiguityInfo.cpp in Sources */, 276E5F151CDB57AA003FF4B4 /* DFAState.cpp in Sources */, @@ -2541,6 +2556,7 @@ 27B36AC61DACE7AF0069C868 /* RuleContextWithAltNum.cpp in Sources */, 276E5F0E1CDB57AA003FF4B4 /* DFASerializer.cpp in Sources */, 276E5F2C1CDB57AA003FF4B4 /* FailedPredicateException.cpp in Sources */, + 27D414521DEB0D3D00D0F3F9 /* IterativeParseTreeWalker.cpp in Sources */, 27DB44A71D045537007E790B /* XPathTokenAnywhereElement.cpp in Sources */, 276E5F891CDB57AA003FF4B4 /* ParserInterpreter.cpp in Sources */, 276E5D4C1CDB57AA003FF4B4 /* AmbiguityInfo.cpp in Sources */, diff --git a/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp b/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp new file mode 100644 index 000000000..5ce30d3a7 --- /dev/null +++ b/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp @@ -0,0 +1,96 @@ +/* + * [The "BSD license"] + * Copyright (c) 2012 Terence Parr + * Copyright (c) 2012 Sam Harwell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#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 nodeStack; + std::vector indexStack; + + ParseTree *currentNode = t; + size_t currentIndex = 0; + + while (currentNode != nullptr) { + // pre-order visit + if (antlrcpp::is(currentNode)) { + listener->visitErrorNode(dynamic_cast(currentNode)); + } else if (antlrcpp::is(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(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); + } +} diff --git a/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.h b/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.h new file mode 100644 index 000000000..8957d87e4 --- /dev/null +++ b/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.h @@ -0,0 +1,53 @@ +/* + * [The "BSD license"] + * Copyright (c) 2012 Terence Parr + * Copyright (c) 2012 Sam Harwell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "antlr4-common.h" + +#include "tree/ParseTreeWalker.h" + +namespace antlr4 { +namespace tree { + + class ParseTreeListener; + + /** + * An iterative (read: non-recursive) pre-order and post-order tree walker that + * doesn't use the thread stack but heap-based stacks. Makes it possible to + * process deeply nested parse trees. + */ + class ANTLR4CPP_PUBLIC IterativeParseTreeWalker : public ParseTreeWalker { + public: + virtual void walk(ParseTreeListener *listener, ParseTree *t) const override; + }; + +} // namespace tree +} // namespace antlr4 diff --git a/runtime/Cpp/runtime/src/tree/ParseTreeProperty.h b/runtime/Cpp/runtime/src/tree/ParseTreeProperty.h index c6d2aa155..da465cacd 100755 --- a/runtime/Cpp/runtime/src/tree/ParseTreeProperty.h +++ b/runtime/Cpp/runtime/src/tree/ParseTreeProperty.h @@ -31,6 +31,8 @@ #pragma once +#include "antlr4-common.h" + namespace antlr4 { namespace tree { diff --git a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp index 8b5e71168..04fd9e648 100755 --- a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp +++ b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp @@ -34,12 +34,13 @@ #include "tree/ParseTreeListener.h" #include "support/CPPUtils.h" +#include "tree/IterativeParseTreeWalker.h" #include "tree/ParseTreeWalker.h" using namespace antlr4::tree; using namespace antlrcpp; -ParseTreeWalker ParseTreeWalker::DEFAULT; +ParseTreeWalker ParseTreeWalker::DEFAULT = IterativeParseTreeWalker(); void ParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const { if (is(t)) { @@ -52,7 +53,7 @@ void ParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const { enterRule(listener, t); for (auto &child : t->children) { - walk(listener, dynamic_cast(child)); + walk(listener, child); } exitRule(listener, t); } diff --git a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h index 1b2bca1ba..1dc4d7dc7 100755 --- a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h +++ b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h @@ -31,6 +31,8 @@ #pragma once +#include "antlr4-common.h" + namespace antlr4 { namespace tree {