/* 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. */ #pragma once #include "tree/ParseTree.h" #include "tree/ParseTreeVisitor.h" namespace antlr4 { namespace tree { class ANTLR4CPP_PUBLIC AbstractParseTreeVisitor : public ParseTreeVisitor { public: /// The default implementation calls on the /// specified tree. virtual std::any visit(ParseTree *tree) override { return tree->accept(this); } /** *

The default implementation initializes the aggregate result to * {@link #defaultResult defaultResult()}. Before visiting each child, it * calls {@link #shouldVisitNextChild shouldVisitNextChild}; if the result * is {@code false} no more children are visited and the current aggregate * result is returned. After visiting a child, the aggregate result is * updated by calling {@link #aggregateResult aggregateResult} with the * previous aggregate result and the result of visiting the child.

* *

The default implementation is not safe for use in visitors that modify * the tree structure. Visitors that modify the tree should override this * method to behave properly in respect to the specific algorithm in use.

*/ virtual std::any visitChildren(ParseTree *node) override { std::any result = defaultResult(); size_t n = node->children.size(); for (size_t i = 0; i < n; i++) { if (!shouldVisitNextChild(node, result)) { break; } std::any childResult = node->children[i]->accept(this); result = aggregateResult(std::move(result), std::move(childResult)); } return result; } /// The default implementation returns the result of /// . virtual std::any visitTerminal(TerminalNode * /*node*/) override { return defaultResult(); } /// The default implementation returns the result of /// . virtual std::any visitErrorNode(ErrorNode * /*node*/) override { return defaultResult(); } protected: /// /// Gets the default value returned by visitor methods. This value is /// returned by the default implementations of /// , . /// The default implementation of /// initializes its aggregate result to this value. ///

/// The base implementation returns {@code std::any()}. ///

/// The default value returned by visitor methods. virtual std::any defaultResult() { return std::any(); } /// /// Aggregates the results of visiting multiple children of a node. After /// either all children are visited or returns /// {@code false}, the aggregate value is returned as the result of /// . ///

/// The default implementation returns {@code nextResult}, meaning /// will return the result of the last child visited /// (or return the initial value if the node has no children). ///

/// The previous aggregate value. In the default /// implementation, the aggregate value is initialized to /// , which is passed as the {@code aggregate} argument /// to this method after the first child node is visited. /// The result of the immediately preceeding call to visit /// a child node. /// /// The updated aggregate result. virtual std::any aggregateResult(std::any /*aggregate*/, std::any nextResult) { return nextResult; } /// /// This method is called after visiting each child in /// . This method is first called before the first /// child is visited; at that point {@code currentResult} will be the initial /// value (in the default implementation, the initial value is returned by a /// call to . This method is not called after the last /// child is visited. ///

/// The default implementation always returns {@code true}, indicating that /// {@code visitChildren} should only return after all children are visited. /// One reason to override this method is to provide a "short circuit" /// evaluation option for situations where the result of visiting a single /// child has the potential to determine the result of the visit operation as /// a whole. ///

/// The whose children are currently being /// visited. /// The current aggregate result of the children visited /// to the current point. /// /// {@code true} to continue visiting children. Otherwise return /// {@code false} to stop visiting children and immediately return the /// current aggregate result from . virtual bool shouldVisitNextChild(ParseTree * /*node*/, const std::any &/*currentResult*/) { return true; } }; } // namespace tree } // namespace antlr4