diff options
| author | Patrick Schönberger | 2021-08-14 14:56:12 +0200 |
|---|---|---|
| committer | Patrick Schönberger | 2021-08-14 14:56:12 +0200 |
| commit | c6ad2948bb98d42f8e0883ef82cd14cd2d5eda60 (patch) | |
| tree | 9e83d6d8f61e56f5d3425b8709314d6bdb9315a9 /antlr4-cpp-runtime-4.9.2-source/runtime/src/tree | |
| parent | 9f94b672a5dc32da5ad01742bd4e976315a30d9c (diff) | |
| download | toc-main.tar.gz toc-main.zip | |
Diffstat (limited to 'antlr4-cpp-runtime-4.9.2-source/runtime/src/tree')
60 files changed, 3615 insertions, 0 deletions
diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/AbstractParseTreeVisitor.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/AbstractParseTreeVisitor.h new file mode 100644 index 0000000..d21795b --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/AbstractParseTreeVisitor.h @@ -0,0 +1,128 @@ +/* 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/ParseTreeVisitor.h" + +namespace antlr4 { +namespace tree { + + class ANTLR4CPP_PUBLIC AbstractParseTreeVisitor : public ParseTreeVisitor { + public: + /// The default implementation calls <seealso cref="ParseTree#accept"/> on the + /// specified tree. + virtual antlrcpp::Any visit(ParseTree *tree) override { + return tree->accept(this); + } + + /** + * <p>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.</p> + * + * <p>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.</p> + */ + virtual antlrcpp::Any visitChildren(ParseTree *node) override { + antlrcpp::Any result = defaultResult(); + size_t n = node->children.size(); + for (size_t i = 0; i < n; i++) { + if (!shouldVisitNextChild(node, result)) { + break; + } + + antlrcpp::Any childResult = node->children[i]->accept(this); + result = aggregateResult(result, childResult); + } + + return result; + } + + /// The default implementation returns the result of + /// <seealso cref="#defaultResult defaultResult"/>. + virtual antlrcpp::Any visitTerminal(TerminalNode * /*node*/) override { + return defaultResult(); + } + + /// The default implementation returns the result of + /// <seealso cref="#defaultResult defaultResult"/>. + 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 + /// <seealso cref="#visitTerminal visitTerminal"/>, <seealso cref="#visitErrorNode visitErrorNode"/>. + /// The default implementation of <seealso cref="#visitChildren visitChildren"/> + /// initializes its aggregate result to this value. + /// <p/> + /// The base implementation returns {@code null}. + /// </summary> + /// <returns> The default value returned by visitor methods. </returns> + virtual antlrcpp::Any defaultResult() { + return nullptr; // support isNotNull + } + + /// <summary> + /// Aggregates the results of visiting multiple children of a node. After + /// either all children are visited or <seealso cref="#shouldVisitNextChild"/> returns + /// {@code false}, the aggregate value is returned as the result of + /// <seealso cref="#visitChildren"/>. + /// <p/> + /// The default implementation returns {@code nextResult}, meaning + /// <seealso cref="#visitChildren"/> will return the result of the last child visited + /// (or return the initial value if the node has no children). + /// </summary> + /// <param name="aggregate"> The previous aggregate value. In the default + /// implementation, the aggregate value is initialized to + /// <seealso cref="#defaultResult"/>, which is passed as the {@code aggregate} argument + /// to this method after the first child node is visited. </param> + /// <param name="nextResult"> The result of the immediately preceeding call to visit + /// a child node. + /// </param> + /// <returns> The updated aggregate result. </returns> + virtual antlrcpp::Any aggregateResult(antlrcpp::Any /*aggregate*/, const antlrcpp::Any &nextResult) { + return nextResult; + } + + /// <summary> + /// This method is called after visiting each child in + /// <seealso cref="#visitChildren"/>. 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 <seealso cref="#defaultResult"/>. This method is not called after the last + /// child is visited. + /// <p/> + /// 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. + /// </summary> + /// <param name="node"> The <seealso cref="ParseTree"/> whose children are currently being + /// visited. </param> + /// <param name="currentResult"> The current aggregate result of the children visited + /// to the current point. + /// </param> + /// <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(ParseTree * /*node*/, const antlrcpp::Any &/*currentResult*/) { + return true; + } + + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNode.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNode.cpp new file mode 100644 index 0000000..ade2539 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNode.cpp @@ -0,0 +1,9 @@ +/* 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 "tree/ErrorNode.h" + +antlr4::tree::ErrorNode::~ErrorNode() { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNode.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNode.h new file mode 100644 index 0000000..619f44d --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNode.h @@ -0,0 +1,19 @@ +/* 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/TerminalNode.h" + +namespace antlr4 { +namespace tree { + + class ANTLR4CPP_PUBLIC ErrorNode : public virtual TerminalNode { + public: + ~ErrorNode() override; + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNodeImpl.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNodeImpl.cpp new file mode 100644 index 0000000..fde942d --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNodeImpl.cpp @@ -0,0 +1,23 @@ +/* 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 "Exceptions.h" +#include "tree/ParseTreeVisitor.h" + +#include "tree/ErrorNodeImpl.h" + +using namespace antlr4; +using namespace antlr4::misc; +using namespace antlr4::tree; + +ErrorNodeImpl::ErrorNodeImpl(Token *token) : TerminalNodeImpl(token) { +} + +ErrorNodeImpl::~ErrorNodeImpl() { +} + +antlrcpp::Any ErrorNodeImpl::accept(ParseTreeVisitor *visitor) { + return visitor->visitErrorNode(this); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNodeImpl.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNodeImpl.h new file mode 100644 index 0000000..b64b6f9 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ErrorNodeImpl.h @@ -0,0 +1,33 @@ +/* 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/ErrorNode.h" +#include "tree/TerminalNodeImpl.h" +#include "misc/Interval.h" + +#include "support/Any.h" + +namespace antlr4 { +namespace tree { + + /// <summary> + /// Represents a token that was consumed during resynchronization + /// rather than during a valid match operation. For example, + /// we will create this kind of a node during single token insertion + /// and deletion as well as during "consume until error recovery set" + /// upon no viable alternative exceptions. + /// </summary> + class ANTLR4CPP_PUBLIC ErrorNodeImpl : public virtual TerminalNodeImpl, public virtual ErrorNode { + public: + ErrorNodeImpl(Token *token); + ~ErrorNodeImpl() override; + + virtual antlrcpp::Any accept(ParseTreeVisitor *visitor) override; + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/IterativeParseTreeWalker.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/IterativeParseTreeWalker.cpp new file mode 100644 index 0000000..a4b3efd --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/IterativeParseTreeWalker.cpp @@ -0,0 +1,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/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); + } +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/IterativeParseTreeWalker.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/IterativeParseTreeWalker.h new file mode 100644 index 0000000..8957d87 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/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/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTree.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTree.cpp new file mode 100644 index 0000000..b975a40 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTree.cpp @@ -0,0 +1,15 @@ +/* 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 "tree/ParseTree.h" + +using namespace antlr4::tree; + +ParseTree::ParseTree() : parent(nullptr) { +} + +bool ParseTree::operator == (const ParseTree &other) const { + return &other == this; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTree.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTree.h new file mode 100644 index 0000000..3b91be8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTree.h @@ -0,0 +1,102 @@ +/* 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 "support/Any.h" + +namespace antlr4 { +namespace tree { + + /// An interface to access the tree of <seealso cref="RuleContext"/> objects created + /// during a parse that makes the data structure look like a simple parse tree. + /// This node represents both internal nodes, rule invocations, + /// and leaf nodes, token matches. + /// + /// The payload is either a <seealso cref="Token"/> or a <seealso cref="RuleContext"/> object. + // ml: This class unites 4 Java classes: RuleNode, ParseTree, SyntaxTree and Tree. + class ANTLR4CPP_PUBLIC ParseTree { + public: + ParseTree(); + ParseTree(ParseTree const&) = delete; + virtual ~ParseTree() {} + + ParseTree& operator=(ParseTree const&) = delete; + + /// The parent of this node. If the return value is null, then this + /// node is the root of the tree. + ParseTree *parent; + + /// If we are debugging or building a parse tree for a visitor, + /// we need to track all of the tokens and rule invocations associated + /// with this rule's context. This is empty for parsing w/o tree constr. + /// operation because we don't the need to track the details about + /// how we parse this rule. + // ml: memory is not managed here, but by the owning class. This is just for the structure. + std::vector<ParseTree *> children; + + /// Print out a whole tree, not just a node, in LISP format + /// {@code (root child1 .. childN)}. Print just a node if this is a leaf. + virtual std::string toStringTree(bool pretty = false) = 0; + virtual std::string toString() = 0; + + /// Specialize toStringTree so that it can print out more information + /// based upon the parser. + virtual std::string toStringTree(Parser *parser, bool pretty = false) = 0; + + virtual bool operator == (const ParseTree &other) const; + + /// 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; + + /// 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. + virtual std::string getText() = 0; + + /** + * Return an {@link Interval} indicating the index in the + * {@link TokenStream} of the first and last token associated with this + * subtree. If this node is a leaf, then the interval represents a single + * token and has interval i..i for token index i. + * + * <p>An interval of i..i-1 indicates an empty interval at position + * i in the input stream, where 0 <= i <= the size of the input + * token stream. Currently, the code base can only have i=0..n-1 but + * in concept one could have an empty interval after EOF. </p> + * + * <p>If source interval is unknown, this returns {@link Interval#INVALID}.</p> + * + * <p>As a weird special case, the source interval for rules matched after + * EOF is unspecified.</p> + */ + virtual misc::Interval getSourceInterval() = 0; + }; + + // A class to help managing ParseTree instances without the need of a shared_ptr. + class ANTLR4CPP_PUBLIC ParseTreeTracker { + public: + template<typename T, typename ... Args> + T* createInstance(Args&& ... args) { + static_assert(std::is_base_of<ParseTree, T>::value, "Argument must be a parse tree type"); + T* result = new T(args...); + _allocated.push_back(result); + return result; + } + + void reset() { + for (auto * entry : _allocated) + delete entry; + _allocated.clear(); + } + + private: + std::vector<ParseTree *> _allocated; + }; + + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeListener.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeListener.cpp new file mode 100644 index 0000000..ce12297 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeListener.cpp @@ -0,0 +1,9 @@ +/* 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 "ParseTreeListener.h" + +antlr4::tree::ParseTreeListener::~ParseTreeListener() { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeListener.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeListener.h new file mode 100644 index 0000000..6a7f96a --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeListener.h @@ -0,0 +1,39 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { + + /** This interface describes the minimal core of methods triggered + * by {@link ParseTreeWalker}. E.g., + * + * ParseTreeWalker walker = new ParseTreeWalker(); + * walker.walk(myParseTreeListener, myParseTree); <-- triggers events in your listener + * + * If you want to trigger events in multiple listeners during a single + * tree walk, you can use the ParseTreeDispatcher object available at + * + * https://github.com/antlr/antlr4/issues/841 + */ + class ANTLR4CPP_PUBLIC ParseTreeListener { + public: + virtual ~ParseTreeListener(); + + virtual void visitTerminal(TerminalNode *node) = 0; + virtual void visitErrorNode(ErrorNode *node) = 0; + virtual void enterEveryRule(ParserRuleContext *ctx) = 0; + virtual void exitEveryRule(ParserRuleContext *ctx) = 0; + + bool operator == (const ParseTreeListener &other) { + return this == &other; + } + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeProperty.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeProperty.h new file mode 100644 index 0000000..8669a10 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeProperty.h @@ -0,0 +1,50 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { + + /// <summary> + /// Associate a property with a parse tree node. Useful with parse tree listeners + /// that need to associate values with particular tree nodes, kind of like + /// specifying a return value for the listener event method that visited a + /// particular node. Example: + /// + /// <pre> + /// ParseTreeProperty<Integer> values = new ParseTreeProperty<Integer>(); + /// values.put(tree, 36); + /// int x = values.get(tree); + /// values.removeFrom(tree); + /// </pre> + /// + /// You would make one decl (values here) in the listener and use lots of times + /// in your event methods. + /// </summary> + template<typename V> + class ANTLR4CPP_PUBLIC ParseTreeProperty { + public: + virtual ~ParseTreeProperty() {} + virtual V get(ParseTree *node) { + return _annotations[node]; + } + virtual void put(ParseTree *node, V value) { + _annotations[node] = value; + } + virtual V removeFrom(ParseTree *node) { + auto value = _annotations[node]; + _annotations.erase(node); + return value; + } + + protected: + std::map<ParseTree*, V> _annotations; + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeVisitor.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeVisitor.cpp new file mode 100644 index 0000000..a329919 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeVisitor.cpp @@ -0,0 +1,9 @@ +/* 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 "ParseTreeVisitor.h" + +antlr4::tree::ParseTreeVisitor::~ParseTreeVisitor() { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeVisitor.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeVisitor.h new file mode 100644 index 0000000..5a08599 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeVisitor.h @@ -0,0 +1,57 @@ +/* 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 "support/Any.h" + +namespace antlr4 { +namespace tree { + + /// <summary> + /// This interface defines the basic notion of a parse tree visitor. Generated + /// visitors implement this interface and the {@code XVisitor} interface for + /// grammar {@code X}. + /// </summary> + /// @param <T> The return type of the visit operation. Use <seealso cref="Void"/> for + /// operations with no return type. </param> + // 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(); + + /// <summary> + /// Visit a parse tree, and return a user-defined result of the operation. + /// </summary> + /// <param name="tree"> The <seealso cref="ParseTree"/> to visit. </param> + /// <returns> The result of visiting the parse tree. </returns> + virtual antlrcpp::Any visit(ParseTree *tree) = 0; + + /// <summary> + /// Visit the children of a node, and return a user-defined result of the + /// operation. + /// </summary> + /// <param name="node"> The <seealso cref="ParseTree"/> whose children should be visited. </param> + /// <returns> The result of visiting the children of the node. </returns> + virtual antlrcpp::Any visitChildren(ParseTree *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 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 antlrcpp::Any visitErrorNode(ErrorNode *node) = 0; + + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeWalker.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeWalker.cpp new file mode 100644 index 0000000..998c9ed --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeWalker.cpp @@ -0,0 +1,49 @@ +/* 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 "tree/ErrorNode.h" +#include "ParserRuleContext.h" +#include "tree/ParseTreeListener.h" +#include "support/CPPUtils.h" + +#include "tree/IterativeParseTreeWalker.h" +#include "tree/ParseTreeWalker.h" + +using namespace antlr4::tree; +using namespace antlrcpp; + +static IterativeParseTreeWalker defaultWalker; +ParseTreeWalker &ParseTreeWalker::DEFAULT = defaultWalker; + +ParseTreeWalker::~ParseTreeWalker() { +} + +void ParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const { + if (is<ErrorNode *>(t)) { + listener->visitErrorNode(dynamic_cast<ErrorNode *>(t)); + return; + } else if (is<TerminalNode *>(t)) { + listener->visitTerminal(dynamic_cast<TerminalNode *>(t)); + return; + } + + enterRule(listener, t); + for (auto &child : t->children) { + walk(listener, child); + } + exitRule(listener, t); +} + +void ParseTreeWalker::enterRule(ParseTreeListener *listener, ParseTree *r) const { + ParserRuleContext *ctx = dynamic_cast<ParserRuleContext *>(r); + listener->enterEveryRule(ctx); + ctx->enterRule(listener); +} + +void ParseTreeWalker::exitRule(ParseTreeListener *listener, ParseTree *r) const { + ParserRuleContext *ctx = dynamic_cast<ParserRuleContext *>(r); + ctx->exitRule(listener); + listener->exitEveryRule(ctx); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeWalker.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeWalker.h new file mode 100644 index 0000000..166ad80 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/ParseTreeWalker.h @@ -0,0 +1,55 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { + + class ANTLR4CPP_PUBLIC ParseTreeWalker { + public: + static ParseTreeWalker &DEFAULT; + + virtual ~ParseTreeWalker(); + + /** + * <summary> + * Performs a walk on the given parse tree starting at the root and going down recursively + * with depth-first search. On each node, <seealso cref="ParseTreeWalker#enterRule"/> is called before + * recursively walking down into child nodes, then + * <seealso cref="ParseTreeWalker#exitRule"/> is called after the recursive call to wind up. + * </summary> + * <param name='listener'> The listener used by the walker to process grammar rules </param> + * <param name='t'> The parse tree to be walked on </param> + */ + virtual void walk(ParseTreeListener *listener, ParseTree *t) const; + + protected: + + /** + * <summary> + * Enters a grammar rule by first triggering the generic event <seealso cref="ParseTreeListener#enterEveryRule"/> + * then by triggering the event specific to the given parse tree node + * </summary> + * <param name='listener'> The listener responding to the trigger events </param> + * <param name='r'> The grammar rule containing the rule context </param> + */ + virtual void enterRule(ParseTreeListener *listener, ParseTree *r) const; + + /** + * <summary> + * Exits a grammar rule by first triggering the event specific to the given parse tree node + * then by triggering the generic event <seealso cref="ParseTreeListener#exitEveryRule"/> + * </summary> + * <param name='listener'> The listener responding to the trigger events </param> + * <param name='r'> The grammar rule containing the rule context </param> + */ + virtual void exitRule(ParseTreeListener *listener, ParseTree *r) const; + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNode.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNode.cpp new file mode 100644 index 0000000..d630469 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNode.cpp @@ -0,0 +1,9 @@ +/* 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 "tree/TerminalNode.h" + +antlr4::tree::TerminalNode::~TerminalNode() { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNode.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNode.h new file mode 100644 index 0000000..7108f70 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNode.h @@ -0,0 +1,32 @@ +/* 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" + +namespace antlr4 { +namespace tree { + + class ANTLR4CPP_PUBLIC TerminalNode : public ParseTree { + public: + ~TerminalNode() override; + + virtual Token* getSymbol() = 0; + + /** Set the parent for this leaf node. + * + * Technically, this is not backward compatible as it changes + * the interface but no one was able to create custom + * TerminalNodes anyway so I'm adding as it improves internal + * code quality. + * + * @since 4.7 + */ + virtual void setParent(RuleContext *parent) = 0; + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNodeImpl.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNodeImpl.cpp new file mode 100644 index 0000000..7ab121b --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNodeImpl.cpp @@ -0,0 +1,57 @@ +/* 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 "misc/Interval.h" +#include "Token.h" +#include "RuleContext.h" +#include "tree/ParseTreeVisitor.h" + +#include "tree/TerminalNodeImpl.h" + +using namespace antlr4; +using namespace antlr4::tree; + +TerminalNodeImpl::TerminalNodeImpl(Token *symbol_) : symbol(symbol_) { +} + +Token* TerminalNodeImpl::getSymbol() { + return symbol; +} + +void TerminalNodeImpl::setParent(RuleContext *parent_) { + this->parent = parent_; +} + +misc::Interval TerminalNodeImpl::getSourceInterval() { + if (symbol == nullptr) { + return misc::Interval::INVALID; + } + + size_t tokenIndex = symbol->getTokenIndex(); + return misc::Interval(tokenIndex, tokenIndex); +} + +antlrcpp::Any TerminalNodeImpl::accept(ParseTreeVisitor *visitor) { + return visitor->visitTerminal(this); +} + +std::string TerminalNodeImpl::getText() { + return symbol->getText(); +} + +std::string TerminalNodeImpl::toStringTree(Parser * /*parser*/, bool /*pretty*/) { + return toString(); +} + +std::string TerminalNodeImpl::toString() { + if (symbol->getType() == Token::EOF) { + return "<EOF>"; + } + return symbol->getText(); +} + +std::string TerminalNodeImpl::toStringTree(bool /*pretty*/) { + return toString(); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNodeImpl.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNodeImpl.h new file mode 100644 index 0000000..6f65d82 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/TerminalNodeImpl.h @@ -0,0 +1,33 @@ +/* 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/TerminalNode.h" + +namespace antlr4 { +namespace tree { + + class ANTLR4CPP_PUBLIC TerminalNodeImpl : public virtual TerminalNode { + public: + Token *symbol; + + TerminalNodeImpl(Token *symbol); + + virtual Token* getSymbol() override; + virtual void setParent(RuleContext *parent) override; + virtual misc::Interval getSourceInterval() override; + + virtual antlrcpp::Any accept(ParseTreeVisitor *visitor) override; + + virtual std::string getText() override; + virtual std::string toStringTree(Parser *parser, bool pretty = false) override; + virtual std::string toString() override; + virtual std::string toStringTree(bool pretty = false) override; + + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/Trees.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/Trees.cpp new file mode 100644 index 0000000..34cfb74 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/Trees.cpp @@ -0,0 +1,241 @@ +/* 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 "tree/ErrorNode.h" +#include "Parser.h" +#include "ParserRuleContext.h" +#include "support/CPPUtils.h" +#include "tree/TerminalNodeImpl.h" +#include "atn/ATN.h" +#include "misc/Interval.h" +#include "Token.h" +#include "CommonToken.h" +#include "misc/Predicate.h" + +#include "tree/Trees.h" + +using namespace antlr4; +using namespace antlr4::misc; +using namespace antlr4::tree; + +using namespace antlrcpp; + +Trees::Trees() { +} + +std::string Trees::toStringTree(ParseTree *t, bool pretty) { + return toStringTree(t, nullptr, pretty); +} + +std::string Trees::toStringTree(ParseTree *t, Parser *recog, bool pretty) { + if (recog == nullptr) + return toStringTree(t, std::vector<std::string>(), pretty); + return toStringTree(t, recog->getRuleNames(), pretty); +} + +std::string Trees::toStringTree(ParseTree *t, const std::vector<std::string> &ruleNames, bool pretty) { + std::string temp = antlrcpp::escapeWhitespace(Trees::getNodeText(t, ruleNames), false); + if (t->children.empty()) { + return temp; + } + + std::stringstream ss; + ss << "(" << temp << ' '; + + // Implement the recursive walk as iteration to avoid trouble with deep nesting. + std::stack<size_t> stack; + size_t childIndex = 0; + ParseTree *run = t; + size_t indentationLevel = 1; + while (childIndex < run->children.size()) { + if (childIndex > 0) { + ss << ' '; + } + ParseTree *child = run->children[childIndex]; + temp = antlrcpp::escapeWhitespace(Trees::getNodeText(child, ruleNames), false); + if (!child->children.empty()) { + // Go deeper one level. + stack.push(childIndex); + run = child; + childIndex = 0; + if (pretty) { + ++indentationLevel; + ss << std::endl; + for (size_t i = 0; i < indentationLevel; ++i) { + ss << " "; + } + } + ss << "(" << temp << " "; + } else { + ss << temp; + while (++childIndex == run->children.size()) { + if (stack.size() > 0) { + // Reached the end of the current level. See if we can step up from here. + childIndex = stack.top(); + stack.pop(); + run = run->parent; + if (pretty) { + --indentationLevel; + } + ss << ")"; + } else { + break; + } + } + } + } + + ss << ")"; + return ss.str(); +} + +std::string Trees::getNodeText(ParseTree *t, Parser *recog) { + return getNodeText(t, recog->getRuleNames()); +} + +std::string Trees::getNodeText(ParseTree *t, const std::vector<std::string> &ruleNames) { + if (ruleNames.size() > 0) { + if (is<RuleContext *>(t)) { + size_t ruleIndex = dynamic_cast<RuleContext *>(t)->getRuleIndex(); + std::string ruleName = ruleNames[ruleIndex]; + size_t altNumber = dynamic_cast<RuleContext *>(t)->getAltNumber(); + if (altNumber != atn::ATN::INVALID_ALT_NUMBER) { + return ruleName + ":" + std::to_string(altNumber); + } + return ruleName; + } else if (is<ErrorNode *>(t)) { + return t->toString(); + } else if (is<TerminalNode *>(t)) { + Token *symbol = dynamic_cast<TerminalNode *>(t)->getSymbol(); + if (symbol != nullptr) { + std::string s = symbol->getText(); + return s; + } + } + } + // no recog for rule names + if (is<RuleContext *>(t)) { + return dynamic_cast<RuleContext *>(t)->getText(); + } + + if (is<TerminalNodeImpl *>(t)) { + return dynamic_cast<TerminalNodeImpl *>(t)->getSymbol()->getText(); + } + + return ""; +} + +std::vector<ParseTree *> Trees::getAncestors(ParseTree *t) { + std::vector<ParseTree *> ancestors; + ParseTree *parent = t->parent; + while (parent != nullptr) { + ancestors.insert(ancestors.begin(), parent); // insert at start + parent = parent->parent; + } + return ancestors; +} + +template<typename T> +static void _findAllNodes(ParseTree *t, size_t index, bool findTokens, std::vector<T> &nodes) { + // check this node (the root) first + if (findTokens && is<TerminalNode *>(t)) { + TerminalNode *tnode = dynamic_cast<TerminalNode *>(t); + if (tnode->getSymbol()->getType() == index) { + nodes.push_back(t); + } + } else if (!findTokens && is<ParserRuleContext *>(t)) { + ParserRuleContext *ctx = dynamic_cast<ParserRuleContext *>(t); + if (ctx->getRuleIndex() == index) { + nodes.push_back(t); + } + } + // check children + for (size_t i = 0; i < t->children.size(); i++) { + _findAllNodes(t->children[i], index, findTokens, nodes); + } +} + +bool Trees::isAncestorOf(ParseTree *t, ParseTree *u) { + if (t == nullptr || u == nullptr || t->parent == nullptr) { + return false; + } + + ParseTree *p = u->parent; + while (p != nullptr) { + if (t == p) { + return true; + } + p = p->parent; + } + return false; +} + +std::vector<ParseTree *> Trees::findAllTokenNodes(ParseTree *t, size_t ttype) { + return findAllNodes(t, ttype, true); +} + +std::vector<ParseTree *> Trees::findAllRuleNodes(ParseTree *t, size_t ruleIndex) { + return findAllNodes(t, ruleIndex, false); +} + +std::vector<ParseTree *> Trees::findAllNodes(ParseTree *t, size_t index, bool findTokens) { + std::vector<ParseTree *> nodes; + _findAllNodes<ParseTree *>(t, index, findTokens, nodes); + return nodes; +} + +std::vector<ParseTree *> Trees::getDescendants(ParseTree *t) { + std::vector<ParseTree *> nodes; + nodes.push_back(t); + std::size_t n = t->children.size(); + for (size_t i = 0 ; i < n ; i++) { + auto descentants = getDescendants(t->children[i]); + for (auto *entry: descentants) { + nodes.push_back(entry); + } + } + return nodes; +} + +std::vector<ParseTree *> Trees::descendants(ParseTree *t) { + return getDescendants(t); +} + +ParserRuleContext* Trees::getRootOfSubtreeEnclosingRegion(ParseTree *t, size_t startTokenIndex, size_t stopTokenIndex) { + size_t n = t->children.size(); + for (size_t i = 0; i < n; i++) { + ParserRuleContext *r = getRootOfSubtreeEnclosingRegion(t->children[i], startTokenIndex, stopTokenIndex); + if (r != nullptr) { + return r; + } + } + + if (is<ParserRuleContext *>(t)) { + ParserRuleContext *r = dynamic_cast<ParserRuleContext *>(t); + if (startTokenIndex >= r->getStart()->getTokenIndex() && // is range fully contained in t? + (r->getStop() == nullptr || stopTokenIndex <= r->getStop()->getTokenIndex())) { + // note: r.getStop()==null likely implies that we bailed out of parser and there's nothing to the right + return r; + } + } + return nullptr; +} + +ParseTree * Trees::findNodeSuchThat(ParseTree *t, Ref<Predicate> const& pred) { + if (pred->test(t)) { + return t; + } + + size_t n = t->children.size(); + for (size_t i = 0 ; i < n ; ++i) { + ParseTree *u = findNodeSuchThat(t->children[i], pred); + if (u != nullptr) { + return u; + } + } + + return nullptr; +} + diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/Trees.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/Trees.h new file mode 100644 index 0000000..d9d0462 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/Trees.h @@ -0,0 +1,78 @@ +/* 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/TerminalNode.h" +#include "ParserRuleContext.h" +#include "Recognizer.h" + +namespace antlr4 { +namespace tree { + + /// A set of utility routines useful for all kinds of ANTLR trees. + class ANTLR4CPP_PUBLIC Trees { + public: + /// Print out a whole tree in LISP form. getNodeText is used on the + /// node payloads to get the text for the nodes. Detect + /// parse trees and extract data appropriately. + static std::string toStringTree(ParseTree *t, bool pretty = false); + + /// Print out a whole tree in LISP form. getNodeText is used on the + /// node payloads to get the text for the nodes. Detect + /// parse trees and extract data appropriately. + static std::string toStringTree(ParseTree *t, Parser *recog, bool pretty = false); + + /// Print out a whole tree in LISP form. getNodeText is used on the + /// node payloads to get the text for the nodes. Detect + /// parse trees and extract data appropriately. + static std::string toStringTree(ParseTree *t, const std::vector<std::string> &ruleNames, bool pretty = false); + static std::string getNodeText(ParseTree *t, Parser *recog); + static std::string getNodeText(ParseTree *t, const std::vector<std::string> &ruleNames); + + /// Return a list of all ancestors of this node. The first node of + /// list is the root and the last is the parent of this node. + static std::vector<ParseTree *> getAncestors(ParseTree *t); + + /** Return true if t is u's parent or a node on path to root from u. + * Use == not equals(). + * + * @since 4.5.1 + */ + static bool isAncestorOf(ParseTree *t, ParseTree *u); + static std::vector<ParseTree *> findAllTokenNodes(ParseTree *t, size_t ttype); + static std::vector<ParseTree *> findAllRuleNodes(ParseTree *t, size_t ruleIndex); + static std::vector<ParseTree *> findAllNodes(ParseTree *t, size_t index, bool findTokens); + + /** Get all descendents; includes t itself. + * + * @since 4.5.1 + */ + static std::vector<ParseTree *> getDescendants(ParseTree *t); + + /** @deprecated */ + static std::vector<ParseTree *> descendants(ParseTree *t); + + /** Find smallest subtree of t enclosing range startTokenIndex..stopTokenIndex + * inclusively using postorder traversal. Recursive depth-first-search. + * + * @since 4.5.1 + */ + static ParserRuleContext* getRootOfSubtreeEnclosingRegion(ParseTree *t, + size_t startTokenIndex, // inclusive + size_t stopTokenIndex); // inclusive + + /** Return first node satisfying the pred + * + * @since 4.5.1 + */ + static ParseTree* findNodeSuchThat(ParseTree *t, Ref<misc::Predicate> const& pred); + + private: + Trees(); + }; + +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp new file mode 100644 index 0000000..5320f91 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp @@ -0,0 +1,9 @@ +/* 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 "tree/pattern/Chunk.h" + +antlr4::tree::pattern::Chunk::~Chunk() { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h new file mode 100644 index 0000000..42e7838 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h @@ -0,0 +1,44 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A chunk is either a token tag, a rule tag, or a span of literal text within a + /// tree pattern. + /// <p/> + /// The method <seealso cref="ParseTreePatternMatcher#split(String)"/> returns a list of + /// chunks in preparation for creating a token stream by + /// <seealso cref="ParseTreePatternMatcher#tokenize(String)"/>. From there, we get a parse + /// tree from with <seealso cref="ParseTreePatternMatcher#compile(String, int)"/>. These + /// chunks are converted to <seealso cref="RuleTagToken"/>, <seealso cref="TokenTagToken"/>, or the + /// regular tokens of the text surrounding the tags. + /// </summary> + class ANTLR4CPP_PUBLIC Chunk { + public: + Chunk() = default; + Chunk(Chunk const&) = default; + virtual ~Chunk(); + + Chunk& operator=(Chunk const&) = default; + + /// This method returns a text representation of the tag chunk. Labeled tags + /// are returned in the form {@code label:tag}, and unlabeled tags are + /// returned as just the tag name. + virtual std::string toString() { + std::string str; + return str; + } + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp new file mode 100644 index 0000000..ce34b3f --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp @@ -0,0 +1,69 @@ +/* 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 "Exceptions.h" + +#include "tree/pattern/ParseTreeMatch.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; + +ParseTreeMatch::ParseTreeMatch(ParseTree *tree, const ParseTreePattern &pattern, + const std::map<std::string, std::vector<ParseTree *>> &labels, + ParseTree *mismatchedNode) + : _tree(tree), _pattern(pattern), _labels(labels), _mismatchedNode(mismatchedNode) { + if (tree == nullptr) { + throw IllegalArgumentException("tree cannot be nul"); + } +} + +ParseTreeMatch::~ParseTreeMatch() { +} + +ParseTree* ParseTreeMatch::get(const std::string &label) { + auto iterator = _labels.find(label); + if (iterator == _labels.end() || iterator->second.empty()) { + return nullptr; + } + + return iterator->second.back(); // return last if multiple +} + +std::vector<ParseTree *> ParseTreeMatch::getAll(const std::string &label) { + auto iterator = _labels.find(label); + if (iterator == _labels.end()) { + return {}; + } + + return iterator->second; +} + +std::map<std::string, std::vector<ParseTree *>>& ParseTreeMatch::getLabels() { + return _labels; +} + +ParseTree *ParseTreeMatch::getMismatchedNode() { + return _mismatchedNode; +} + +bool ParseTreeMatch::succeeded() { + return _mismatchedNode == nullptr; +} + +const ParseTreePattern& ParseTreeMatch::getPattern() { + return _pattern; +} + +ParseTree * ParseTreeMatch::getTree() { + return _tree; +} + +std::string ParseTreeMatch::toString() { + if (succeeded()) { + return "Match succeeded; found " + std::to_string(_labels.size()) + " labels"; + } else { + return "Match failed; found " + std::to_string(_labels.size()) + " labels"; + } +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h new file mode 100644 index 0000000..eefde46 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h @@ -0,0 +1,132 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// Represents the result of matching a ParseTree against a tree pattern. + class ANTLR4CPP_PUBLIC ParseTreeMatch { + private: + /// This is the backing field for getTree(). + ParseTree *_tree; + + /// This is the backing field for getPattern(). + const ParseTreePattern &_pattern; + + /// This is the backing field for getLabels(). + std::map<std::string, std::vector<ParseTree *>> _labels; + + /// This is the backing field for getMismatchedNode(). + ParseTree *_mismatchedNode; + + public: + /// <summary> + /// Constructs a new instance of <seealso cref="ParseTreeMatch"/> from the specified + /// parse tree and pattern. + /// </summary> + /// <param name="tree"> The parse tree to match against the pattern. </param> + /// <param name="pattern"> The parse tree pattern. </param> + /// <param name="labels"> A mapping from label names to collections of + /// <seealso cref="ParseTree"/> objects located by the tree pattern matching process. </param> + /// <param name="mismatchedNode"> The first node which failed to match the tree + /// pattern during the matching process. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code tree} is {@code null} </exception> + /// <exception cref="IllegalArgumentException"> if {@code pattern} is {@code null} </exception> + /// <exception cref="IllegalArgumentException"> if {@code labels} is {@code null} </exception> + ParseTreeMatch(ParseTree *tree, ParseTreePattern const& pattern, + const std::map<std::string, std::vector<ParseTree *>> &labels, ParseTree *mismatchedNode); + ParseTreeMatch(ParseTreeMatch const&) = default; + virtual ~ParseTreeMatch(); + + /// <summary> + /// Get the last node associated with a specific {@code label}. + /// <p/> + /// For example, for pattern {@code <id:ID>}, {@code get("id")} returns the + /// node matched for that {@code ID}. If more than one node + /// matched the specified label, only the last is returned. If there is + /// no node associated with the label, this returns {@code null}. + /// <p/> + /// Pattern tags like {@code <ID>} and {@code <expr>} without labels are + /// considered to be labeled with {@code ID} and {@code expr}, respectively. + /// </summary> + /// <param name="labe"> The label to check. + /// </param> + /// <returns> The last <seealso cref="ParseTree"/> to match a tag with the specified + /// label, or {@code null} if no parse tree matched a tag with the label. </returns> + virtual ParseTree* get(const std::string &label); + + /// <summary> + /// Return all nodes matching a rule or token tag with the specified label. + /// <p/> + /// If the {@code label} is the name of a parser rule or token in the + /// grammar, the resulting list will contain both the parse trees matching + /// rule or tags explicitly labeled with the label and the complete set of + /// parse trees matching the labeled and unlabeled tags in the pattern for + /// the parser rule or token. For example, if {@code label} is {@code "foo"}, + /// the result will contain <em>all</em> of the following. + /// + /// <ul> + /// <li>Parse tree nodes matching tags of the form {@code <foo:anyRuleName>} and + /// {@code <foo:AnyTokenName>}.</li> + /// <li>Parse tree nodes matching tags of the form {@code <anyLabel:foo>}.</li> + /// <li>Parse tree nodes matching tags of the form {@code <foo>}.</li> + /// </ul> + /// </summary> + /// <param name="labe"> The label. + /// </param> + /// <returns> A collection of all <seealso cref="ParseTree"/> nodes matching tags with + /// the specified {@code label}. If no nodes matched the label, an empty list + /// is returned. </returns> + virtual std::vector<ParseTree *> getAll(const std::string &label); + + /// <summary> + /// Return a mapping from label → [list of nodes]. + /// <p/> + /// The map includes special entries corresponding to the names of rules and + /// tokens referenced in tags in the original pattern. For additional + /// information, see the description of <seealso cref="#getAll(String)"/>. + /// </summary> + /// <returns> A mapping from labels to parse tree nodes. If the parse tree + /// pattern did not contain any rule or token tags, this map will be empty. </returns> + virtual std::map<std::string, std::vector<ParseTree *>>& getLabels(); + + /// <summary> + /// Get the node at which we first detected a mismatch. + /// </summary> + /// <returns> the node at which we first detected a mismatch, or {@code null} + /// if the match was successful. </returns> + virtual ParseTree* getMismatchedNode(); + + /// <summary> + /// Gets a value indicating whether the match operation succeeded. + /// </summary> + /// <returns> {@code true} if the match operation succeeded; otherwise, + /// {@code false}. </returns> + virtual bool succeeded(); + + /// <summary> + /// Get the tree pattern we are matching against. + /// </summary> + /// <returns> The tree pattern we are matching against. </returns> + virtual const ParseTreePattern& getPattern(); + + /// <summary> + /// Get the parse tree we are trying to match to a pattern. + /// </summary> + /// <returns> The <seealso cref="ParseTree"/> we are trying to match to a pattern. </returns> + virtual ParseTree* getTree(); + + virtual std::string toString(); + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp new file mode 100644 index 0000000..50f44c8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp @@ -0,0 +1,64 @@ +/* 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 "tree/ParseTree.h" +#include "tree/pattern/ParseTreePatternMatcher.h" +#include "tree/pattern/ParseTreeMatch.h" + +#include "tree/xpath/XPath.h" +#include "tree/xpath/XPathElement.h" + +#include "tree/pattern/ParseTreePattern.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; + +using namespace antlrcpp; + +ParseTreePattern::ParseTreePattern(ParseTreePatternMatcher *matcher, const std::string &pattern, int patternRuleIndex_, + ParseTree *patternTree) + : patternRuleIndex(patternRuleIndex_), _pattern(pattern), _patternTree(patternTree), _matcher(matcher) { +} + +ParseTreePattern::~ParseTreePattern() { +} + +ParseTreeMatch ParseTreePattern::match(ParseTree *tree) { + return _matcher->match(tree, *this); +} + +bool ParseTreePattern::matches(ParseTree *tree) { + return _matcher->match(tree, *this).succeeded(); +} + +std::vector<ParseTreeMatch> ParseTreePattern::findAll(ParseTree *tree, const std::string &xpath) { + xpath::XPath finder(_matcher->getParser(), xpath); + std::vector<ParseTree *> subtrees = finder.evaluate(tree); + std::vector<ParseTreeMatch> matches; + for (auto *t : subtrees) { + ParseTreeMatch aMatch = match(t); + if (aMatch.succeeded()) { + matches.push_back(aMatch); + } + } + return matches; +} + + +ParseTreePatternMatcher *ParseTreePattern::getMatcher() const { + return _matcher; +} + +std::string ParseTreePattern::getPattern() const { + return _pattern; +} + +int ParseTreePattern::getPatternRuleIndex() const { + return patternRuleIndex; +} + +ParseTree* ParseTreePattern::getPatternTree() const { + return _patternTree; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h new file mode 100644 index 0000000..d5b86ff --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h @@ -0,0 +1,105 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A pattern like {@code <ID> = <expr>;} converted to a <seealso cref="ParseTree"/> by + /// <seealso cref="ParseTreePatternMatcher#compile(String, int)"/>. + /// </summary> + class ANTLR4CPP_PUBLIC ParseTreePattern { + public: + /// <summary> + /// Construct a new instance of the <seealso cref="ParseTreePattern"/> class. + /// </summary> + /// <param name="matcher"> The <seealso cref="ParseTreePatternMatcher"/> which created this + /// tree pattern. </param> + /// <param name="pattern"> The tree pattern in concrete syntax form. </param> + /// <param name="patternRuleIndex"> The parser rule which serves as the root of the + /// tree pattern. </param> + /// <param name="patternTree"> The tree pattern in <seealso cref="ParseTree"/> form. </param> + ParseTreePattern(ParseTreePatternMatcher *matcher, const std::string &pattern, int patternRuleIndex, + ParseTree *patternTree); + ParseTreePattern(ParseTreePattern const&) = default; + virtual ~ParseTreePattern(); + + /// <summary> + /// Match a specific parse tree against this tree pattern. + /// </summary> + /// <param name="tree"> The parse tree to match against this tree pattern. </param> + /// <returns> A <seealso cref="ParseTreeMatch"/> object describing the result of the + /// match operation. The <seealso cref="ParseTreeMatch#succeeded()"/> method can be + /// used to determine whether or not the match was successful. </returns> + virtual ParseTreeMatch match(ParseTree *tree); + + /// <summary> + /// Determine whether or not a parse tree matches this tree pattern. + /// </summary> + /// <param name="tree"> The parse tree to match against this tree pattern. </param> + /// <returns> {@code true} if {@code tree} is a match for the current tree + /// pattern; otherwise, {@code false}. </returns> + virtual bool matches(ParseTree *tree); + + /// Find all nodes using XPath and then try to match those subtrees against + /// this tree pattern. + /// @param tree The ParseTree to match against this pattern. + /// @param xpath An expression matching the nodes + /// + /// @returns A collection of ParseTreeMatch objects describing the + /// successful matches. Unsuccessful matches are omitted from the result, + /// regardless of the reason for the failure. + virtual std::vector<ParseTreeMatch> findAll(ParseTree *tree, const std::string &xpath); + + /// <summary> + /// Get the <seealso cref="ParseTreePatternMatcher"/> which created this tree pattern. + /// </summary> + /// <returns> The <seealso cref="ParseTreePatternMatcher"/> which created this tree + /// pattern. </returns> + virtual ParseTreePatternMatcher *getMatcher() const; + + /// <summary> + /// Get the tree pattern in concrete syntax form. + /// </summary> + /// <returns> The tree pattern in concrete syntax form. </returns> + virtual std::string getPattern() const; + + /// <summary> + /// Get the parser rule which serves as the outermost rule for the tree + /// pattern. + /// </summary> + /// <returns> The parser rule which serves as the outermost rule for the tree + /// pattern. </returns> + virtual int getPatternRuleIndex() const; + + /// <summary> + /// Get the tree pattern as a <seealso cref="ParseTree"/>. The rule and token tags from + /// the pattern are present in the parse tree as terminal nodes with a symbol + /// of type <seealso cref="RuleTagToken"/> or <seealso cref="TokenTagToken"/>. + /// </summary> + /// <returns> The tree pattern as a <seealso cref="ParseTree"/>. </returns> + virtual ParseTree* getPatternTree() const; + + private: + const int patternRuleIndex; + + /// This is the backing field for <seealso cref="#getPattern()"/>. + const std::string _pattern; + + /// This is the backing field for <seealso cref="#getPatternTree()"/>. + ParseTree *_patternTree; + + /// This is the backing field for <seealso cref="#getMatcher()"/>. + ParseTreePatternMatcher *const _matcher; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp new file mode 100644 index 0000000..2e58a96 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp @@ -0,0 +1,371 @@ +/* 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 "tree/pattern/ParseTreePattern.h" +#include "tree/pattern/ParseTreeMatch.h" +#include "tree/TerminalNode.h" +#include "CommonTokenStream.h" +#include "ParserInterpreter.h" +#include "tree/pattern/TokenTagToken.h" +#include "ParserRuleContext.h" +#include "tree/pattern/RuleTagToken.h" +#include "tree/pattern/TagChunk.h" +#include "atn/ATN.h" +#include "Lexer.h" +#include "BailErrorStrategy.h" + +#include "ListTokenSource.h" +#include "tree/pattern/TextChunk.h" +#include "ANTLRInputStream.h" +#include "support/Arrays.h" +#include "Exceptions.h" +#include "support/StringUtils.h" +#include "support/CPPUtils.h" + +#include "tree/pattern/ParseTreePatternMatcher.h" + +using namespace antlr4; +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; +using namespace antlrcpp; + +ParseTreePatternMatcher::CannotInvokeStartRule::CannotInvokeStartRule(const RuntimeException &e) : RuntimeException(e.what()) { +} + +ParseTreePatternMatcher::CannotInvokeStartRule::~CannotInvokeStartRule() { +} + +ParseTreePatternMatcher::StartRuleDoesNotConsumeFullPattern::~StartRuleDoesNotConsumeFullPattern() { +} + +ParseTreePatternMatcher::ParseTreePatternMatcher(Lexer *lexer, Parser *parser) : _lexer(lexer), _parser(parser) { + InitializeInstanceFields(); +} + +ParseTreePatternMatcher::~ParseTreePatternMatcher() { +} + +void ParseTreePatternMatcher::setDelimiters(const std::string &start, const std::string &stop, const std::string &escapeLeft) { + if (start.empty()) { + throw IllegalArgumentException("start cannot be null or empty"); + } + + if (stop.empty()) { + throw IllegalArgumentException("stop cannot be null or empty"); + } + + _start = start; + _stop = stop; + _escape = escapeLeft; +} + +bool ParseTreePatternMatcher::matches(ParseTree *tree, const std::string &pattern, int patternRuleIndex) { + ParseTreePattern p = compile(pattern, patternRuleIndex); + return matches(tree, p); +} + +bool ParseTreePatternMatcher::matches(ParseTree *tree, const ParseTreePattern &pattern) { + std::map<std::string, std::vector<ParseTree *>> labels; + ParseTree *mismatchedNode = matchImpl(tree, pattern.getPatternTree(), labels); + return mismatchedNode == nullptr; +} + +ParseTreeMatch ParseTreePatternMatcher::match(ParseTree *tree, const std::string &pattern, int patternRuleIndex) { + ParseTreePattern p = compile(pattern, patternRuleIndex); + return match(tree, p); +} + +ParseTreeMatch ParseTreePatternMatcher::match(ParseTree *tree, const ParseTreePattern &pattern) { + std::map<std::string, std::vector<ParseTree *>> labels; + tree::ParseTree *mismatchedNode = matchImpl(tree, pattern.getPatternTree(), labels); + return ParseTreeMatch(tree, pattern, labels, mismatchedNode); +} + +ParseTreePattern ParseTreePatternMatcher::compile(const std::string &pattern, int patternRuleIndex) { + ListTokenSource tokenSrc(tokenize(pattern)); + CommonTokenStream tokens(&tokenSrc); + + ParserInterpreter parserInterp(_parser->getGrammarFileName(), _parser->getVocabulary(), + _parser->getRuleNames(), _parser->getATNWithBypassAlts(), &tokens); + + ParserRuleContext *tree = nullptr; + try { + parserInterp.setErrorHandler(std::make_shared<BailErrorStrategy>()); + tree = parserInterp.parse(patternRuleIndex); + } catch (ParseCancellationException &e) { +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026 + // rethrow_if_nested is not available before VS 2015. + throw e; +#else + std::rethrow_if_nested(e); // Unwrap the nested exception. +#endif + } catch (RecognitionException &re) { + throw re; +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026 + } catch (std::exception &e) { + // throw_with_nested is not available before VS 2015. + throw e; +#else + } catch (std::exception & /*e*/) { + std::throw_with_nested((const char*)"Cannot invoke start rule"); // Wrap any other exception. We should however probably use one of the ANTLR exceptions here. +#endif + } + + // Make sure tree pattern compilation checks for a complete parse + if (tokens.LA(1) != Token::EOF) { + throw StartRuleDoesNotConsumeFullPattern(); + } + + return ParseTreePattern(this, pattern, patternRuleIndex, tree); +} + +Lexer* ParseTreePatternMatcher::getLexer() { + return _lexer; +} + +Parser* ParseTreePatternMatcher::getParser() { + return _parser; +} + +ParseTree* ParseTreePatternMatcher::matchImpl(ParseTree *tree, ParseTree *patternTree, + std::map<std::string, std::vector<ParseTree *>> &labels) { + if (tree == nullptr) { + throw IllegalArgumentException("tree cannot be nul"); + } + + if (patternTree == nullptr) { + throw IllegalArgumentException("patternTree cannot be nul"); + } + + // x and <ID>, x and y, or x and x; or could be mismatched types + if (is<TerminalNode *>(tree) && is<TerminalNode *>(patternTree)) { + TerminalNode *t1 = dynamic_cast<TerminalNode *>(tree); + TerminalNode *t2 = dynamic_cast<TerminalNode *>(patternTree); + + ParseTree *mismatchedNode = nullptr; + // both are tokens and they have same type + if (t1->getSymbol()->getType() == t2->getSymbol()->getType()) { + if (is<TokenTagToken *>(t2->getSymbol())) { // x and <ID> + TokenTagToken *tokenTagToken = dynamic_cast<TokenTagToken *>(t2->getSymbol()); + + // track label->list-of-nodes for both token name and label (if any) + labels[tokenTagToken->getTokenName()].push_back(tree); + if (tokenTagToken->getLabel() != "") { + labels[tokenTagToken->getLabel()].push_back(tree); + } + } else if (t1->getText() == t2->getText()) { + // x and x + } else { + // x and y + if (mismatchedNode == nullptr) { + mismatchedNode = t1; + } + } + } else { + if (mismatchedNode == nullptr) { + mismatchedNode = t1; + } + } + + return mismatchedNode; + } + + if (is<ParserRuleContext *>(tree) && is<ParserRuleContext *>(patternTree)) { + ParserRuleContext *r1 = dynamic_cast<ParserRuleContext *>(tree); + ParserRuleContext *r2 = dynamic_cast<ParserRuleContext *>(patternTree); + ParseTree *mismatchedNode = nullptr; + + // (expr ...) and <expr> + RuleTagToken *ruleTagToken = getRuleTagToken(r2); + if (ruleTagToken != nullptr) { + //ParseTreeMatch *m = nullptr; // unused? + if (r1->getRuleIndex() == r2->getRuleIndex()) { + // track label->list-of-nodes for both rule name and label (if any) + labels[ruleTagToken->getRuleName()].push_back(tree); + if (ruleTagToken->getLabel() != "") { + labels[ruleTagToken->getLabel()].push_back(tree); + } + } else { + if (!mismatchedNode) { + mismatchedNode = r1; + } + } + + return mismatchedNode; + } + + // (expr ...) and (expr ...) + if (r1->children.size() != r2->children.size()) { + if (mismatchedNode == nullptr) { + mismatchedNode = r1; + } + + return mismatchedNode; + } + + std::size_t n = r1->children.size(); + for (size_t i = 0; i < n; i++) { + ParseTree *childMatch = matchImpl(r1->children[i], patternTree->children[i], labels); + if (childMatch) { + return childMatch; + } + } + + return mismatchedNode; + } + + // if nodes aren't both tokens or both rule nodes, can't match + return tree; +} + +RuleTagToken* ParseTreePatternMatcher::getRuleTagToken(ParseTree *t) { + if (t->children.size() == 1 && is<TerminalNode *>(t->children[0])) { + TerminalNode *c = dynamic_cast<TerminalNode *>(t->children[0]); + if (is<RuleTagToken *>(c->getSymbol())) { + return dynamic_cast<RuleTagToken *>(c->getSymbol()); + } + } + return nullptr; +} + +std::vector<std::unique_ptr<Token>> ParseTreePatternMatcher::tokenize(const std::string &pattern) { + // split pattern into chunks: sea (raw input) and islands (<ID>, <expr>) + std::vector<Chunk> chunks = split(pattern); + + // create token stream from text and tags + std::vector<std::unique_ptr<Token>> tokens; + for (auto chunk : chunks) { + if (is<TagChunk *>(&chunk)) { + TagChunk &tagChunk = (TagChunk&)chunk; + // add special rule token or conjure up new token from name + if (isupper(tagChunk.getTag()[0])) { + size_t ttype = _parser->getTokenType(tagChunk.getTag()); + if (ttype == Token::INVALID_TYPE) { + throw IllegalArgumentException("Unknown token " + tagChunk.getTag() + " in pattern: " + pattern); + } + tokens.emplace_back(new TokenTagToken(tagChunk.getTag(), (int)ttype, tagChunk.getLabel())); + } else if (islower(tagChunk.getTag()[0])) { + size_t ruleIndex = _parser->getRuleIndex(tagChunk.getTag()); + if (ruleIndex == INVALID_INDEX) { + throw IllegalArgumentException("Unknown rule " + tagChunk.getTag() + " in pattern: " + pattern); + } + size_t ruleImaginaryTokenType = _parser->getATNWithBypassAlts().ruleToTokenType[ruleIndex]; + tokens.emplace_back(new RuleTagToken(tagChunk.getTag(), ruleImaginaryTokenType, tagChunk.getLabel())); + } else { + throw IllegalArgumentException("invalid tag: " + tagChunk.getTag() + " in pattern: " + pattern); + } + } else { + TextChunk &textChunk = (TextChunk&)chunk; + ANTLRInputStream input(textChunk.getText()); + _lexer->setInputStream(&input); + std::unique_ptr<Token> t(_lexer->nextToken()); + while (t->getType() != Token::EOF) { + tokens.push_back(std::move(t)); + t = _lexer->nextToken(); + } + _lexer->setInputStream(nullptr); + } + } + + return tokens; +} + +std::vector<Chunk> ParseTreePatternMatcher::split(const std::string &pattern) { + size_t p = 0; + size_t n = pattern.length(); + std::vector<Chunk> chunks; + + // find all start and stop indexes first, then collect + std::vector<size_t> starts; + std::vector<size_t> stops; + while (p < n) { + if (p == pattern.find(_escape + _start,p)) { + p += _escape.length() + _start.length(); + } else if (p == pattern.find(_escape + _stop,p)) { + p += _escape.length() + _stop.length(); + } else if (p == pattern.find(_start,p)) { + starts.push_back(p); + p += _start.length(); + } else if (p == pattern.find(_stop,p)) { + stops.push_back(p); + p += _stop.length(); + } else { + p++; + } + } + + if (starts.size() > stops.size()) { + throw IllegalArgumentException("unterminated tag in pattern: " + pattern); + } + + if (starts.size() < stops.size()) { + throw IllegalArgumentException("missing start tag in pattern: " + pattern); + } + + size_t ntags = starts.size(); + for (size_t i = 0; i < ntags; i++) { + if (starts[i] >= stops[i]) { + throw IllegalArgumentException("tag delimiters out of order in pattern: " + pattern); + } + } + + // collect into chunks now + if (ntags == 0) { + std::string text = pattern.substr(0, n); + chunks.push_back(TextChunk(text)); + } + + if (ntags > 0 && starts[0] > 0) { // copy text up to first tag into chunks + std::string text = pattern.substr(0, starts[0]); + chunks.push_back(TextChunk(text)); + } + + for (size_t i = 0; i < ntags; i++) { + // copy inside of <tag> + std::string tag = pattern.substr(starts[i] + _start.length(), stops[i] - (starts[i] + _start.length())); + std::string ruleOrToken = tag; + std::string label = ""; + size_t colon = tag.find(':'); + if (colon != std::string::npos) { + label = tag.substr(0,colon); + ruleOrToken = tag.substr(colon + 1, tag.length() - (colon + 1)); + } + chunks.push_back(TagChunk(label, ruleOrToken)); + if (i + 1 < ntags) { + // copy from end of <tag> to start of next + std::string text = pattern.substr(stops[i] + _stop.length(), starts[i + 1] - (stops[i] + _stop.length())); + chunks.push_back(TextChunk(text)); + } + } + + if (ntags > 0) { + size_t afterLastTag = stops[ntags - 1] + _stop.length(); + if (afterLastTag < n) { // copy text from end of last tag to end + std::string text = pattern.substr(afterLastTag, n - afterLastTag); + chunks.push_back(TextChunk(text)); + } + } + + // strip out all backslashes from text chunks but not tags + for (size_t i = 0; i < chunks.size(); i++) { + Chunk &c = chunks[i]; + if (is<TextChunk *>(&c)) { + TextChunk &tc = (TextChunk&)c; + std::string unescaped = tc.getText(); + unescaped.erase(std::remove(unescaped.begin(), unescaped.end(), '\\'), unescaped.end()); + if (unescaped.length() < tc.getText().length()) { + chunks[i] = TextChunk(unescaped); + } + } + } + + return chunks; +} + +void ParseTreePatternMatcher::InitializeInstanceFields() { + _start = "<"; + _stop = ">"; + _escape = "\\"; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h new file mode 100644 index 0000000..e77c7bc --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h @@ -0,0 +1,185 @@ +/* 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 "Exceptions.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A tree pattern matching mechanism for ANTLR <seealso cref="ParseTree"/>s. + /// <p/> + /// Patterns are strings of source input text with special tags representing + /// token or rule references such as: + /// <p/> + /// {@code <ID> = <expr>;} + /// <p/> + /// Given a pattern start rule such as {@code statement}, this object constructs + /// a <seealso cref="ParseTree"/> with placeholders for the {@code ID} and {@code expr} + /// subtree. Then the <seealso cref="#match"/> routines can compare an actual + /// <seealso cref="ParseTree"/> from a parse with this pattern. Tag {@code <ID>} matches + /// any {@code ID} token and tag {@code <expr>} references the result of the + /// {@code expr} rule (generally an instance of {@code ExprContext}. + /// <p/> + /// Pattern {@code x = 0;} is a similar pattern that matches the same pattern + /// except that it requires the identifier to be {@code x} and the expression to + /// be {@code 0}. + /// <p/> + /// The <seealso cref="#matches"/> routines return {@code true} or {@code false} based + /// upon a match for the tree rooted at the parameter sent in. The + /// <seealso cref="#match"/> routines return a <seealso cref="ParseTreeMatch"/> object that + /// contains the parse tree, the parse tree pattern, and a map from tag name to + /// matched nodes (more below). A subtree that fails to match, returns with + /// <seealso cref="ParseTreeMatch#mismatchedNode"/> set to the first tree node that did not + /// match. + /// <p/> + /// For efficiency, you can compile a tree pattern in string form to a + /// <seealso cref="ParseTreePattern"/> object. + /// <p/> + /// See {@code TestParseTreeMatcher} for lots of examples. + /// <seealso cref="ParseTreePattern"/> has two static helper methods: + /// <seealso cref="ParseTreePattern#findAll"/> and <seealso cref="ParseTreePattern#match"/> that + /// are easy to use but not super efficient because they create new + /// <seealso cref="ParseTreePatternMatcher"/> objects each time and have to compile the + /// pattern in string form before using it. + /// <p/> + /// The lexer and parser that you pass into the <seealso cref="ParseTreePatternMatcher"/> + /// constructor are used to parse the pattern in string form. The lexer converts + /// the {@code <ID> = <expr>;} into a sequence of four tokens (assuming lexer + /// throws out whitespace or puts it on a hidden channel). Be aware that the + /// input stream is reset for the lexer (but not the parser; a + /// <seealso cref="ParserInterpreter"/> is created to parse the input.). Any user-defined + /// fields you have put into the lexer might get changed when this mechanism asks + /// it to scan the pattern string. + /// <p/> + /// Normally a parser does not accept token {@code <expr>} as a valid + /// {@code expr} but, from the parser passed in, we create a special version of + /// the underlying grammar representation (an <seealso cref="ATN"/>) that allows imaginary + /// tokens representing rules ({@code <expr>}) to match entire rules. We call + /// these <em>bypass alternatives</em>. + /// <p/> + /// Delimiters are {@code <} and {@code >}, with {@code \} as the escape string + /// by default, but you can set them to whatever you want using + /// <seealso cref="#setDelimiters"/>. You must escape both start and stop strings + /// {@code \<} and {@code \>}. + /// </summary> + class ANTLR4CPP_PUBLIC ParseTreePatternMatcher { + public: + class CannotInvokeStartRule : public RuntimeException { + public: + CannotInvokeStartRule(const RuntimeException &e); + ~CannotInvokeStartRule(); + }; + + // Fixes https://github.com/antlr/antlr4/issues/413 + // "Tree pattern compilation doesn't check for a complete parse" + class StartRuleDoesNotConsumeFullPattern : public RuntimeException { + public: + StartRuleDoesNotConsumeFullPattern() = default; + StartRuleDoesNotConsumeFullPattern(StartRuleDoesNotConsumeFullPattern const&) = default; + ~StartRuleDoesNotConsumeFullPattern(); + + StartRuleDoesNotConsumeFullPattern& operator=(StartRuleDoesNotConsumeFullPattern const&) = default; + }; + + /// Constructs a <seealso cref="ParseTreePatternMatcher"/> or from a <seealso cref="Lexer"/> and + /// <seealso cref="Parser"/> object. The lexer input stream is altered for tokenizing + /// the tree patterns. The parser is used as a convenient mechanism to get + /// the grammar name, plus token, rule names. + ParseTreePatternMatcher(Lexer *lexer, Parser *parser); + virtual ~ParseTreePatternMatcher(); + + /// <summary> + /// Set the delimiters used for marking rule and token tags within concrete + /// syntax used by the tree pattern parser. + /// </summary> + /// <param name="start"> The start delimiter. </param> + /// <param name="stop"> The stop delimiter. </param> + /// <param name="escapeLeft"> The escape sequence to use for escaping a start or stop delimiter. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code start} is {@code null} or empty. </exception> + /// <exception cref="IllegalArgumentException"> if {@code stop} is {@code null} or empty. </exception> + virtual void setDelimiters(const std::string &start, const std::string &stop, const std::string &escapeLeft); + + /// <summary> + /// Does {@code pattern} matched as rule {@code patternRuleIndex} match {@code tree}? </summary> + virtual bool matches(ParseTree *tree, const std::string &pattern, int patternRuleIndex); + + /// <summary> + /// Does {@code pattern} matched as rule patternRuleIndex match tree? Pass in a + /// compiled pattern instead of a string representation of a tree pattern. + /// </summary> + virtual bool matches(ParseTree *tree, const ParseTreePattern &pattern); + + /// <summary> + /// Compare {@code pattern} matched as rule {@code patternRuleIndex} against + /// {@code tree} and return a <seealso cref="ParseTreeMatch"/> object that contains the + /// matched elements, or the node at which the match failed. + /// </summary> + virtual ParseTreeMatch match(ParseTree *tree, const std::string &pattern, int patternRuleIndex); + + /// <summary> + /// Compare {@code pattern} matched against {@code tree} and return a + /// <seealso cref="ParseTreeMatch"/> object that contains the matched elements, or the + /// node at which the match failed. Pass in a compiled pattern instead of a + /// string representation of a tree pattern. + /// </summary> + virtual ParseTreeMatch match(ParseTree *tree, const ParseTreePattern &pattern); + + /// <summary> + /// For repeated use of a tree pattern, compile it to a + /// <seealso cref="ParseTreePattern"/> using this method. + /// </summary> + virtual ParseTreePattern compile(const std::string &pattern, int patternRuleIndex); + + /// <summary> + /// Used to convert the tree pattern string into a series of tokens. The + /// input stream is reset. + /// </summary> + virtual Lexer* getLexer(); + + /// <summary> + /// Used to collect to the grammar file name, token names, rule names for + /// used to parse the pattern into a parse tree. + /// </summary> + virtual Parser* getParser(); + + // ---- SUPPORT CODE ---- + + virtual std::vector<std::unique_ptr<Token>> tokenize(const std::string &pattern); + + /// Split "<ID> = <e:expr>;" into 4 chunks for tokenizing by tokenize(). + virtual std::vector<Chunk> split(const std::string &pattern); + + protected: + std::string _start; + std::string _stop; + std::string _escape; // e.g., \< and \> must escape BOTH! + + /// Recursively walk {@code tree} against {@code patternTree}, filling + /// {@code match.}<seealso cref="ParseTreeMatch#labels labels"/>. + /// + /// <returns> the first node encountered in {@code tree} which does not match + /// a corresponding node in {@code patternTree}, or {@code null} if the match + /// was successful. The specific node returned depends on the matching + /// algorithm used by the implementation, and may be overridden. </returns> + virtual ParseTree* matchImpl(ParseTree *tree, ParseTree *patternTree, std::map<std::string, std::vector<ParseTree *>> &labels); + + /// Is t <expr> subtree? + virtual RuleTagToken* getRuleTagToken(ParseTree *t); + + private: + Lexer *_lexer; + Parser *_parser; + + void InitializeInstanceFields(); + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp new file mode 100644 index 0000000..4e33f98 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp @@ -0,0 +1,77 @@ +/* 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 "Exceptions.h" + +#include "tree/pattern/RuleTagToken.h" + +using namespace antlr4::tree::pattern; + +RuleTagToken::RuleTagToken(const std::string &/*ruleName*/, int _bypassTokenType) : bypassTokenType(_bypassTokenType) { +} + +RuleTagToken::RuleTagToken(const std::string &ruleName, size_t bypassTokenType, const std::string &label) + : ruleName(ruleName), bypassTokenType(bypassTokenType), label(label) { + if (ruleName.empty()) { + throw IllegalArgumentException("ruleName cannot be null or empty."); + } + +} + +std::string RuleTagToken::getRuleName() const { + return ruleName; +} + +std::string RuleTagToken::getLabel() const { + return label; +} + +size_t RuleTagToken::getChannel() const { + return DEFAULT_CHANNEL; +} + +std::string RuleTagToken::getText() const { + if (label != "") { + return std::string("<") + label + std::string(":") + ruleName + std::string(">"); + } + + return std::string("<") + ruleName + std::string(">"); +} + +size_t RuleTagToken::getType() const { + return bypassTokenType; +} + +size_t RuleTagToken::getLine() const { + return 0; +} + +size_t RuleTagToken::getCharPositionInLine() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getTokenIndex() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getStartIndex() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getStopIndex() const { + return INVALID_INDEX; +} + +antlr4::TokenSource *RuleTagToken::getTokenSource() const { + return nullptr; +} + +antlr4::CharStream *RuleTagToken::getInputStream() const { + return nullptr; +} + +std::string RuleTagToken::toString() const { + return ruleName + ":" + std::to_string(bypassTokenType); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h new file mode 100644 index 0000000..368ae41 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h @@ -0,0 +1,117 @@ +/* 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 "Token.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A <seealso cref="Token"/> object representing an entire subtree matched by a parser + /// rule; e.g., {@code <expr>}. These tokens are created for <seealso cref="TagChunk"/> + /// chunks where the tag corresponds to a parser rule. + /// </summary> + class ANTLR4CPP_PUBLIC RuleTagToken : public Token { + /// <summary> + /// This is the backing field for <seealso cref="#getRuleName"/>. + /// </summary> + private: + const std::string ruleName; + + /// The token type for the current token. This is the token type assigned to + /// the bypass alternative for the rule during ATN deserialization. + const size_t bypassTokenType; + + /// This is the backing field for <seealso cref="#getLabe"/>. + const std::string label; + + public: + /// <summary> + /// Constructs a new instance of <seealso cref="RuleTagToken"/> with the specified rule + /// name and bypass token type and no label. + /// </summary> + /// <param name="ruleName"> The name of the parser rule this rule tag matches. </param> + /// <param name="bypassTokenType"> The bypass token type assigned to the parser rule. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code ruleName} is {@code null} + /// or empty. </exception> + RuleTagToken(const std::string &ruleName, int bypassTokenType); //this(ruleName, bypassTokenType, nullptr); + + /// <summary> + /// Constructs a new instance of <seealso cref="RuleTagToken"/> with the specified rule + /// name, bypass token type, and label. + /// </summary> + /// <param name="ruleName"> The name of the parser rule this rule tag matches. </param> + /// <param name="bypassTokenType"> The bypass token type assigned to the parser rule. </param> + /// <param name="label"> The label associated with the rule tag, or {@code null} if + /// the rule tag is unlabeled. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code ruleName} is {@code null} + /// or empty. </exception> + RuleTagToken(const std::string &ruleName, size_t bypassTokenType, const std::string &label); + + /// <summary> + /// Gets the name of the rule associated with this rule tag. + /// </summary> + /// <returns> The name of the parser rule associated with this rule tag. </returns> + std::string getRuleName() const; + + /// <summary> + /// Gets the label associated with the rule tag. + /// </summary> + /// <returns> The name of the label associated with the rule tag, or + /// {@code null} if this is an unlabeled rule tag. </returns> + std::string getLabel() const; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// Rule tag tokens are always placed on the <seealso cref="#DEFAULT_CHANNE"/>. + /// </summary> + virtual size_t getChannel() const override; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// This method returns the rule tag formatted with {@code <} and {@code >} + /// delimiters. + /// </summary> + virtual std::string getText() const override; + + /// Rule tag tokens have types assigned according to the rule bypass + /// transitions created during ATN deserialization. + virtual size_t getType() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns 0. + virtual size_t getLine() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getCharPositionInLine() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getTokenIndex() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getStartIndex() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getStopIndex() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns {@code null}. + virtual TokenSource *getTokenSource() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns {@code null}. + virtual CharStream *getInputStream() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> returns a string of the form {@code ruleName:bypassTokenType}. + virtual std::string toString() const override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp new file mode 100644 index 0000000..77f2b4c --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp @@ -0,0 +1,39 @@ +/* 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 "Exceptions.h" + +#include "tree/pattern/TagChunk.h" + +using namespace antlr4::tree::pattern; + +TagChunk::TagChunk(const std::string &tag) : TagChunk("", tag) { +} + +TagChunk::TagChunk(const std::string &label, const std::string &tag) : _tag(tag), _label(label) { + if (tag.empty()) { + throw IllegalArgumentException("tag cannot be null or empty"); + } + +} + +TagChunk::~TagChunk() { +} + +std::string TagChunk::getTag() { + return _tag; +} + +std::string TagChunk::getLabel() { + return _label; +} + +std::string TagChunk::toString() { + if (!_label.empty()) { + return _label + ":" + _tag; + } + + return _tag; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h new file mode 100644 index 0000000..3d0c9f8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h @@ -0,0 +1,86 @@ +/* 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 "Chunk.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// Represents a placeholder tag in a tree pattern. A tag can have any of the + /// following forms. + /// + /// <ul> + /// <li>{@code expr}: An unlabeled placeholder for a parser rule {@code expr}.</li> + /// <li>{@code ID}: An unlabeled placeholder for a token of type {@code ID}.</li> + /// <li>{@code e:expr}: A labeled placeholder for a parser rule {@code expr}.</li> + /// <li>{@code id:ID}: A labeled placeholder for a token of type {@code ID}.</li> + /// </ul> + /// + /// This class does not perform any validation on the tag or label names aside + /// from ensuring that the tag is a non-null, non-empty string. + /// </summary> + class ANTLR4CPP_PUBLIC TagChunk : public Chunk { + public: + /// <summary> + /// Construct a new instance of <seealso cref="TagChunk"/> using the specified tag and + /// no label. + /// </summary> + /// <param name="tag"> The tag, which should be the name of a parser rule or token + /// type. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code tag} is {@code null} or + /// empty. </exception> + TagChunk(const std::string &tag); + virtual ~TagChunk(); + + /// <summary> + /// Construct a new instance of <seealso cref="TagChunk"/> using the specified label + /// and tag. + /// </summary> + /// <param name="label"> The label for the tag. If this is {@code null}, the + /// <seealso cref="TagChunk"/> represents an unlabeled tag. </param> + /// <param name="tag"> The tag, which should be the name of a parser rule or token + /// type. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code tag} is {@code null} or + /// empty. </exception> + TagChunk(const std::string &label, const std::string &tag); + + /// <summary> + /// Get the tag for this chunk. + /// </summary> + /// <returns> The tag for the chunk. </returns> + std::string getTag(); + + /// <summary> + /// Get the label, if any, assigned to this chunk. + /// </summary> + /// <returns> The label assigned to this chunk, or {@code null} if no label is + /// assigned to the chunk. </returns> + std::string getLabel(); + + /// <summary> + /// This method returns a text representation of the tag chunk. Labeled tags + /// are returned in the form {@code label:tag}, and unlabeled tags are + /// returned as just the tag name. + /// </summary> + virtual std::string toString() override; + + private: + /// This is the backing field for <seealso cref="#getTag"/>. + const std::string _tag; + /// <summary> + /// This is the backing field for <seealso cref="#getLabe"/>. + /// </summary> + const std::string _label; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp new file mode 100644 index 0000000..f8dcfb0 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp @@ -0,0 +1,28 @@ +/* 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 "Exceptions.h" + +#include "tree/pattern/TextChunk.h" + +using namespace antlr4::tree::pattern; + +TextChunk::TextChunk(const std::string &text) : text(text) { + if (text == "") { + throw IllegalArgumentException("text cannot be nul"); + } + +} + +TextChunk::~TextChunk() { +} + +std::string TextChunk::getText() { + return text; +} + +std::string TextChunk::toString() { + return std::string("'") + text + std::string("'"); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h new file mode 100644 index 0000000..1cbc0dd --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h @@ -0,0 +1,51 @@ +/* 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 "Chunk.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// Represents a span of raw text (concrete syntax) between tags in a tree + /// pattern string. + /// </summary> + class ANTLR4CPP_PUBLIC TextChunk : public Chunk { + private: + /// <summary> + /// This is the backing field for <seealso cref="#getText"/>. + /// </summary> + const std::string text; + + /// <summary> + /// Constructs a new instance of <seealso cref="TextChunk"/> with the specified text. + /// </summary> + /// <param name="text"> The text of this chunk. </param> + /// <exception cref="IllegalArgumentException"> if {@code text} is {@code null}. </exception> + public: + TextChunk(const std::string &text); + virtual ~TextChunk(); + + /// <summary> + /// Gets the raw text of this chunk. + /// </summary> + /// <returns> The text of the chunk. </returns> + std::string getText(); + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// The implementation for <seealso cref="TextChunk"/> returns the result of + /// <seealso cref="#getText()"/> in single quotes. + /// </summary> + virtual std::string toString() override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp new file mode 100644 index 0000000..7d6cc9a --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp @@ -0,0 +1,36 @@ +/* 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 "tree/pattern/TokenTagToken.h" + +using namespace antlr4::tree::pattern; + +TokenTagToken::TokenTagToken(const std::string &/*tokenName*/, int type) + : CommonToken(type), tokenName(""), label("") { +} + +TokenTagToken::TokenTagToken(const std::string &tokenName, int type, const std::string &label) + : CommonToken(type), tokenName(tokenName), label(label) { +} + +std::string TokenTagToken::getTokenName() const { + return tokenName; +} + +std::string TokenTagToken::getLabel() const { + return label; +} + +std::string TokenTagToken::getText() const { + if (!label.empty()) { + return "<" + label + ":" + tokenName + ">"; + } + + return "<" + tokenName + ">"; +} + +std::string TokenTagToken::toString() const { + return tokenName + ":" + std::to_string(_type); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h new file mode 100644 index 0000000..9013fb8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h @@ -0,0 +1,80 @@ +/* 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 "CommonToken.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A <seealso cref="Token"/> object representing a token of a particular type; e.g., + /// {@code <ID>}. These tokens are created for <seealso cref="TagChunk"/> chunks where the + /// tag corresponds to a lexer rule or token type. + /// </summary> + class ANTLR4CPP_PUBLIC TokenTagToken : public CommonToken { + /// <summary> + /// This is the backing field for <seealso cref="#getTokenName"/>. + /// </summary> + private: + const std::string tokenName; + /// <summary> + /// This is the backing field for <seealso cref="#getLabe"/>. + /// </summary> + const std::string label; + + /// <summary> + /// Constructs a new instance of <seealso cref="TokenTagToken"/> for an unlabeled tag + /// with the specified token name and type. + /// </summary> + /// <param name="tokenName"> The token name. </param> + /// <param name="type"> The token type. </param> + public: + TokenTagToken(const std::string &tokenName, int type); //this(tokenName, type, nullptr); + + /// <summary> + /// Constructs a new instance of <seealso cref="TokenTagToken"/> with the specified + /// token name, type, and label. + /// </summary> + /// <param name="tokenName"> The token name. </param> + /// <param name="type"> The token type. </param> + /// <param name="label"> The label associated with the token tag, or {@code null} if + /// the token tag is unlabeled. </param> + TokenTagToken(const std::string &tokenName, int type, const std::string &label); + + /// <summary> + /// Gets the token name. </summary> + /// <returns> The token name. </returns> + std::string getTokenName() const; + + /// <summary> + /// Gets the label associated with the rule tag. + /// </summary> + /// <returns> The name of the label associated with the rule tag, or + /// {@code null} if this is an unlabeled rule tag. </returns> + std::string getLabel() const; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// The implementation for <seealso cref="TokenTagToken"/> returns the token tag + /// formatted with {@code <} and {@code >} delimiters. + /// </summary> + virtual std::string getText() const override; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// The implementation for <seealso cref="TokenTagToken"/> returns a string of the form + /// {@code tokenName:type}. + /// </summary> + virtual std::string toString() const override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPath.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPath.cpp new file mode 100644 index 0000000..c039896 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPath.cpp @@ -0,0 +1,154 @@ +/* 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 "XPathLexer.h" +#include "XPathLexerErrorListener.h" +#include "XPathElement.h" +#include "XPathWildcardAnywhereElement.h" +#include "XPathWildcardElement.h" +#include "XPathTokenAnywhereElement.h" +#include "XPathTokenElement.h" +#include "XPathRuleAnywhereElement.h" +#include "XPathRuleElement.h" + +#include "XPath.h" + +using namespace antlr4; +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +const std::string XPath::WILDCARD = "*"; +const std::string XPath::NOT = "!"; + +XPath::XPath(Parser *parser, const std::string &path) { + _parser = parser; + _path = path; +} + +std::vector<std::unique_ptr<XPathElement>> XPath::split(const std::string &path) { + ANTLRInputStream in(path); + XPathLexer lexer(&in); + lexer.removeErrorListeners(); + XPathLexerErrorListener listener; + lexer.addErrorListener(&listener); + CommonTokenStream tokenStream(&lexer); + try { + tokenStream.fill(); + } catch (LexerNoViableAltException &) { + size_t pos = lexer.getCharPositionInLine(); + std::string msg = "Invalid tokens or characters at index " + std::to_string(pos) + " in path '" + path + "'"; + throw IllegalArgumentException(msg); + } + + std::vector<Token *> tokens = tokenStream.getTokens(); + std::vector<std::unique_ptr<XPathElement>> elements; + size_t n = tokens.size(); + size_t i = 0; + bool done = false; + while (!done && i < n) { + Token *el = tokens[i]; + Token *next = nullptr; + switch (el->getType()) { + case XPathLexer::ROOT: + case XPathLexer::ANYWHERE: { + bool anywhere = el->getType() == XPathLexer::ANYWHERE; + i++; + next = tokens[i]; + bool invert = next->getType() == XPathLexer::BANG; + if (invert) { + i++; + next = tokens[i]; + } + std::unique_ptr<XPathElement> pathElement = getXPathElement(next, anywhere); + pathElement->setInvert(invert); + elements.push_back(std::move(pathElement)); + i++; + break; + + } + case XPathLexer::TOKEN_REF: + case XPathLexer::RULE_REF: + case XPathLexer::WILDCARD: + elements.push_back(getXPathElement(el, false)); + i++; + break; + + case Token::EOF: + done = true; + break; + + default : + throw IllegalArgumentException("Unknown path element " + el->toString()); + } + } + + return elements; +} + +std::unique_ptr<XPathElement> XPath::getXPathElement(Token *wordToken, bool anywhere) { + if (wordToken->getType() == Token::EOF) { + throw IllegalArgumentException("Missing path element at end of path"); + } + + std::string word = wordToken->getText(); + size_t ttype = _parser->getTokenType(word); + ssize_t ruleIndex = _parser->getRuleIndex(word); + switch (wordToken->getType()) { + case XPathLexer::WILDCARD : + if (anywhere) + return std::unique_ptr<XPathWildcardAnywhereElement>(new XPathWildcardAnywhereElement()); + return std::unique_ptr<XPathWildcardElement>(new XPathWildcardElement()); + + case XPathLexer::TOKEN_REF: + case XPathLexer::STRING : + if (ttype == Token::INVALID_TYPE) { + throw IllegalArgumentException(word + " at index " + std::to_string(wordToken->getStartIndex()) + " isn't a valid token name"); + } + if (anywhere) + return std::unique_ptr<XPathTokenAnywhereElement>(new XPathTokenAnywhereElement(word, (int)ttype)); + return std::unique_ptr<XPathTokenElement>(new XPathTokenElement(word, (int)ttype)); + + default : + if (ruleIndex == -1) { + throw IllegalArgumentException(word + " at index " + std::to_string(wordToken->getStartIndex()) + " isn't a valid rule name"); + } + if (anywhere) + return std::unique_ptr<XPathRuleAnywhereElement>(new XPathRuleAnywhereElement(word, (int)ruleIndex)); + return std::unique_ptr<XPathRuleElement>(new XPathRuleElement(word, (int)ruleIndex)); + } +} + +static ParserRuleContext dummyRoot; + +std::vector<ParseTree *> XPath::findAll(ParseTree *tree, std::string const& xpath, Parser *parser) { + XPath p(parser, xpath); + return p.evaluate(tree); +} + +std::vector<ParseTree *> XPath::evaluate(ParseTree *t) { + dummyRoot.children = { t }; // don't set t's parent. + + std::vector<ParseTree *> work = { &dummyRoot }; + + size_t i = 0; + std::vector<std::unique_ptr<XPathElement>> elements = split(_path); + + while (i < elements.size()) { + std::vector<ParseTree *> next; + for (auto *node : work) { + if (!node->children.empty()) { + // only try to match next element if it has children + // e.g., //func/*/stat might have a token node for which + // we can't go looking for stat nodes. + auto matching = elements[i]->evaluate(node); + next.insert(next.end(), matching.begin(), matching.end()); + } + } + i++; + work = next; + } + + return work; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPath.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPath.h new file mode 100644 index 0000000..e38d482 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPath.h @@ -0,0 +1,86 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + /// Represent a subset of XPath XML path syntax for use in identifying nodes in + /// parse trees. + /// + /// <para> + /// Split path into words and separators {@code /} and {@code //} via ANTLR + /// itself then walk path elements from left to right. At each separator-word + /// pair, find set of nodes. Next stage uses those as work list.</para> + /// + /// <para> + /// The basic interface is + /// <seealso cref="XPath#findAll ParseTree.findAll"/>{@code (tree, pathString, parser)}. + /// But that is just shorthand for:</para> + /// + /// <pre> + /// <seealso cref="XPath"/> p = new <seealso cref="XPath#XPath XPath"/>(parser, pathString); + /// return p.<seealso cref="#evaluate evaluate"/>(tree); + /// </pre> + /// + /// <para> + /// See {@code org.antlr.v4.test.TestXPath} for descriptions. In short, this + /// allows operators:</para> + /// + /// <dl> + /// <dt>/</dt> <dd>root</dd> + /// <dt>//</dt> <dd>anywhere</dd> + /// <dt>!</dt> <dd>invert; this must appear directly after root or anywhere + /// operator</dd> + /// </dl> + /// + /// <para> + /// and path elements:</para> + /// + /// <dl> + /// <dt>ID</dt> <dd>token name</dd> + /// <dt>'string'</dt> <dd>any string literal token from the grammar</dd> + /// <dt>expr</dt> <dd>rule name</dd> + /// <dt>*</dt> <dd>wildcard matching any node</dd> + /// </dl> + /// + /// <para> + /// Whitespace is not allowed.</para> + + class ANTLR4CPP_PUBLIC XPath { + public: + static const std::string WILDCARD; // word not operator/separator + static const std::string NOT; // word for invert operator + + XPath(Parser *parser, const std::string &path); + virtual ~XPath() {} + + // TODO: check for invalid token/rule names, bad syntax + virtual std::vector<std::unique_ptr<XPathElement>> split(const std::string &path); + + static std::vector<ParseTree *> findAll(ParseTree *tree, std::string const& xpath, Parser *parser); + + /// Return a list of all nodes starting at {@code t} as root that satisfy the + /// path. The root {@code /} is relative to the node passed to + /// <seealso cref="#evaluate"/>. + virtual std::vector<ParseTree *> evaluate(ParseTree *t); + + protected: + std::string _path; + Parser *_parser; + + /// Convert word like {@code *} or {@code ID} or {@code expr} to a path + /// element. {@code anywhere} is {@code true} if {@code //} precedes the + /// word. + virtual std::unique_ptr<XPathElement> getXPathElement(Token *wordToken, bool anywhere); + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathElement.cpp new file mode 100644 index 0000000..64b122d --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathElement.cpp @@ -0,0 +1,31 @@ +/* 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 "XPathElement.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathElement::XPathElement(const std::string &nodeName) { + _nodeName = nodeName; +} + +XPathElement::~XPathElement() { +} + +std::vector<ParseTree *> XPathElement::evaluate(ParseTree * /*t*/) { + return {}; +} + +std::string XPathElement::toString() const { + std::string inv = _invert ? "!" : ""; + return antlrcpp::toString(*this) + "[" + inv + _nodeName + "]"; +} + +void XPathElement::setInvert(bool value) { + _invert = value; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathElement.h new file mode 100644 index 0000000..f339117 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathElement.h @@ -0,0 +1,40 @@ +/* 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 "antlr4-common.h" + +namespace antlr4 { +namespace tree { + class ParseTree; + +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathElement { + public: + /// Construct element like {@code /ID} or {@code ID} or {@code /*} etc... + /// op is null if just node + XPathElement(const std::string &nodeName); + XPathElement(XPathElement const&) = default; + virtual ~XPathElement(); + + XPathElement& operator=(XPathElement const&) = default; + + /// Given tree rooted at {@code t} return all nodes matched by this path + /// element. + virtual std::vector<ParseTree *> evaluate(ParseTree *t); + virtual std::string toString() const; + + void setInvert(bool value); + + protected: + std::string _nodeName; + bool _invert = false; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.cpp new file mode 100644 index 0000000..fb18788 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.cpp @@ -0,0 +1,173 @@ +#include "XPathLexer.h" + + +using namespace antlr4; + + +XPathLexer::XPathLexer(CharStream *input) : Lexer(input) { + _interpreter = new atn::LexerATNSimulator(this, _atn, _decisionToDFA, _sharedContextCache); +} + +XPathLexer::~XPathLexer() { + delete _interpreter; +} + +std::string XPathLexer::getGrammarFileName() const { + return "XPathLexer.g4"; +} + +const std::vector<std::string>& XPathLexer::getRuleNames() const { + return _ruleNames; +} + +const std::vector<std::string>& XPathLexer::getChannelNames() const { + return _channelNames; +} + +const std::vector<std::string>& XPathLexer::getModeNames() const { + return _modeNames; +} + +const std::vector<std::string>& XPathLexer::getTokenNames() const { + return _tokenNames; +} + +dfa::Vocabulary& XPathLexer::getVocabulary() const { + return _vocabulary; +} + +const std::vector<uint16_t> XPathLexer::getSerializedATN() const { + return _serializedATN; +} + +const atn::ATN& XPathLexer::getATN() const { + return _atn; +} + + +void XPathLexer::action(RuleContext *context, size_t ruleIndex, size_t actionIndex) { + switch (ruleIndex) { + case 4: IDAction(dynamic_cast<antlr4::RuleContext *>(context), actionIndex); break; + + default: + break; + } +} + +void XPathLexer::IDAction(antlr4::RuleContext * /*context*/, size_t actionIndex) { + switch (actionIndex) { + case 0: + if (isupper(getText()[0])) + setType(TOKEN_REF); + else + setType(RULE_REF); + break; + + default: + break; + } +} + + + +// Static vars and initialization. +std::vector<dfa::DFA> XPathLexer::_decisionToDFA; +atn::PredictionContextCache XPathLexer::_sharedContextCache; + +// We own the ATN which in turn owns the ATN states. +atn::ATN XPathLexer::_atn; +std::vector<uint16_t> XPathLexer::_serializedATN; + +std::vector<std::string> XPathLexer::_ruleNames = { + "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", "NameChar", "NameStartChar", + "STRING" +}; + +std::vector<std::string> XPathLexer::_channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +}; + +std::vector<std::string> XPathLexer::_modeNames = { + "DEFAULT_MODE" +}; + +std::vector<std::string> XPathLexer::_literalNames = { + "", "", "", "'//'", "'/'", "'*'", "'!'" +}; + +std::vector<std::string> XPathLexer::_symbolicNames = { + "", "TOKEN_REF", "RULE_REF", "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", + "STRING" +}; + +dfa::Vocabulary XPathLexer::_vocabulary(_literalNames, _symbolicNames); + +std::vector<std::string> XPathLexer::_tokenNames; + +XPathLexer::Initializer::Initializer() { + // This code could be in a static initializer lambda, but VS doesn't allow access to private class members from there. + for (size_t i = 0; i < _symbolicNames.size(); ++i) { + std::string name = _vocabulary.getLiteralName(i); + if (name.empty()) { + name = _vocabulary.getSymbolicName(i); + } + + if (name.empty()) { + _tokenNames.push_back("<INVALID>"); + } else { + _tokenNames.push_back(name); + } + } + + _serializedATN = { + 0x3, 0x430, 0xd6d1, 0x8206, 0xad2d, 0x4417, 0xaef1, 0x8d80, 0xaadd, + 0x2, 0xa, 0x34, 0x8, 0x1, 0x4, 0x2, 0x9, 0x2, 0x4, 0x3, 0x9, 0x3, 0x4, + 0x4, 0x9, 0x4, 0x4, 0x5, 0x9, 0x5, 0x4, 0x6, 0x9, 0x6, 0x4, 0x7, 0x9, + 0x7, 0x4, 0x8, 0x9, 0x8, 0x4, 0x9, 0x9, 0x9, 0x3, 0x2, 0x3, 0x2, 0x3, + 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x4, 0x3, 0x5, 0x3, 0x5, 0x3, + 0x6, 0x3, 0x6, 0x7, 0x6, 0x1f, 0xa, 0x6, 0xc, 0x6, 0xe, 0x6, 0x22, 0xb, + 0x6, 0x3, 0x6, 0x3, 0x6, 0x3, 0x7, 0x3, 0x7, 0x5, 0x7, 0x28, 0xa, 0x7, + 0x3, 0x8, 0x3, 0x8, 0x3, 0x9, 0x3, 0x9, 0x7, 0x9, 0x2e, 0xa, 0x9, 0xc, + 0x9, 0xe, 0x9, 0x31, 0xb, 0x9, 0x3, 0x9, 0x3, 0x9, 0x3, 0x2f, 0x2, 0xa, + 0x3, 0x5, 0x5, 0x6, 0x7, 0x7, 0x9, 0x8, 0xb, 0x9, 0xd, 0x2, 0xf, 0x2, + 0x11, 0xa, 0x3, 0x2, 0x4, 0x7, 0x2, 0x32, 0x3b, 0x61, 0x61, 0xb9, 0xb9, + 0x302, 0x371, 0x2041, 0x2042, 0xf, 0x2, 0x43, 0x5c, 0x63, 0x7c, 0xc2, + 0xd8, 0xda, 0xf8, 0xfa, 0x301, 0x372, 0x37f, 0x381, 0x2001, 0x200e, + 0x200f, 0x2072, 0x2191, 0x2c02, 0x2ff1, 0x3003, 0xd801, 0xf902, 0xfdd1, + 0xfdf2, 0x1, 0x34, 0x2, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x5, 0x3, 0x2, + 0x2, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x9, 0x3, 0x2, 0x2, 0x2, + 0x2, 0xb, 0x3, 0x2, 0x2, 0x2, 0x2, 0x11, 0x3, 0x2, 0x2, 0x2, 0x3, 0x13, + 0x3, 0x2, 0x2, 0x2, 0x5, 0x16, 0x3, 0x2, 0x2, 0x2, 0x7, 0x18, 0x3, 0x2, + 0x2, 0x2, 0x9, 0x1a, 0x3, 0x2, 0x2, 0x2, 0xb, 0x1c, 0x3, 0x2, 0x2, 0x2, + 0xd, 0x27, 0x3, 0x2, 0x2, 0x2, 0xf, 0x29, 0x3, 0x2, 0x2, 0x2, 0x11, + 0x2b, 0x3, 0x2, 0x2, 0x2, 0x13, 0x14, 0x7, 0x31, 0x2, 0x2, 0x14, 0x15, + 0x7, 0x31, 0x2, 0x2, 0x15, 0x4, 0x3, 0x2, 0x2, 0x2, 0x16, 0x17, 0x7, + 0x31, 0x2, 0x2, 0x17, 0x6, 0x3, 0x2, 0x2, 0x2, 0x18, 0x19, 0x7, 0x2c, + 0x2, 0x2, 0x19, 0x8, 0x3, 0x2, 0x2, 0x2, 0x1a, 0x1b, 0x7, 0x23, 0x2, + 0x2, 0x1b, 0xa, 0x3, 0x2, 0x2, 0x2, 0x1c, 0x20, 0x5, 0xf, 0x8, 0x2, + 0x1d, 0x1f, 0x5, 0xd, 0x7, 0x2, 0x1e, 0x1d, 0x3, 0x2, 0x2, 0x2, 0x1f, + 0x22, 0x3, 0x2, 0x2, 0x2, 0x20, 0x1e, 0x3, 0x2, 0x2, 0x2, 0x20, 0x21, + 0x3, 0x2, 0x2, 0x2, 0x21, 0x23, 0x3, 0x2, 0x2, 0x2, 0x22, 0x20, 0x3, + 0x2, 0x2, 0x2, 0x23, 0x24, 0x8, 0x6, 0x2, 0x2, 0x24, 0xc, 0x3, 0x2, + 0x2, 0x2, 0x25, 0x28, 0x5, 0xf, 0x8, 0x2, 0x26, 0x28, 0x9, 0x2, 0x2, + 0x2, 0x27, 0x25, 0x3, 0x2, 0x2, 0x2, 0x27, 0x26, 0x3, 0x2, 0x2, 0x2, + 0x28, 0xe, 0x3, 0x2, 0x2, 0x2, 0x29, 0x2a, 0x9, 0x3, 0x2, 0x2, 0x2a, + 0x10, 0x3, 0x2, 0x2, 0x2, 0x2b, 0x2f, 0x7, 0x29, 0x2, 0x2, 0x2c, 0x2e, + 0xb, 0x2, 0x2, 0x2, 0x2d, 0x2c, 0x3, 0x2, 0x2, 0x2, 0x2e, 0x31, 0x3, + 0x2, 0x2, 0x2, 0x2f, 0x30, 0x3, 0x2, 0x2, 0x2, 0x2f, 0x2d, 0x3, 0x2, + 0x2, 0x2, 0x30, 0x32, 0x3, 0x2, 0x2, 0x2, 0x31, 0x2f, 0x3, 0x2, 0x2, + 0x2, 0x32, 0x33, 0x7, 0x29, 0x2, 0x2, 0x33, 0x12, 0x3, 0x2, 0x2, 0x2, + 0x6, 0x2, 0x20, 0x27, 0x2f, 0x3, 0x3, 0x6, 0x2, + }; + + atn::ATNDeserializer deserializer; + _atn = deserializer.deserialize(_serializedATN); + + size_t count = _atn.getNumberOfDecisions(); + _decisionToDFA.reserve(count); + for (size_t i = 0; i < count; i++) { + _decisionToDFA.emplace_back(_atn.getDecisionState(i), i); + } +} + +XPathLexer::Initializer XPathLexer::_init; diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.g4 b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.g4 new file mode 100644 index 0000000..14bcf5a --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.g4 @@ -0,0 +1,64 @@ +lexer grammar XPathLexer; + +tokens { TOKEN_REF, RULE_REF } + +/* +path : separator? word (separator word)* EOF ; + +separator + : '/' '!' + | '//' '!' + | '/' + | '//' + ; + +word: TOKEN_REF + | RULE_REF + | STRING + | '*' + ; +*/ + +ANYWHERE : '//' ; +ROOT : '/' ; +WILDCARD : '*' ; +BANG : '!' ; + +ID : NameStartChar NameChar* + { + if (isupper(getText()[0])) + setType(TOKEN_REF); + else + setType(RULE_REF); + } + ; + +fragment +NameChar : NameStartChar + | '0'..'9' + | '_' + | '\u00B7' + | '\u0300'..'\u036F' + | '\u203F'..'\u2040' + ; + +fragment +NameStartChar + : 'A'..'Z' | 'a'..'z' + | '\u00C0'..'\u00D6' + | '\u00D8'..'\u00F6' + | '\u00F8'..'\u02FF' + | '\u0370'..'\u037D' + | '\u037F'..'\u1FFF' + | '\u200C'..'\u200D' + | '\u2070'..'\u218F' + | '\u2C00'..'\u2FEF' + | '\u3001'..'\uD7FF' + | '\uF900'..'\uFDCF' + | '\uFDF0'..'\uFFFF' // implicitly includes ['\u10000-'\uEFFFF] + ; + +STRING : '\'' .*? '\''; + +//WS : [ \t\r\n]+ -> skip ; + diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.h new file mode 100644 index 0000000..ca471c9 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.h @@ -0,0 +1,56 @@ +#pragma once + + +#include "antlr4-runtime.h" + + + + +class XPathLexer : public antlr4::Lexer { +public: + enum { + TOKEN_REF = 1, RULE_REF = 2, ANYWHERE = 3, ROOT = 4, WILDCARD = 5, BANG = 6, + ID = 7, STRING = 8 + }; + + XPathLexer(antlr4::CharStream *input); + ~XPathLexer(); + + virtual std::string getGrammarFileName() const override; + virtual const std::vector<std::string>& getRuleNames() const override; + + virtual const std::vector<std::string>& getChannelNames() const override; + virtual const std::vector<std::string>& getModeNames() const override; + virtual const std::vector<std::string>& getTokenNames() const override; // deprecated, use vocabulary instead + virtual antlr4::dfa::Vocabulary& getVocabulary() const override; + + virtual const std::vector<uint16_t> getSerializedATN() const override; + virtual const antlr4::atn::ATN& getATN() const override; + + virtual void action(antlr4::RuleContext *context, size_t ruleIndex, size_t actionIndex) override; +private: + static std::vector<antlr4::dfa::DFA> _decisionToDFA; + static antlr4::atn::PredictionContextCache _sharedContextCache; + static std::vector<std::string> _ruleNames; + static std::vector<std::string> _tokenNames; + static std::vector<std::string> _channelNames; + static std::vector<std::string> _modeNames; + + static std::vector<std::string> _literalNames; + static std::vector<std::string> _symbolicNames; + static antlr4::dfa::Vocabulary _vocabulary; + static antlr4::atn::ATN _atn; + static std::vector<uint16_t> _serializedATN; + + + // Individual action functions triggered by action() above. + void IDAction(antlr4::RuleContext *context, size_t actionIndex); + + // Individual semantic predicate functions triggered by sempred() above. + + struct Initializer { + Initializer(); + }; + static Initializer _init; +}; + diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.tokens b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.tokens new file mode 100644 index 0000000..5bf699e --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexer.tokens @@ -0,0 +1,12 @@ +TOKEN_REF=1 +RULE_REF=2 +ANYWHERE=3 +ROOT=4 +WILDCARD=5 +BANG=6 +ID=7 +STRING=8 +'//'=3 +'/'=4 +'*'=5 +'!'=6 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexerErrorListener.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexerErrorListener.cpp new file mode 100644 index 0000000..2804c8e --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexerErrorListener.cpp @@ -0,0 +1,13 @@ +/* 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 "XPathLexerErrorListener.h" + +using namespace antlr4; +using namespace antlr4::tree::xpath; + +void XPathLexerErrorListener::syntaxError(Recognizer * /*recognizer*/, Token * /*offendingSymbol*/, + size_t /*line*/, size_t /*charPositionInLine*/, const std::string &/*msg*/, std::exception_ptr /*e*/) { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexerErrorListener.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexerErrorListener.h new file mode 100644 index 0000000..c0c3eaa --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathLexerErrorListener.h @@ -0,0 +1,22 @@ +/* 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 "BaseErrorListener.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathLexerErrorListener : public BaseErrorListener { + public: + virtual void syntaxError(Recognizer *recognizer, Token *offendingSymbol, size_t line, + size_t charPositionInLine, const std::string &msg, std::exception_ptr e) override; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleAnywhereElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleAnywhereElement.cpp new file mode 100644 index 0000000..9ca910d --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleAnywhereElement.cpp @@ -0,0 +1,20 @@ +/* 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 "tree/ParseTree.h" +#include "tree/Trees.h" + +#include "tree/xpath/XPathRuleAnywhereElement.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathRuleAnywhereElement::XPathRuleAnywhereElement(const std::string &ruleName, int ruleIndex) : XPathElement(ruleName) { + _ruleIndex = ruleIndex; +} + +std::vector<ParseTree *> XPathRuleAnywhereElement::evaluate(ParseTree *t) { + return Trees::findAllRuleNodes(t, _ruleIndex); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleAnywhereElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleAnywhereElement.h new file mode 100644 index 0000000..2ceb75c --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleAnywhereElement.h @@ -0,0 +1,27 @@ +/* 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 "XPathElement.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + /// Either {@code ID} at start of path or {@code ...//ID} in middle of path. + class ANTLR4CPP_PUBLIC XPathRuleAnywhereElement : public XPathElement { + public: + XPathRuleAnywhereElement(const std::string &ruleName, int ruleIndex); + + virtual std::vector<ParseTree *> evaluate(ParseTree *t) override; + + protected: + int _ruleIndex = 0; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleElement.cpp new file mode 100644 index 0000000..1d145fb --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleElement.cpp @@ -0,0 +1,30 @@ +/* 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 "tree/ParseTree.h" +#include "tree/Trees.h" + +#include "XPathRuleElement.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathRuleElement::XPathRuleElement(const std::string &ruleName, size_t ruleIndex) : XPathElement(ruleName) { + _ruleIndex = ruleIndex; +} + +std::vector<ParseTree *> XPathRuleElement::evaluate(ParseTree *t) { + // return all children of t that match nodeName + std::vector<ParseTree *> nodes; + for (auto *c : t->children) { + if (antlrcpp::is<ParserRuleContext *>(c)) { + ParserRuleContext *ctx = dynamic_cast<ParserRuleContext *>(c); + if ((ctx->getRuleIndex() == _ruleIndex && !_invert) || (ctx->getRuleIndex() != _ruleIndex && _invert)) { + nodes.push_back(ctx); + } + } + } + return nodes; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleElement.h new file mode 100644 index 0000000..b57276f --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathRuleElement.h @@ -0,0 +1,26 @@ +/* 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 "XPathElement.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathRuleElement : public XPathElement { + public: + XPathRuleElement(const std::string &ruleName, size_t ruleIndex); + + virtual std::vector<ParseTree *> evaluate(ParseTree *t) override; + + protected: + size_t _ruleIndex = 0; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenAnywhereElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenAnywhereElement.cpp new file mode 100644 index 0000000..c557c9d --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenAnywhereElement.cpp @@ -0,0 +1,20 @@ +/* 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 "tree/ParseTree.h" +#include "tree/Trees.h" + +#include "XPathTokenAnywhereElement.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathTokenAnywhereElement::XPathTokenAnywhereElement(const std::string &tokenName, int tokenType) : XPathElement(tokenName) { + this->tokenType = tokenType; +} + +std::vector<ParseTree *> XPathTokenAnywhereElement::evaluate(ParseTree *t) { + return Trees::findAllTokenNodes(t, tokenType); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenAnywhereElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenAnywhereElement.h new file mode 100644 index 0000000..2045d91 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenAnywhereElement.h @@ -0,0 +1,25 @@ +/* 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 "XPathElement.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathTokenAnywhereElement : public XPathElement { + protected: + int tokenType = 0; + public: + XPathTokenAnywhereElement(const std::string &tokenName, int tokenType); + + virtual std::vector<ParseTree *> evaluate(ParseTree *t) override; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenElement.cpp new file mode 100644 index 0000000..d52fc26 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenElement.cpp @@ -0,0 +1,33 @@ +/* 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 "tree/ParseTree.h" +#include "tree/Trees.h" +#include "support/CPPUtils.h" +#include "Token.h" + +#include "XPathTokenElement.h" + +using namespace antlr4; +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathTokenElement::XPathTokenElement(const std::string &tokenName, size_t tokenType) : XPathElement(tokenName) { + _tokenType = tokenType; +} + +std::vector<ParseTree *> XPathTokenElement::evaluate(ParseTree *t) { + // return all children of t that match nodeName + std::vector<ParseTree *> nodes; + for (auto *c : t->children) { + if (antlrcpp::is<TerminalNode *>(c)) { + TerminalNode *tnode = dynamic_cast<TerminalNode *>(c); + if ((tnode->getSymbol()->getType() == _tokenType && !_invert) || (tnode->getSymbol()->getType() != _tokenType && _invert)) { + nodes.push_back(tnode); + } + } + } + return nodes; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenElement.h new file mode 100644 index 0000000..7221530 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathTokenElement.h @@ -0,0 +1,26 @@ +/* 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 "XPathElement.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathTokenElement : public XPathElement { + public: + XPathTokenElement(const std::string &tokenName, size_t tokenType); + + virtual std::vector<ParseTree *> evaluate(ParseTree *t) override; + + protected: + size_t _tokenType = 0; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardAnywhereElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardAnywhereElement.cpp new file mode 100644 index 0000000..4ff424f --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardAnywhereElement.cpp @@ -0,0 +1,23 @@ +/* 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 "XPath.h" +#include "tree/ParseTree.h" +#include "tree/Trees.h" + +#include "XPathWildcardAnywhereElement.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathWildcardAnywhereElement::XPathWildcardAnywhereElement() : XPathElement(XPath::WILDCARD) { +} + +std::vector<ParseTree *> XPathWildcardAnywhereElement::evaluate(ParseTree *t) { + if (_invert) { + return {}; // !* is weird but valid (empty) + } + return Trees::getDescendants(t); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardAnywhereElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardAnywhereElement.h new file mode 100644 index 0000000..dc5d1e5 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardAnywhereElement.h @@ -0,0 +1,23 @@ +/* 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 "XPathElement.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathWildcardAnywhereElement : public XPathElement { + public: + XPathWildcardAnywhereElement(); + + virtual std::vector<ParseTree *> evaluate(ParseTree *t) override; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardElement.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardElement.cpp new file mode 100644 index 0000000..aabda5a --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardElement.cpp @@ -0,0 +1,24 @@ +/* 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 "XPath.h" +#include "tree/ParseTree.h" +#include "tree/Trees.h" + +#include "XPathWildcardElement.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::xpath; + +XPathWildcardElement::XPathWildcardElement() : XPathElement(XPath::WILDCARD) { +} + +std::vector<ParseTree *> XPathWildcardElement::evaluate(ParseTree *t) { + if (_invert) { + return {}; // !* is weird but valid (empty) + } + + return t->children; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardElement.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardElement.h new file mode 100644 index 0000000..accb461 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/xpath/XPathWildcardElement.h @@ -0,0 +1,23 @@ +/* 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 "XPathElement.h" + +namespace antlr4 { +namespace tree { +namespace xpath { + + class ANTLR4CPP_PUBLIC XPathWildcardElement : public XPathElement { + public: + XPathWildcardElement(); + + virtual std::vector<ParseTree *> evaluate(ParseTree *t) override; + }; + +} // namespace xpath +} // namespace tree +} // namespace antlr4 |
