forked from jasder/antlr
Rework of the visitor implementation
The translation from Java generics to templates in C++ lead to the need of virtual template functions, which is not supported by C++. Instead we use now the Any class for results of visits and no longer need templates for that part.
This commit is contained in:
parent
51b91f4d1b
commit
8a5f6815fe
|
@ -881,6 +881,7 @@
|
|||
27DB44D81D0463DB007E790B /* XPathWildcardAnywhereElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 27DB449A1D045537007E790B /* XPathWildcardAnywhereElement.h */; };
|
||||
27DB44D91D0463DB007E790B /* XPathWildcardElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27DB449B1D045537007E790B /* XPathWildcardElement.cpp */; };
|
||||
27DB44DA1D0463DB007E790B /* XPathWildcardElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 27DB449C1D045537007E790B /* XPathWildcardElement.h */; };
|
||||
27F4A8561D4CEB2A00E067EE /* Any.h in Headers */ = {isa = PBXBuildFile; fileRef = 27F4A8551D4CEB2A00E067EE /* Any.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -1118,7 +1119,7 @@
|
|||
276E5CFE1CDB57AA003FF4B4 /* ParseTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseTree.h; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
276E5D001CDB57AA003FF4B4 /* ParseTreeListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseTreeListener.h; sourceTree = "<group>"; };
|
||||
276E5D021CDB57AA003FF4B4 /* ParseTreeProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseTreeProperty.h; sourceTree = "<group>"; };
|
||||
276E5D031CDB57AA003FF4B4 /* ParseTreeVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseTreeVisitor.h; sourceTree = "<group>"; };
|
||||
276E5D031CDB57AA003FF4B4 /* ParseTreeVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseTreeVisitor.h; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
276E5D041CDB57AA003FF4B4 /* ParseTreeWalker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParseTreeWalker.cpp; sourceTree = "<group>"; };
|
||||
276E5D051CDB57AA003FF4B4 /* ParseTreeWalker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseTreeWalker.h; sourceTree = "<group>"; };
|
||||
276E5D071CDB57AA003FF4B4 /* Chunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Chunk.h; sourceTree = "<group>"; };
|
||||
|
@ -1179,6 +1180,7 @@
|
|||
27DB449C1D045537007E790B /* XPathWildcardElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPathWildcardElement.h; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
27DB44AF1D0463CC007E790B /* XPathLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XPathLexer.cpp; sourceTree = "<group>"; };
|
||||
27DB44B01D0463CC007E790B /* XPathLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPathLexer.h; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
27F4A8551D4CEB2A00E067EE /* Any.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Any.h; sourceTree = "<group>"; };
|
||||
37C147171B4D5A04008EDDDB /* libantlr4-runtime.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libantlr4-runtime.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
37D727AA1867AF1E007B6D10 /* libantlr4-runtime.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libantlr4-runtime.dylib"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -1483,6 +1485,7 @@
|
|||
276E5CE41CDB57AA003FF4B4 /* support */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
27F4A8551D4CEB2A00E067EE /* Any.h */,
|
||||
276E5CE51CDB57AA003FF4B4 /* Arrays.cpp */,
|
||||
276E5CE61CDB57AA003FF4B4 /* Arrays.h */,
|
||||
276E5CE71CDB57AA003FF4B4 /* BitSet.h */,
|
||||
|
@ -2085,6 +2088,7 @@
|
|||
27DB44A81D045537007E790B /* XPathTokenAnywhereElement.h in Headers */,
|
||||
276E5FD41CDB57AA003FF4B4 /* TokenFactory.h in Headers */,
|
||||
276E5EF91CDB57AA003FF4B4 /* CommonTokenStream.h in Headers */,
|
||||
27F4A8561D4CEB2A00E067EE /* Any.h in Headers */,
|
||||
276E5EB11CDB57AA003FF4B4 /* StarBlockStartState.h in Headers */,
|
||||
276E5F6E1CDB57AA003FF4B4 /* MurmurHash.h in Headers */,
|
||||
276E601F1CDB57AA003FF4B4 /* ParseTreePatternMatcher.h in Headers */,
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "misc/Interval.h"
|
||||
#include "Parser.h"
|
||||
#include "atn/ATN.h"
|
||||
#include "tree/ParseTreeVisitor.h"
|
||||
|
||||
#include "RuleContext.h"
|
||||
|
||||
|
@ -112,6 +113,10 @@ std::size_t RuleContext::getChildCount() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any RuleContext::accept(tree::ParseTreeVisitor *visitor) {
|
||||
return visitor->visitChildren(this);
|
||||
}
|
||||
|
||||
std::string RuleContext::toStringTree(Parser *recog) {
|
||||
return tree::Trees::toStringTree(shared_from_this(), recog);
|
||||
}
|
||||
|
|
|
@ -136,10 +136,7 @@ namespace antlr4 {
|
|||
|
||||
virtual std::size_t getChildCount() override;
|
||||
|
||||
template<typename T, typename T1>
|
||||
T accept(tree::ParseTreeVisitor<T1> *visitor) {
|
||||
return visitor->visitChildren(this);
|
||||
}
|
||||
virtual antlrcpp::Any accept(tree::ParseTreeVisitor *visitor) override;
|
||||
|
||||
/// <summary>
|
||||
/// Print out a whole tree, not just a node, in LISP format
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <stack>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
#include "misc/IntervalSet.h"
|
||||
#include "misc/MurmurHash.h"
|
||||
#include "misc/Predicate.h"
|
||||
#include "support/Any.h"
|
||||
#include "support/Arrays.h"
|
||||
#include "support/BitSet.h"
|
||||
#include "support/CPPUtils.h"
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* [The "BSD license"]
|
||||
* Copyright (c) 2016 Mike Lischke
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// A standard C++ class loosely modeled after boost::Any.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "antlr4-common.h"
|
||||
|
||||
namespace antlrcpp {
|
||||
|
||||
template<class T>
|
||||
using StorageType = typename std::decay<T>::type;
|
||||
|
||||
struct Any
|
||||
{
|
||||
bool isNull() const { return !_ptr; }
|
||||
bool isNotNull() const { return _ptr; }
|
||||
|
||||
Any() : _ptr(nullptr) {
|
||||
}
|
||||
|
||||
Any(Any& that) : _ptr(that.clone()) {
|
||||
}
|
||||
|
||||
Any(Any&& that) : _ptr(that._ptr) {
|
||||
that._ptr = nullptr;
|
||||
}
|
||||
|
||||
Any(const Any& that) : _ptr(that.clone()) {
|
||||
}
|
||||
|
||||
Any(const Any&& that) : _ptr(that.clone()) {
|
||||
}
|
||||
|
||||
template<typename U> Any(U&& value) : _ptr(new Derived<StorageType<U>>(std::forward<U>(value))) {
|
||||
}
|
||||
|
||||
template<class U> bool is() const {
|
||||
typedef StorageType<U> T;
|
||||
|
||||
auto derived = dynamic_cast<Derived<T> *>(_ptr);
|
||||
|
||||
return derived;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
StorageType<U>& as() {
|
||||
typedef StorageType<U> T;
|
||||
|
||||
auto derived = dynamic_cast<Derived<T>*>(_ptr);
|
||||
|
||||
if (!derived)
|
||||
throw std::bad_cast();
|
||||
|
||||
return derived->value;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
operator U() {
|
||||
return as<StorageType<U>>();
|
||||
}
|
||||
|
||||
Any& operator = (const Any& a) {
|
||||
if (_ptr == a._ptr)
|
||||
return *this;
|
||||
|
||||
auto old_ptr = _ptr;
|
||||
_ptr = a.clone();
|
||||
|
||||
if (old_ptr)
|
||||
delete old_ptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Any& operator = (Any&& a) {
|
||||
if (_ptr == a._ptr)
|
||||
return *this;
|
||||
|
||||
std::swap(_ptr, a._ptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~Any() {
|
||||
delete _ptr;
|
||||
}
|
||||
|
||||
virtual bool equals(Any other) const {
|
||||
return _ptr == other._ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Base {
|
||||
virtual ~Base() { }
|
||||
virtual Base* clone() const = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Derived : Base
|
||||
{
|
||||
template<typename U> Derived(U&& value) : value(std::forward<U>(value)) {
|
||||
}
|
||||
|
||||
T value;
|
||||
|
||||
Base* clone() const {
|
||||
return new Derived<T>(value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Base* clone() const
|
||||
{
|
||||
if (_ptr)
|
||||
return _ptr->clone();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Base *_ptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace antlrcpp
|
|
@ -153,13 +153,13 @@ namespace antlr4 {
|
|||
class Vocabulary;
|
||||
}
|
||||
namespace tree {
|
||||
template <typename t> class AbstractParseTreeVisitor;
|
||||
class AbstractParseTreeVisitor;
|
||||
class ErrorNode;
|
||||
class ErrorNodeImpl;
|
||||
class ParseTree;
|
||||
class ParseTreeListener;
|
||||
template<typename T> class ParseTreeProperty;
|
||||
template<typename T> class ParseTreeVisitor;
|
||||
class ParseTreeVisitor;
|
||||
class ParseTreeWalker;
|
||||
class RuleNode;
|
||||
class SyntaxTree;
|
||||
|
|
|
@ -37,16 +37,11 @@
|
|||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
template<typename T>
|
||||
class ANTLR4CPP_PUBLIC AbstractParseTreeVisitor : public ParseTreeVisitor<T> {
|
||||
/// <summary>
|
||||
/// {@inheritDoc}
|
||||
/// <p/>
|
||||
class ANTLR4CPP_PUBLIC AbstractParseTreeVisitor : public ParseTreeVisitor {
|
||||
public:
|
||||
/// The default implementation calls <seealso cref="ParseTree#accept"/> on the
|
||||
/// specified tree.
|
||||
/// </summary>
|
||||
public:
|
||||
virtual T* visit(ParseTree *tree) override {
|
||||
virtual antlrcpp::Any visit(ParseTree *tree) override {
|
||||
return tree->accept(this);
|
||||
}
|
||||
|
||||
|
@ -63,8 +58,8 @@ namespace tree {
|
|||
* the tree structure. Visitors that modify the tree should override this
|
||||
* method to behave properly in respect to the specific algorithm in use.</p>
|
||||
*/
|
||||
virtual T* visitChildren(RuleNode *node) override {
|
||||
T* result = defaultResult();
|
||||
virtual antlrcpp::Any visitChildren(RuleNode *node) override {
|
||||
antlrcpp::Any result = defaultResult();
|
||||
size_t n = node->getChildCount();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (!shouldVisitNextChild(node, result)) {
|
||||
|
@ -72,33 +67,26 @@ namespace tree {
|
|||
}
|
||||
|
||||
Ref<ParseTree> c = node->getChild(i);
|
||||
T childResult = c->accept(this);
|
||||
antlrcpp::Any childResult = c->accept(this);
|
||||
result = aggregateResult(result, childResult);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {@inheritDoc}
|
||||
/// <p/>
|
||||
/// The default implementation returns the result of
|
||||
/// <seealso cref="#defaultResult defaultResult"/>.
|
||||
/// </summary>
|
||||
virtual T* visitTerminal(TerminalNode * /*node*/) override {
|
||||
virtual antlrcpp::Any visitTerminal(TerminalNode * /*node*/) override {
|
||||
return defaultResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {@inheritDoc}
|
||||
/// <p/>
|
||||
/// The default implementation returns the result of
|
||||
/// <seealso cref="#defaultResult defaultResult"/>.
|
||||
/// </summary>
|
||||
virtual T* visitErrorNode(ErrorNode * /*node*/) override {
|
||||
virtual antlrcpp::Any visitErrorNode(ErrorNode * /*node*/) override {
|
||||
return defaultResult();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// <summary>
|
||||
/// Gets the default value returned by visitor methods. This value is
|
||||
/// returned by the default implementations of
|
||||
|
@ -109,9 +97,8 @@ namespace tree {
|
|||
/// The base implementation returns {@code null}.
|
||||
/// </summary>
|
||||
/// <returns> The default value returned by visitor methods. </returns>
|
||||
protected:
|
||||
virtual T* defaultResult() {
|
||||
return nullptr;
|
||||
virtual antlrcpp::Any defaultResult() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -132,7 +119,7 @@ namespace tree {
|
|||
/// a child node.
|
||||
/// </param>
|
||||
/// <returns> The updated aggregate result. </returns>
|
||||
virtual T* aggregateResult(T* /*aggregate*/, T* nextResult) {
|
||||
virtual antlrcpp::Any aggregateResult(antlrcpp::Any /*aggregate*/, antlrcpp::Any nextResult) {
|
||||
return nextResult;
|
||||
}
|
||||
|
||||
|
@ -159,7 +146,7 @@ namespace tree {
|
|||
/// <returns> {@code true} to continue visiting children. Otherwise return
|
||||
/// {@code false} to stop visiting children and immediately return the
|
||||
/// current aggregate result from <seealso cref="#visitChildren"/>. </returns>
|
||||
virtual bool shouldVisitNextChild(RuleNode * /*node*/, T /*currentResult*/) {
|
||||
virtual bool shouldVisitNextChild(RuleNode * /*node*/, antlrcpp::Any /*currentResult*/) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "tree/ParseTreeVisitor.h"
|
||||
|
||||
#include "tree/ErrorNodeImpl.h"
|
||||
|
||||
|
@ -39,3 +40,7 @@ using namespace antlr4::tree;
|
|||
|
||||
ErrorNodeImpl::ErrorNodeImpl(Token *token) : TerminalNodeImpl(token) {
|
||||
}
|
||||
|
||||
antlrcpp::Any ErrorNodeImpl::accept(ParseTreeVisitor *visitor) {
|
||||
return visitor->visitErrorNode(this);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "tree/TerminalNodeImpl.h"
|
||||
#include "misc/Interval.h"
|
||||
|
||||
#include "support/Any.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
|
@ -49,10 +51,7 @@ namespace tree {
|
|||
public:
|
||||
ErrorNodeImpl(Token *token);
|
||||
|
||||
template<typename T, typename T1>
|
||||
T accept(ParseTreeVisitor<T1> *visitor) {
|
||||
return visitor->visitErrorNode(this);
|
||||
}
|
||||
virtual antlrcpp::Any accept(ParseTreeVisitor *visitor) override;
|
||||
};
|
||||
|
||||
} // namespace tree
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "tree/SyntaxTree.h"
|
||||
#include "support/any.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
@ -45,27 +46,22 @@ namespace tree {
|
|||
/// The payload is either a <seealso cref="Token"/> or a <seealso cref="RuleContext"/> object.
|
||||
/// </summary>
|
||||
class ANTLR4CPP_PUBLIC ParseTree : public SyntaxTree {
|
||||
// the following methods narrow the return type; they are not additional methods
|
||||
public:
|
||||
// the following methods narrow the return type; they are not additional methods
|
||||
std::weak_ptr<ParseTree> getParent() { return std::dynamic_pointer_cast<ParseTree>(getParentReference().lock()); };
|
||||
virtual Ref<ParseTree> getChild(size_t i) { return std::dynamic_pointer_cast<ParseTree>(getChildReference(i)); };
|
||||
|
||||
/// <summary>
|
||||
/// The <seealso cref="ParseTreeVisitor"/> needs a double dispatch method. </summary>
|
||||
template<typename T, typename T1>
|
||||
T *accept(ParseTreeVisitor<T1> *visitor);
|
||||
/// The <seealso cref="ParseTreeVisitor"/> needs a double dispatch method.
|
||||
// ml: This has been changed to use Any instead of a template parameter, to avoid the need of a virtual template function.
|
||||
virtual antlrcpp::Any accept(ParseTreeVisitor *visitor) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Return the combined text of all leaf nodes. Does not get any
|
||||
/// off-channel tokens (if any) so won't return whitespace and
|
||||
/// comments if they are sent to parser on hidden channel.
|
||||
/// </summary>
|
||||
/// off-channel tokens (if any) so won't return whitespace and
|
||||
/// comments if they are sent to parser on hidden channel.
|
||||
virtual std::string getText() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Specialize toStringTree so that it can print out more information
|
||||
/// based upon the parser.
|
||||
/// </summary>
|
||||
/// based upon the parser.
|
||||
virtual std::string toStringTree(Parser *parser) = 0;
|
||||
using Tree::toStringTree;
|
||||
};
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "antlr4-common.h"
|
||||
#include "support/Any.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
@ -43,7 +43,7 @@ namespace tree {
|
|||
/// </summary>
|
||||
/// @param <T> The return type of the visit operation. Use <seealso cref="Void"/> for
|
||||
/// operations with no return type. </param>
|
||||
template<typename T>
|
||||
// ml: no template parameter here, to avoid the need for virtual template functions. Instead we have our Any class.
|
||||
class ANTLR4CPP_PUBLIC ParseTreeVisitor {
|
||||
public:
|
||||
virtual ~ParseTreeVisitor() {}
|
||||
|
@ -53,7 +53,7 @@ namespace tree {
|
|||
/// </summary>
|
||||
/// <param name="tree"> The <seealso cref="ParseTree"/> to visit. </param>
|
||||
/// <returns> The result of visiting the parse tree. </returns>
|
||||
virtual T* visit(ParseTree *tree) = 0;
|
||||
virtual antlrcpp::Any visit(ParseTree *tree) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Visit the children of a node, and return a user-defined result of the
|
||||
|
@ -61,21 +61,21 @@ namespace tree {
|
|||
/// </summary>
|
||||
/// <param name="node"> The <seealso cref="RuleNode"/> whose children should be visited. </param>
|
||||
/// <returns> The result of visiting the children of the node. </returns>
|
||||
virtual T* visitChildren(RuleNode *node) = 0;
|
||||
virtual antlrcpp::Any visitChildren(RuleNode *node) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Visit a terminal node, and return a user-defined result of the operation.
|
||||
/// </summary>
|
||||
/// <param name="node"> The <seealso cref="TerminalNode"/> to visit. </param>
|
||||
/// <returns> The result of visiting the node. </returns>
|
||||
virtual T* visitTerminal(TerminalNode *node) = 0;
|
||||
virtual antlrcpp::Any visitTerminal(TerminalNode *node) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Visit an error node, and return a user-defined result of the operation.
|
||||
/// </summary>
|
||||
/// <param name="node"> The <seealso cref="ErrorNode"/> to visit. </param>
|
||||
/// <returns> The result of visiting the node. </returns>
|
||||
virtual T* visitErrorNode(ErrorNode *node) = 0;
|
||||
virtual antlrcpp::Any visitErrorNode(ErrorNode *node) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "misc/Interval.h"
|
||||
#include "Token.h"
|
||||
#include "tree/ParseTreeVisitor.h"
|
||||
|
||||
#include "tree/TerminalNodeImpl.h"
|
||||
|
||||
|
@ -57,6 +58,10 @@ std::size_t TerminalNodeImpl::getChildCount() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any TerminalNodeImpl::accept(ParseTreeVisitor *visitor) {
|
||||
return visitor->visitTerminal(this);
|
||||
}
|
||||
|
||||
std::string TerminalNodeImpl::getText() {
|
||||
return symbol->getText();
|
||||
}
|
||||
|
|
|
@ -48,10 +48,7 @@ namespace tree {
|
|||
|
||||
virtual std::size_t getChildCount() override;
|
||||
|
||||
template<typename T, typename T1>
|
||||
T accept(ParseTreeVisitor<T1> *visitor) {
|
||||
return visitor->visitTerminal(this);
|
||||
}
|
||||
virtual antlrcpp::Any accept(ParseTreeVisitor *visitor) override;
|
||||
|
||||
virtual std::string getText() override;
|
||||
virtual std::string toStringTree(Parser *parser) override;
|
||||
|
|
|
@ -1044,15 +1044,17 @@ void <parser.name>::<struct.name>::<if (method.isEnter)>enter<else>exit<endif>Ru
|
|||
|
||||
VisitorDispatchMethodHeader(method) ::= <<
|
||||
|
||||
template \<typename T>
|
||||
T* accept(tree::ParseTreeVisitor\<T> *visitor) {
|
||||
if (dynamic_cast\<<parser.grammarName>Visitor\<T>*>(visitor) != nullptr)
|
||||
return ((<parser.grammarName>Visitor\<T> *)visitor)->visit<struct.derivedFromName; format="cap">(this);
|
||||
virtual antlrcpp::Any accept(tree::ParseTreeVisitor *visitor) override;
|
||||
>>
|
||||
VisitorDispatchMethod(method) ::= <<
|
||||
|
||||
antlrcpp::Any <parser.name>::<struct.name>::accept(tree::ParseTreeVisitor *visitor) {
|
||||
if (dynamic_cast\<<parser.grammarName>Visitor*>(visitor) != nullptr)
|
||||
return ((<parser.grammarName>Visitor *)visitor)->visit<struct.derivedFromName; format="cap">(this);
|
||||
else
|
||||
return visitor->visitChildren(this);
|
||||
}
|
||||
>>
|
||||
VisitorDispatchMethod(method) ::= "<! Template function, must be implemented in the header. !>"
|
||||
|
||||
AttributeDeclHeader(d) ::= "<d.type> <d.name><if(d.initValue)> = <d.initValue><endif>"
|
||||
AttributeDecl(d) ::= "<d.type> <d.name>"
|
||||
|
|
|
@ -90,8 +90,6 @@ using namespace antlr4;
|
|||
|
||||
<if (file.genPackage)>namespace <file.genPackage> {<endif>
|
||||
|
||||
template \<typename T>
|
||||
class <file.grammarName>Visitor;
|
||||
<parser>
|
||||
|
||||
<if (file.genPackage)>
|
||||
|
@ -104,7 +102,8 @@ ParserFile(file, parser, namedActions, contextSuperClass) ::= <<
|
|||
|
||||
<namedActions.preinclude>
|
||||
|
||||
<if (file.genListener)>#include "<file.grammarName>BaseListener.h"<endif>
|
||||
<if (file.genListener)>#include "<file.grammarName>Listener.h"<endif>
|
||||
<if (file.genVisitor)>#include "<file.grammarName>Visitor.h"<endif>
|
||||
|
||||
#include "<file.parser.name>.h"
|
||||
|
||||
|
@ -252,17 +251,14 @@ namespace <file.genPackage> {
|
|||
/**
|
||||
* This class provides an empty implementation of <file.grammarName>Visitor, which can be
|
||||
* extended to create a visitor which only needs to handle a subset of the available methods.
|
||||
*
|
||||
* @param \<T> The return type of the visit operation. Use void for operations with no return type.
|
||||
*/
|
||||
template \<typename T>
|
||||
class <file.grammarName>BaseVisitor : public tree::AbstractParseTreeVisitor\<T>, public <file.grammarName>Visitor\<T> {
|
||||
class <file.grammarName>BaseVisitor : public <file.grammarName>Visitor {
|
||||
public:
|
||||
<namedActions.basevisitordeclarations>
|
||||
|
||||
<file.visitorNames: { lname |
|
||||
virtual T* visit<lname; format = "cap">(<file.parserName>::<lname; format = "cap">Context *ctx) override {
|
||||
return tree::AbstractParseTreeVisitor\<T>::visitChildren(ctx);
|
||||
virtual antlrcpp::Any visit<lname; format = "cap">(<file.parserName>::<lname; format = "cap">Context *ctx) override {
|
||||
return visitChildren(ctx);
|
||||
\}
|
||||
}; separator="\n">
|
||||
|
||||
|
@ -309,14 +305,10 @@ VisitorFileHeader(file, header, namedActions) ::= <<
|
|||
<if(file.genPackage)>namespace <file.genPackage> {<endif>
|
||||
|
||||
/**
|
||||
* This template class defines an abstract visitor for a parse tree
|
||||
* This class defines an abstract visitor for a parse tree
|
||||
* produced by <file.parserName>.
|
||||
*
|
||||
* @param \<T> The return type of the visit operation. Use void for
|
||||
* operations with no return type.
|
||||
*/
|
||||
template \<typename T>
|
||||
class <file.grammarName>Visitor : public antlr4::tree::ParseTreeVisitor\<T> {
|
||||
class <file.grammarName>Visitor : public antlr4::tree::AbstractParseTreeVisitor {
|
||||
public:
|
||||
<namedActions.visitordeclarations>
|
||||
|
||||
|
@ -324,7 +316,7 @@ public:
|
|||
* Visit parse trees produced by <file.parserName>.
|
||||
*/
|
||||
<file.visitorNames: {lname |
|
||||
virtual T* visit<lname; format = "cap">(<file.parserName>::<lname; format = "cap">Context *context) = 0;
|
||||
virtual antlrcpp::Any visit<lname; format = "cap">(<file.parserName>::<lname; format = "cap">Context *context) = 0;
|
||||
}; separator="\n">
|
||||
|
||||
<if (namedActions.visitormembers)>
|
||||
|
|
Loading…
Reference in New Issue