Initial commit from sysy-main
This commit is contained in:
129
antlr/antlr4-runtime-4.12.0/runtime/src/tree/AbstractParseTreeVisitor.h
Executable file
129
antlr/antlr4-runtime-4.12.0/runtime/src/tree/AbstractParseTreeVisitor.h
Executable file
@@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
||||
* Use of this file is governed by the BSD 3-clause license that
|
||||
* can be found in the LICENSE.txt file in the project root.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tree/ParseTree.h"
|
||||
#include "tree/ParseTreeVisitor.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
class ANTLR4CPP_PUBLIC AbstractParseTreeVisitor : public ParseTreeVisitor {
|
||||
public:
|
||||
/// The default implementation calls <seealso cref="ParseTree#accept"/> on the
|
||||
/// specified tree.
|
||||
virtual std::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 std::any visitChildren(ParseTree *node) override {
|
||||
std::any result = defaultResult();
|
||||
size_t n = node->children.size();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (!shouldVisitNextChild(node, result)) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::any childResult = node->children[i]->accept(this);
|
||||
result = aggregateResult(std::move(result), std::move(childResult));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// The default implementation returns the result of
|
||||
/// <seealso cref="#defaultResult defaultResult"/>.
|
||||
virtual std::any visitTerminal(TerminalNode * /*node*/) override {
|
||||
return defaultResult();
|
||||
}
|
||||
|
||||
/// The default implementation returns the result of
|
||||
/// <seealso cref="#defaultResult defaultResult"/>.
|
||||
virtual std::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 std::any()}.
|
||||
/// </summary>
|
||||
/// <returns> The default value returned by visitor methods. </returns>
|
||||
virtual std::any defaultResult() {
|
||||
return std::any();
|
||||
}
|
||||
|
||||
/// <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 std::any aggregateResult(std::any /*aggregate*/, std::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 std::any &/*currentResult*/) {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace tree
|
||||
} // namespace antlr4
|
||||
24
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ErrorNode.h
Executable file
24
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ErrorNode.h
Executable file
@@ -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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tree/TerminalNode.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
class ANTLR4CPP_PUBLIC ErrorNode : public TerminalNode {
|
||||
public:
|
||||
static bool is(const tree::ParseTree &parseTree) { return parseTree.getTreeType() == tree::ParseTreeType::ERROR; }
|
||||
|
||||
static bool is(const tree::ParseTree *parseTree) { return parseTree != nullptr && is(*parseTree); }
|
||||
|
||||
protected:
|
||||
using TerminalNode::TerminalNode;
|
||||
};
|
||||
|
||||
} // namespace tree
|
||||
} // namespace antlr4
|
||||
54
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ErrorNodeImpl.cpp
Executable file
54
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ErrorNodeImpl.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
/* 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/ErrorNodeImpl.h"
|
||||
|
||||
using namespace antlr4;
|
||||
using namespace antlr4::tree;
|
||||
|
||||
Token* ErrorNodeImpl::getSymbol() const {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
void ErrorNodeImpl::setParent(RuleContext *parent_) {
|
||||
this->parent = parent_;
|
||||
}
|
||||
|
||||
misc::Interval ErrorNodeImpl::getSourceInterval() {
|
||||
if (symbol == nullptr) {
|
||||
return misc::Interval::INVALID;
|
||||
}
|
||||
|
||||
size_t tokenIndex = symbol->getTokenIndex();
|
||||
return misc::Interval(tokenIndex, tokenIndex);
|
||||
}
|
||||
|
||||
std::any ErrorNodeImpl::accept(ParseTreeVisitor *visitor) {
|
||||
return visitor->visitErrorNode(this);
|
||||
}
|
||||
|
||||
std::string ErrorNodeImpl::getText() {
|
||||
return symbol->getText();
|
||||
}
|
||||
|
||||
std::string ErrorNodeImpl::toStringTree(Parser * /*parser*/, bool /*pretty*/) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
std::string ErrorNodeImpl::toString() {
|
||||
if (symbol->getType() == Token::EOF) {
|
||||
return "<EOF>";
|
||||
}
|
||||
return symbol->getText();
|
||||
}
|
||||
|
||||
std::string ErrorNodeImpl::toStringTree(bool /*pretty*/) {
|
||||
return toString();
|
||||
}
|
||||
43
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ErrorNodeImpl.h
Executable file
43
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ErrorNodeImpl.h
Executable file
@@ -0,0 +1,43 @@
|
||||
/* 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 ErrorNode {
|
||||
public:
|
||||
Token *symbol;
|
||||
|
||||
explicit ErrorNodeImpl(Token *symbol) : ErrorNode(ParseTreeType::ERROR), symbol(symbol) {}
|
||||
|
||||
virtual Token* getSymbol() const override;
|
||||
virtual void setParent(RuleContext *parent) override;
|
||||
virtual misc::Interval getSourceInterval() override;
|
||||
|
||||
virtual std::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
|
||||
@@ -0,0 +1,66 @@
|
||||
/* 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 "support/Casts.h"
|
||||
|
||||
#include "tree/ParseTreeListener.h"
|
||||
#include "tree/ParseTree.h"
|
||||
#include "tree/ErrorNode.h"
|
||||
|
||||
#include "IterativeParseTreeWalker.h"
|
||||
|
||||
using namespace antlr4::tree;
|
||||
using namespace antlrcpp;
|
||||
|
||||
void IterativeParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const {
|
||||
std::vector<std::pair<ParseTree*, size_t>> stack;
|
||||
ParseTree *currentNode = t;
|
||||
size_t currentIndex = 0;
|
||||
|
||||
while (currentNode != nullptr) {
|
||||
// pre-order visit
|
||||
if (ErrorNode::is(*currentNode)) {
|
||||
listener->visitErrorNode(downCast<ErrorNode*>(currentNode));
|
||||
} else if (TerminalNode::is(*currentNode)) {
|
||||
listener->visitTerminal(downCast<TerminalNode*>(currentNode));
|
||||
} else {
|
||||
enterRule(listener, currentNode);
|
||||
}
|
||||
|
||||
// Move down to first child, if it exists.
|
||||
if (!currentNode->children.empty()) {
|
||||
stack.push_back(std::make_pair(currentNode, currentIndex));
|
||||
currentIndex = 0;
|
||||
currentNode = currentNode->children[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
// No child nodes, so walk tree.
|
||||
do {
|
||||
// post-order visit
|
||||
if (!TerminalNode::is(*currentNode)) {
|
||||
exitRule(listener, currentNode);
|
||||
}
|
||||
|
||||
// No parent, so no siblings.
|
||||
if (stack.empty()) {
|
||||
currentNode = nullptr;
|
||||
currentIndex = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Move to next sibling if possible.
|
||||
if (stack.back().first->children.size() > ++currentIndex) {
|
||||
currentNode = stack.back().first->children[currentIndex];
|
||||
break;
|
||||
}
|
||||
|
||||
// No next sibling, so move up.
|
||||
std::tie(currentNode, currentIndex) = stack.back();
|
||||
stack.pop_back();
|
||||
} while (currentNode != nullptr);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
12
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTree.cpp
Executable file
12
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTree.cpp
Executable file
@@ -0,0 +1,12 @@
|
||||
/* 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;
|
||||
|
||||
bool ParseTree::operator == (const ParseTree &other) const {
|
||||
return &other == this;
|
||||
}
|
||||
111
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTree.h
Executable file
111
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTree.h
Executable file
@@ -0,0 +1,111 @@
|
||||
/* 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"
|
||||
#include "tree/ParseTreeType.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 const&) = delete;
|
||||
|
||||
virtual ~ParseTree() = default;
|
||||
|
||||
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 = nullptr;
|
||||
|
||||
/// 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 std::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;
|
||||
|
||||
ParseTreeType getTreeType() const { return _treeType; }
|
||||
|
||||
protected:
|
||||
explicit ParseTree(ParseTreeType treeType) : _treeType(treeType) {}
|
||||
|
||||
private:
|
||||
const ParseTreeType _treeType;
|
||||
};
|
||||
|
||||
// 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
|
||||
@@ -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() {
|
||||
}
|
||||
39
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeListener.h
Executable file
39
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeListener.h
Executable file
@@ -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
|
||||
50
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeProperty.h
Executable file
50
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeProperty.h
Executable file
@@ -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
|
||||
22
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeType.h
Normal file
22
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeType.h
Normal file
@@ -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 <cstddef>
|
||||
|
||||
#include "antlr4-common.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
enum class ParseTreeType : size_t {
|
||||
TERMINAL = 1,
|
||||
ERROR = 2,
|
||||
RULE = 3,
|
||||
};
|
||||
|
||||
} // namespace tree
|
||||
} // namespace antlr4
|
||||
@@ -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() {
|
||||
}
|
||||
57
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeVisitor.h
Executable file
57
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeVisitor.h
Executable file
@@ -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 std::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 std::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 std::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 std::any visitErrorNode(ErrorNode *node) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace tree
|
||||
} // namespace antlr4
|
||||
48
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeWalker.cpp
Executable file
48
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeWalker.cpp
Executable file
@@ -0,0 +1,48 @@
|
||||
/* 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 "support/Casts.h"
|
||||
|
||||
#include "tree/IterativeParseTreeWalker.h"
|
||||
#include "tree/ParseTreeWalker.h"
|
||||
|
||||
using namespace antlr4::tree;
|
||||
using namespace antlrcpp;
|
||||
|
||||
static IterativeParseTreeWalker defaultWalker;
|
||||
ParseTreeWalker &ParseTreeWalker::DEFAULT = defaultWalker;
|
||||
|
||||
void ParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const {
|
||||
if (ErrorNode::is(*t)) {
|
||||
listener->visitErrorNode(downCast<ErrorNode*>(t));
|
||||
return;
|
||||
}
|
||||
if (TerminalNode::is(*t)) {
|
||||
listener->visitTerminal(downCast<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 {
|
||||
auto *ctx = downCast<ParserRuleContext*>(r);
|
||||
listener->enterEveryRule(ctx);
|
||||
ctx->enterRule(listener);
|
||||
}
|
||||
|
||||
void ParseTreeWalker::exitRule(ParseTreeListener *listener, ParseTree *r) const {
|
||||
auto *ctx = downCast<ParserRuleContext*>(r);
|
||||
ctx->exitRule(listener);
|
||||
listener->exitEveryRule(ctx);
|
||||
}
|
||||
55
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeWalker.h
Executable file
55
antlr/antlr4-runtime-4.12.0/runtime/src/tree/ParseTreeWalker.h
Executable file
@@ -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() = default;
|
||||
|
||||
/**
|
||||
* <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
|
||||
40
antlr/antlr4-runtime-4.12.0/runtime/src/tree/TerminalNode.h
Executable file
40
antlr/antlr4-runtime-4.12.0/runtime/src/tree/TerminalNode.h
Executable file
@@ -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 "tree/ParseTree.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
class ANTLR4CPP_PUBLIC TerminalNode : public ParseTree {
|
||||
public:
|
||||
static bool is(const tree::ParseTree &parseTree) {
|
||||
const auto treeType = parseTree.getTreeType();
|
||||
return treeType == ParseTreeType::TERMINAL || treeType == ParseTreeType::ERROR;
|
||||
}
|
||||
|
||||
static bool is(const tree::ParseTree *parseTree) { return parseTree != nullptr && is(*parseTree); }
|
||||
|
||||
virtual Token* getSymbol() const = 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;
|
||||
|
||||
protected:
|
||||
using ParseTree::ParseTree;
|
||||
};
|
||||
|
||||
} // namespace tree
|
||||
} // namespace antlr4
|
||||
54
antlr/antlr4-runtime-4.12.0/runtime/src/tree/TerminalNodeImpl.cpp
Executable file
54
antlr/antlr4-runtime-4.12.0/runtime/src/tree/TerminalNodeImpl.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
/* 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;
|
||||
|
||||
Token* TerminalNodeImpl::getSymbol() const {
|
||||
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);
|
||||
}
|
||||
|
||||
std::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();
|
||||
}
|
||||
32
antlr/antlr4-runtime-4.12.0/runtime/src/tree/TerminalNodeImpl.h
Executable file
32
antlr/antlr4-runtime-4.12.0/runtime/src/tree/TerminalNodeImpl.h
Executable file
@@ -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/TerminalNode.h"
|
||||
|
||||
namespace antlr4 {
|
||||
namespace tree {
|
||||
|
||||
class ANTLR4CPP_PUBLIC TerminalNodeImpl : public TerminalNode {
|
||||
public:
|
||||
Token *symbol;
|
||||
|
||||
explicit TerminalNodeImpl(Token *symbol) : TerminalNode(ParseTreeType::TERMINAL), symbol(symbol) {}
|
||||
|
||||
virtual Token* getSymbol() const override;
|
||||
virtual void setParent(RuleContext *parent) override;
|
||||
virtual misc::Interval getSourceInterval() override;
|
||||
|
||||
virtual std::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
|
||||
241
antlr/antlr4-runtime-4.12.0/runtime/src/tree/Trees.cpp
Executable file
241
antlr/antlr4-runtime-4.12.0/runtime/src/tree/Trees.cpp
Executable file
@@ -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;
|
||||
}
|
||||
|
||||
78
antlr/antlr4-runtime-4.12.0/runtime/src/tree/Trees.h
Executable file
78
antlr/antlr4-runtime-4.12.0/runtime/src/tree/Trees.h
Executable file
@@ -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
|
||||
@@ -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() {
|
||||
}
|
||||
44
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/Chunk.h
Executable file
44
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/Chunk.h
Executable file
@@ -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
|
||||
69
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreeMatch.cpp
Executable file
69
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreeMatch.cpp
Executable file
@@ -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";
|
||||
}
|
||||
}
|
||||
132
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreeMatch.h
Executable file
132
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreeMatch.h
Executable file
@@ -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
|
||||
64
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePattern.cpp
Executable file
64
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePattern.cpp
Executable file
@@ -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;
|
||||
}
|
||||
105
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePattern.h
Executable file
105
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePattern.h
Executable file
@@ -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
|
||||
370
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp
Executable file
370
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp
Executable file
@@ -0,0 +1,370 @@
|
||||
/* 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/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(RuntimeException("Cannot invoke start rule")); // Wrap any other exception.
|
||||
#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 = "\\";
|
||||
}
|
||||
185
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePatternMatcher.h
Executable file
185
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/ParseTreePatternMatcher.h
Executable file
@@ -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
|
||||
77
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/RuleTagToken.cpp
Executable file
77
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/RuleTagToken.cpp
Executable file
@@ -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);
|
||||
}
|
||||
117
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/RuleTagToken.h
Executable file
117
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/RuleTagToken.h
Executable file
@@ -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
|
||||
39
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TagChunk.cpp
Executable file
39
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TagChunk.cpp
Executable file
@@ -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;
|
||||
}
|
||||
86
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TagChunk.h
Executable file
86
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TagChunk.h
Executable file
@@ -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
|
||||
28
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TextChunk.cpp
Executable file
28
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TextChunk.cpp
Executable file
@@ -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("'");
|
||||
}
|
||||
51
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TextChunk.h
Executable file
51
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TextChunk.h
Executable file
@@ -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
|
||||
36
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TokenTagToken.cpp
Executable file
36
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TokenTagToken.cpp
Executable file
@@ -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);
|
||||
}
|
||||
80
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TokenTagToken.h
Executable file
80
antlr/antlr4-runtime-4.12.0/runtime/src/tree/pattern/TokenTagToken.h
Executable file
@@ -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
|
||||
154
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPath.cpp
Executable file
154
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPath.cpp
Executable file
@@ -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;
|
||||
}
|
||||
86
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPath.h
Executable file
86
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPath.h
Executable file
@@ -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
|
||||
31
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathElement.cpp
Executable file
31
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathElement.cpp
Executable file
@@ -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;
|
||||
}
|
||||
40
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathElement.h
Executable file
40
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathElement.h
Executable file
@@ -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
|
||||
@@ -0,0 +1,182 @@
|
||||
|
||||
// Generated from XPathLexer.g4 by ANTLR 4.9.3
|
||||
|
||||
|
||||
#include "XPathLexer.h"
|
||||
|
||||
|
||||
using namespace antlr4;
|
||||
|
||||
namespace {
|
||||
|
||||
struct XPathLexerStaticData final {
|
||||
XPathLexerStaticData(std::vector<std::string> ruleNames,
|
||||
std::vector<std::string> channelNames,
|
||||
std::vector<std::string> modeNames,
|
||||
std::vector<std::string> literalNames,
|
||||
std::vector<std::string> symbolicNames)
|
||||
: ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)),
|
||||
modeNames(std::move(modeNames)), literalNames(std::move(literalNames)),
|
||||
symbolicNames(std::move(symbolicNames)),
|
||||
vocabulary(this->literalNames, this->symbolicNames) {}
|
||||
|
||||
XPathLexerStaticData(const XPathLexerStaticData&) = delete;
|
||||
XPathLexerStaticData(XPathLexerStaticData&&) = delete;
|
||||
XPathLexerStaticData& operator=(const XPathLexerStaticData&) = delete;
|
||||
XPathLexerStaticData& operator=(XPathLexerStaticData&&) = delete;
|
||||
|
||||
std::vector<antlr4::dfa::DFA> decisionToDFA;
|
||||
antlr4::atn::PredictionContextCache sharedContextCache;
|
||||
const std::vector<std::string> ruleNames;
|
||||
const std::vector<std::string> channelNames;
|
||||
const std::vector<std::string> modeNames;
|
||||
const std::vector<std::string> literalNames;
|
||||
const std::vector<std::string> symbolicNames;
|
||||
const antlr4::dfa::Vocabulary vocabulary;
|
||||
antlr4::atn::SerializedATNView serializedATN;
|
||||
std::unique_ptr<antlr4::atn::ATN> atn;
|
||||
};
|
||||
|
||||
::antlr4::internal::OnceFlag xpathLexerOnceFlag;
|
||||
XPathLexerStaticData *xpathLexerStaticData = nullptr;
|
||||
|
||||
void xpathLexerInitialize() {
|
||||
assert(xpathLexerStaticData == nullptr);
|
||||
auto staticData = std::make_unique<XPathLexerStaticData>(
|
||||
std::vector<std::string>{
|
||||
"ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", "NameChar", "NameStartChar",
|
||||
"STRING"
|
||||
},
|
||||
std::vector<std::string>{
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
},
|
||||
std::vector<std::string>{
|
||||
"DEFAULT_MODE"
|
||||
},
|
||||
std::vector<std::string>{
|
||||
"", "", "", "'//'", "'/'", "'*'", "'!'"
|
||||
},
|
||||
std::vector<std::string>{
|
||||
"", "TOKEN_REF", "RULE_REF", "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID",
|
||||
"STRING"
|
||||
}
|
||||
);
|
||||
static const int32_t serializedATNSegment[] = {
|
||||
0x4, 0x0, 0x8, 0x32, 0x6, -1, 0x2, 0x0, 0x7, 0x0, 0x2, 0x1, 0x7,
|
||||
0x1, 0x2, 0x2, 0x7, 0x2, 0x2, 0x3, 0x7, 0x3, 0x2, 0x4, 0x7, 0x4,
|
||||
0x2, 0x5, 0x7, 0x5, 0x2, 0x6, 0x7, 0x6, 0x2, 0x7, 0x7, 0x7, 0x1,
|
||||
0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2,
|
||||
0x1, 0x3, 0x1, 0x3, 0x1, 0x4, 0x1, 0x4, 0x5, 0x4, 0x1d, 0x8, 0x4,
|
||||
0xa, 0x4, 0xc, 0x4, 0x20, 0x9, 0x4, 0x1, 0x4, 0x1, 0x4, 0x1, 0x5,
|
||||
0x1, 0x5, 0x3, 0x5, 0x26, 0x8, 0x5, 0x1, 0x6, 0x1, 0x6, 0x1, 0x7,
|
||||
0x1, 0x7, 0x5, 0x7, 0x2c, 0x8, 0x7, 0xa, 0x7, 0xc, 0x7, 0x2f, 0x9,
|
||||
0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x2d, 0x0, 0x8, 0x1, 0x3, 0x3, 0x4,
|
||||
0x5, 0x5, 0x7, 0x6, 0x9, 0x7, 0xb, 0x0, 0xd, 0x0, 0xf, 0x8, 0x1,
|
||||
0x0, 0x2, 0x5, 0x0, 0x30, 0x39, 0x5f, 0x5f, 0xb7, 0xb7, 0x300, 0x36f,
|
||||
0x203f, 0x2040, 0xd, 0x0, 0x41, 0x5a, 0x61, 0x7a, 0xc0, 0xd6, 0xd8,
|
||||
0xf6, 0xf8, 0x2ff, 0x370, 0x37d, 0x37f, 0x1fff, 0x200c, 0x200d, 0x2070,
|
||||
0x218f, 0x2c00, 0x2fef, 0x3001, 0xd7ff, 0xf900, 0xfdcf, 0xfdf0, -1,
|
||||
0x0, 0x32, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1, 0x0, 0x0,
|
||||
0x0, 0x0, 0x5, 0x1, 0x0, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0,
|
||||
0x0, 0x9, 0x1, 0x0, 0x0, 0x0, 0x0, 0xf, 0x1, 0x0, 0x0, 0x0, 0x1,
|
||||
0x11, 0x1, 0x0, 0x0, 0x0, 0x3, 0x14, 0x1, 0x0, 0x0, 0x0, 0x5, 0x16,
|
||||
0x1, 0x0, 0x0, 0x0, 0x7, 0x18, 0x1, 0x0, 0x0, 0x0, 0x9, 0x1a, 0x1,
|
||||
0x0, 0x0, 0x0, 0xb, 0x25, 0x1, 0x0, 0x0, 0x0, 0xd, 0x27, 0x1, 0x0,
|
||||
0x0, 0x0, 0xf, 0x29, 0x1, 0x0, 0x0, 0x0, 0x11, 0x12, 0x5, 0x2f, 0x0,
|
||||
0x0, 0x12, 0x13, 0x5, 0x2f, 0x0, 0x0, 0x13, 0x2, 0x1, 0x0, 0x0, 0x0,
|
||||
0x14, 0x15, 0x5, 0x2f, 0x0, 0x0, 0x15, 0x4, 0x1, 0x0, 0x0, 0x0, 0x16,
|
||||
0x17, 0x5, 0x2a, 0x0, 0x0, 0x17, 0x6, 0x1, 0x0, 0x0, 0x0, 0x18, 0x19,
|
||||
0x5, 0x21, 0x0, 0x0, 0x19, 0x8, 0x1, 0x0, 0x0, 0x0, 0x1a, 0x1e, 0x3,
|
||||
0xd, 0x6, 0x0, 0x1b, 0x1d, 0x3, 0xb, 0x5, 0x0, 0x1c, 0x1b, 0x1, 0x0,
|
||||
0x0, 0x0, 0x1d, 0x20, 0x1, 0x0, 0x0, 0x0, 0x1e, 0x1c, 0x1, 0x0, 0x0,
|
||||
0x0, 0x1e, 0x1f, 0x1, 0x0, 0x0, 0x0, 0x1f, 0x21, 0x1, 0x0, 0x0, 0x0,
|
||||
0x20, 0x1e, 0x1, 0x0, 0x0, 0x0, 0x21, 0x22, 0x6, 0x4, 0x0, 0x0, 0x22,
|
||||
0xa, 0x1, 0x0, 0x0, 0x0, 0x23, 0x26, 0x3, 0xd, 0x6, 0x0, 0x24, 0x26,
|
||||
0x7, 0x0, 0x0, 0x0, 0x25, 0x23, 0x1, 0x0, 0x0, 0x0, 0x25, 0x24, 0x1,
|
||||
0x0, 0x0, 0x0, 0x26, 0xc, 0x1, 0x0, 0x0, 0x0, 0x27, 0x28, 0x7, 0x1,
|
||||
0x0, 0x0, 0x28, 0xe, 0x1, 0x0, 0x0, 0x0, 0x29, 0x2d, 0x5, 0x27, 0x0,
|
||||
0x0, 0x2a, 0x2c, 0x9, 0x0, 0x0, 0x0, 0x2b, 0x2a, 0x1, 0x0, 0x0, 0x0,
|
||||
0x2c, 0x2f, 0x1, 0x0, 0x0, 0x0, 0x2d, 0x2e, 0x1, 0x0, 0x0, 0x0, 0x2d,
|
||||
0x2b, 0x1, 0x0, 0x0, 0x0, 0x2e, 0x30, 0x1, 0x0, 0x0, 0x0, 0x2f, 0x2d,
|
||||
0x1, 0x0, 0x0, 0x0, 0x30, 0x31, 0x5, 0x27, 0x0, 0x0, 0x31, 0x10,
|
||||
0x1, 0x0, 0x0, 0x0, 0x4, 0x0, 0x1e, 0x25, 0x2d, 0x1, 0x1, 0x4, 0x0,
|
||||
};
|
||||
|
||||
staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0]));
|
||||
|
||||
atn::ATNDeserializer deserializer;
|
||||
staticData->atn = deserializer.deserialize(staticData->serializedATN);
|
||||
|
||||
size_t count = staticData->atn->getNumberOfDecisions();
|
||||
staticData->decisionToDFA.reserve(count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i);
|
||||
}
|
||||
xpathLexerStaticData = staticData.release();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XPathLexer::XPathLexer(CharStream *input) : Lexer(input) {
|
||||
XPathLexer::initialize();
|
||||
_interpreter = new atn::LexerATNSimulator(this, *xpathLexerStaticData->atn, xpathLexerStaticData->decisionToDFA, xpathLexerStaticData->sharedContextCache);
|
||||
}
|
||||
|
||||
XPathLexer::~XPathLexer() {
|
||||
delete _interpreter;
|
||||
}
|
||||
|
||||
std::string XPathLexer::getGrammarFileName() const {
|
||||
return "XPathLexer.g4";
|
||||
}
|
||||
|
||||
const std::vector<std::string>& XPathLexer::getRuleNames() const {
|
||||
return xpathLexerStaticData->ruleNames;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& XPathLexer::getChannelNames() const {
|
||||
return xpathLexerStaticData->channelNames;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& XPathLexer::getModeNames() const {
|
||||
return xpathLexerStaticData->modeNames;
|
||||
}
|
||||
|
||||
const dfa::Vocabulary& XPathLexer::getVocabulary() const {
|
||||
return xpathLexerStaticData->vocabulary;
|
||||
}
|
||||
|
||||
antlr4::atn::SerializedATNView XPathLexer::getSerializedATN() const {
|
||||
return xpathLexerStaticData->serializedATN;
|
||||
}
|
||||
|
||||
const atn::ATN& XPathLexer::getATN() const {
|
||||
return *xpathLexerStaticData->atn;
|
||||
}
|
||||
|
||||
void XPathLexer::action(RuleContext *context, size_t ruleIndex, size_t actionIndex) {
|
||||
switch (ruleIndex) {
|
||||
case 4: IDAction(antlrcpp::downCast<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;
|
||||
}
|
||||
}
|
||||
|
||||
void XPathLexer::initialize() {
|
||||
::antlr4::internal::call_once(xpathLexerOnceFlag, xpathLexerInitialize);
|
||||
}
|
||||
@@ -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 ;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
// Generated from XPathLexer.g4 by ANTLR 4.9.3
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
explicit XPathLexer(antlr4::CharStream *input);
|
||||
|
||||
~XPathLexer() override;
|
||||
|
||||
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 antlr4::dfa::Vocabulary& getVocabulary() const override;
|
||||
|
||||
virtual antlr4::atn::SerializedATNView getSerializedATN() const override;
|
||||
|
||||
virtual const antlr4::atn::ATN& getATN() const override;
|
||||
|
||||
virtual void action(antlr4::RuleContext *context, size_t ruleIndex, size_t actionIndex) override;
|
||||
|
||||
// By default the static state used to implement the lexer is lazily initialized during the first
|
||||
// call to the constructor. You can call this function if you wish to initialize the static state
|
||||
// ahead of time.
|
||||
static void initialize();
|
||||
private:
|
||||
// Individual action functions triggered by action() above.
|
||||
void IDAction(antlr4::RuleContext *context, size_t actionIndex);
|
||||
|
||||
// Individual semantic predicate functions triggered by sempred() above.
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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*/) {
|
||||
}
|
||||
22
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathLexerErrorListener.h
Executable file
22
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathLexerErrorListener.h
Executable file
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
30
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathRuleElement.cpp
Executable file
30
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathRuleElement.cpp
Executable file
@@ -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;
|
||||
}
|
||||
26
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathRuleElement.h
Executable file
26
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathRuleElement.h
Executable file
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
33
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathTokenElement.cpp
Executable file
33
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathTokenElement.cpp
Executable file
@@ -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;
|
||||
}
|
||||
26
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathTokenElement.h
Executable file
26
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathTokenElement.h
Executable file
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
24
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathWildcardElement.cpp
Executable file
24
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathWildcardElement.cpp
Executable file
@@ -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;
|
||||
}
|
||||
23
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathWildcardElement.h
Executable file
23
antlr/antlr4-runtime-4.12.0/runtime/src/tree/xpath/XPathWildcardElement.h
Executable file
@@ -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
|
||||
Reference in New Issue
Block a user