diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2023-12-02 01:45:21 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2023-12-02 02:42:50 +0300 |
commit | 9c43d58f75cf086b744cf4fe2ae180e8f37e4a0c (patch) | |
tree | 9f88a486917d371d099cd712efd91b4c122d209d /contrib/libs/antlr4_cpp_runtime/src/tree/pattern | |
parent | 32fb6dda1feb24f9ab69ece5df0cb9ec238ca5e6 (diff) | |
download | ydb-9c43d58f75cf086b744cf4fe2ae180e8f37e4a0c.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/libs/antlr4_cpp_runtime/src/tree/pattern')
16 files changed, 1492 insertions, 0 deletions
diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/Chunk.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/Chunk.cpp new file mode 100644 index 0000000000..5320f910b9 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/Chunk.cpp @@ -0,0 +1,9 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/pattern/Chunk.h" + +antlr4::tree::pattern::Chunk::~Chunk() { +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/Chunk.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/Chunk.h new file mode 100644 index 0000000000..61079a8ca8 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/Chunk.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A chunk is either a token tag, a rule tag, or a span of literal text within a + /// tree pattern. + /// <p/> + /// The method <seealso cref="ParseTreePatternMatcher#split(String)"/> returns a list of + /// chunks in preparation for creating a token stream by + /// <seealso cref="ParseTreePatternMatcher#tokenize(String)"/>. From there, we get a parse + /// tree from with <seealso cref="ParseTreePatternMatcher#compile(String, int)"/>. These + /// chunks are converted to <seealso cref="RuleTagToken"/>, <seealso cref="TokenTagToken"/>, or the + /// regular tokens of the text surrounding the tags. + /// </summary> + class ANTLR4CPP_PUBLIC Chunk { + public: + Chunk() = default; + Chunk(Chunk const&) = default; + virtual ~Chunk(); + + Chunk& operator=(Chunk const&) = default; + + /// This method returns a text representation of the tag chunk. Labeled tags + /// are returned in the form {@code label:tag}, and unlabeled tags are + /// returned as just the tag name. + virtual std::string toString() { + std::string str; + return str; + } + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreeMatch.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreeMatch.cpp new file mode 100644 index 0000000000..41896d6df7 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreeMatch.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/ParseTreeMatch.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; + +ParseTreeMatch::ParseTreeMatch(ParseTree *tree, const ParseTreePattern &pattern, + const std::map<std::string, std::vector<ParseTree *>> &labels, + ParseTree *mismatchedNode) + : _tree(tree), _pattern(pattern), _labels(labels), _mismatchedNode(mismatchedNode) { + if (tree == nullptr) { + throw IllegalArgumentException("tree cannot be nul"); + } +} + +ParseTreeMatch::~ParseTreeMatch() { +} + +ParseTree* ParseTreeMatch::get(const std::string &label) { + auto iterator = _labels.find(label); + if (iterator == _labels.end() || iterator->second.empty()) { + return nullptr; + } + + return iterator->second.back(); // return last if multiple +} + +std::vector<ParseTree *> ParseTreeMatch::getAll(const std::string &label) { + auto iterator = _labels.find(label); + if (iterator == _labels.end()) { + return {}; + } + + return iterator->second; +} + +std::map<std::string, std::vector<ParseTree *>>& ParseTreeMatch::getLabels() { + return _labels; +} + +ParseTree *ParseTreeMatch::getMismatchedNode() { + return _mismatchedNode; +} + +bool ParseTreeMatch::succeeded() { + return _mismatchedNode == nullptr; +} + +const ParseTreePattern& ParseTreeMatch::getPattern() { + return _pattern; +} + +ParseTree * ParseTreeMatch::getTree() { + return _tree; +} + +std::string ParseTreeMatch::toString() { + if (succeeded()) { + return "Match succeeded; found " + std::to_string(_labels.size()) + " labels"; + } else { + return "Match failed; found " + std::to_string(_labels.size()) + " labels"; + } +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreeMatch.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreeMatch.h new file mode 100644 index 0000000000..eefde46c83 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreeMatch.h @@ -0,0 +1,132 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// Represents the result of matching a ParseTree against a tree pattern. + class ANTLR4CPP_PUBLIC ParseTreeMatch { + private: + /// This is the backing field for getTree(). + ParseTree *_tree; + + /// This is the backing field for getPattern(). + const ParseTreePattern &_pattern; + + /// This is the backing field for getLabels(). + std::map<std::string, std::vector<ParseTree *>> _labels; + + /// This is the backing field for getMismatchedNode(). + ParseTree *_mismatchedNode; + + public: + /// <summary> + /// Constructs a new instance of <seealso cref="ParseTreeMatch"/> from the specified + /// parse tree and pattern. + /// </summary> + /// <param name="tree"> The parse tree to match against the pattern. </param> + /// <param name="pattern"> The parse tree pattern. </param> + /// <param name="labels"> A mapping from label names to collections of + /// <seealso cref="ParseTree"/> objects located by the tree pattern matching process. </param> + /// <param name="mismatchedNode"> The first node which failed to match the tree + /// pattern during the matching process. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code tree} is {@code null} </exception> + /// <exception cref="IllegalArgumentException"> if {@code pattern} is {@code null} </exception> + /// <exception cref="IllegalArgumentException"> if {@code labels} is {@code null} </exception> + ParseTreeMatch(ParseTree *tree, ParseTreePattern const& pattern, + const std::map<std::string, std::vector<ParseTree *>> &labels, ParseTree *mismatchedNode); + ParseTreeMatch(ParseTreeMatch const&) = default; + virtual ~ParseTreeMatch(); + + /// <summary> + /// Get the last node associated with a specific {@code label}. + /// <p/> + /// For example, for pattern {@code <id:ID>}, {@code get("id")} returns the + /// node matched for that {@code ID}. If more than one node + /// matched the specified label, only the last is returned. If there is + /// no node associated with the label, this returns {@code null}. + /// <p/> + /// Pattern tags like {@code <ID>} and {@code <expr>} without labels are + /// considered to be labeled with {@code ID} and {@code expr}, respectively. + /// </summary> + /// <param name="labe"> The label to check. + /// </param> + /// <returns> The last <seealso cref="ParseTree"/> to match a tag with the specified + /// label, or {@code null} if no parse tree matched a tag with the label. </returns> + virtual ParseTree* get(const std::string &label); + + /// <summary> + /// Return all nodes matching a rule or token tag with the specified label. + /// <p/> + /// If the {@code label} is the name of a parser rule or token in the + /// grammar, the resulting list will contain both the parse trees matching + /// rule or tags explicitly labeled with the label and the complete set of + /// parse trees matching the labeled and unlabeled tags in the pattern for + /// the parser rule or token. For example, if {@code label} is {@code "foo"}, + /// the result will contain <em>all</em> of the following. + /// + /// <ul> + /// <li>Parse tree nodes matching tags of the form {@code <foo:anyRuleName>} and + /// {@code <foo:AnyTokenName>}.</li> + /// <li>Parse tree nodes matching tags of the form {@code <anyLabel:foo>}.</li> + /// <li>Parse tree nodes matching tags of the form {@code <foo>}.</li> + /// </ul> + /// </summary> + /// <param name="labe"> The label. + /// </param> + /// <returns> A collection of all <seealso cref="ParseTree"/> nodes matching tags with + /// the specified {@code label}. If no nodes matched the label, an empty list + /// is returned. </returns> + virtual std::vector<ParseTree *> getAll(const std::string &label); + + /// <summary> + /// Return a mapping from label → [list of nodes]. + /// <p/> + /// The map includes special entries corresponding to the names of rules and + /// tokens referenced in tags in the original pattern. For additional + /// information, see the description of <seealso cref="#getAll(String)"/>. + /// </summary> + /// <returns> A mapping from labels to parse tree nodes. If the parse tree + /// pattern did not contain any rule or token tags, this map will be empty. </returns> + virtual std::map<std::string, std::vector<ParseTree *>>& getLabels(); + + /// <summary> + /// Get the node at which we first detected a mismatch. + /// </summary> + /// <returns> the node at which we first detected a mismatch, or {@code null} + /// if the match was successful. </returns> + virtual ParseTree* getMismatchedNode(); + + /// <summary> + /// Gets a value indicating whether the match operation succeeded. + /// </summary> + /// <returns> {@code true} if the match operation succeeded; otherwise, + /// {@code false}. </returns> + virtual bool succeeded(); + + /// <summary> + /// Get the tree pattern we are matching against. + /// </summary> + /// <returns> The tree pattern we are matching against. </returns> + virtual const ParseTreePattern& getPattern(); + + /// <summary> + /// Get the parse tree we are trying to match to a pattern. + /// </summary> + /// <returns> The <seealso cref="ParseTree"/> we are trying to match to a pattern. </returns> + virtual ParseTree* getTree(); + + virtual std::string toString(); + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePattern.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePattern.cpp new file mode 100644 index 0000000000..ca7f8f20d6 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePattern.cpp @@ -0,0 +1,64 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/ParseTree.h" +#include "tree/pattern/ParseTreePatternMatcher.h" +#include "tree/pattern/ParseTreeMatch.h" + +#include "tree/xpath/XPath.h" +#include "tree/xpath/XPathElement.h" + +#include "tree/pattern/ParseTreePattern.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; + +using namespace antlrcpp; + +ParseTreePattern::ParseTreePattern(ParseTreePatternMatcher *matcher, const std::string &pattern, int patternRuleIndex_, + ParseTree *patternTree) + : patternRuleIndex(patternRuleIndex_), _pattern(pattern), _patternTree(patternTree), _matcher(matcher) { +} + +ParseTreePattern::~ParseTreePattern() { +} + +ParseTreeMatch ParseTreePattern::match(ParseTree *tree) { + return _matcher->match(tree, *this); +} + +bool ParseTreePattern::matches(ParseTree *tree) { + return _matcher->match(tree, *this).succeeded(); +} + +std::vector<ParseTreeMatch> ParseTreePattern::findAll(ParseTree *tree, const std::string &xpath) { + xpath::XPath finder(_matcher->getParser(), xpath); + std::vector<ParseTree *> subtrees = finder.evaluate(tree); + std::vector<ParseTreeMatch> matches; + for (auto *t : subtrees) { + ParseTreeMatch aMatch = match(t); + if (aMatch.succeeded()) { + matches.push_back(aMatch); + } + } + return matches; +} + + +ParseTreePatternMatcher *ParseTreePattern::getMatcher() const { + return _matcher; +} + +std::string ParseTreePattern::getPattern() const { + return _pattern; +} + +int ParseTreePattern::getPatternRuleIndex() const { + return patternRuleIndex; +} + +ParseTree* ParseTreePattern::getPatternTree() const { + return _patternTree; +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePattern.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePattern.h new file mode 100644 index 0000000000..d5b86ff473 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePattern.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A pattern like {@code <ID> = <expr>;} converted to a <seealso cref="ParseTree"/> by + /// <seealso cref="ParseTreePatternMatcher#compile(String, int)"/>. + /// </summary> + class ANTLR4CPP_PUBLIC ParseTreePattern { + public: + /// <summary> + /// Construct a new instance of the <seealso cref="ParseTreePattern"/> class. + /// </summary> + /// <param name="matcher"> The <seealso cref="ParseTreePatternMatcher"/> which created this + /// tree pattern. </param> + /// <param name="pattern"> The tree pattern in concrete syntax form. </param> + /// <param name="patternRuleIndex"> The parser rule which serves as the root of the + /// tree pattern. </param> + /// <param name="patternTree"> The tree pattern in <seealso cref="ParseTree"/> form. </param> + ParseTreePattern(ParseTreePatternMatcher *matcher, const std::string &pattern, int patternRuleIndex, + ParseTree *patternTree); + ParseTreePattern(ParseTreePattern const&) = default; + virtual ~ParseTreePattern(); + + /// <summary> + /// Match a specific parse tree against this tree pattern. + /// </summary> + /// <param name="tree"> The parse tree to match against this tree pattern. </param> + /// <returns> A <seealso cref="ParseTreeMatch"/> object describing the result of the + /// match operation. The <seealso cref="ParseTreeMatch#succeeded()"/> method can be + /// used to determine whether or not the match was successful. </returns> + virtual ParseTreeMatch match(ParseTree *tree); + + /// <summary> + /// Determine whether or not a parse tree matches this tree pattern. + /// </summary> + /// <param name="tree"> The parse tree to match against this tree pattern. </param> + /// <returns> {@code true} if {@code tree} is a match for the current tree + /// pattern; otherwise, {@code false}. </returns> + virtual bool matches(ParseTree *tree); + + /// Find all nodes using XPath and then try to match those subtrees against + /// this tree pattern. + /// @param tree The ParseTree to match against this pattern. + /// @param xpath An expression matching the nodes + /// + /// @returns A collection of ParseTreeMatch objects describing the + /// successful matches. Unsuccessful matches are omitted from the result, + /// regardless of the reason for the failure. + virtual std::vector<ParseTreeMatch> findAll(ParseTree *tree, const std::string &xpath); + + /// <summary> + /// Get the <seealso cref="ParseTreePatternMatcher"/> which created this tree pattern. + /// </summary> + /// <returns> The <seealso cref="ParseTreePatternMatcher"/> which created this tree + /// pattern. </returns> + virtual ParseTreePatternMatcher *getMatcher() const; + + /// <summary> + /// Get the tree pattern in concrete syntax form. + /// </summary> + /// <returns> The tree pattern in concrete syntax form. </returns> + virtual std::string getPattern() const; + + /// <summary> + /// Get the parser rule which serves as the outermost rule for the tree + /// pattern. + /// </summary> + /// <returns> The parser rule which serves as the outermost rule for the tree + /// pattern. </returns> + virtual int getPatternRuleIndex() const; + + /// <summary> + /// Get the tree pattern as a <seealso cref="ParseTree"/>. The rule and token tags from + /// the pattern are present in the parse tree as terminal nodes with a symbol + /// of type <seealso cref="RuleTagToken"/> or <seealso cref="TokenTagToken"/>. + /// </summary> + /// <returns> The tree pattern as a <seealso cref="ParseTree"/>. </returns> + virtual ParseTree* getPatternTree() const; + + private: + const int patternRuleIndex; + + /// This is the backing field for <seealso cref="#getPattern()"/>. + const std::string _pattern; + + /// This is the backing field for <seealso cref="#getPatternTree()"/>. + ParseTree *_patternTree; + + /// This is the backing field for <seealso cref="#getMatcher()"/>. + ParseTreePatternMatcher *const _matcher; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePatternMatcher.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePatternMatcher.cpp new file mode 100644 index 0000000000..4c28658954 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePatternMatcher.cpp @@ -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 = "\\"; +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePatternMatcher.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePatternMatcher.h new file mode 100644 index 0000000000..8641fc9a00 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/ParseTreePatternMatcher.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Exceptions.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A tree pattern matching mechanism for ANTLR <seealso cref="ParseTree"/>s. + /// <p/> + /// Patterns are strings of source input text with special tags representing + /// token or rule references such as: + /// <p/> + /// {@code <ID> = <expr>;} + /// <p/> + /// Given a pattern start rule such as {@code statement}, this object constructs + /// a <seealso cref="ParseTree"/> with placeholders for the {@code ID} and {@code expr} + /// subtree. Then the <seealso cref="#match"/> routines can compare an actual + /// <seealso cref="ParseTree"/> from a parse with this pattern. Tag {@code <ID>} matches + /// any {@code ID} token and tag {@code <expr>} references the result of the + /// {@code expr} rule (generally an instance of {@code ExprContext}. + /// <p/> + /// Pattern {@code x = 0;} is a similar pattern that matches the same pattern + /// except that it requires the identifier to be {@code x} and the expression to + /// be {@code 0}. + /// <p/> + /// The <seealso cref="#matches"/> routines return {@code true} or {@code false} based + /// upon a match for the tree rooted at the parameter sent in. The + /// <seealso cref="#match"/> routines return a <seealso cref="ParseTreeMatch"/> object that + /// contains the parse tree, the parse tree pattern, and a map from tag name to + /// matched nodes (more below). A subtree that fails to match, returns with + /// <seealso cref="ParseTreeMatch#mismatchedNode"/> set to the first tree node that did not + /// match. + /// <p/> + /// For efficiency, you can compile a tree pattern in string form to a + /// <seealso cref="ParseTreePattern"/> object. + /// <p/> + /// See {@code TestParseTreeMatcher} for lots of examples. + /// <seealso cref="ParseTreePattern"/> has two static helper methods: + /// <seealso cref="ParseTreePattern#findAll"/> and <seealso cref="ParseTreePattern#match"/> that + /// are easy to use but not super efficient because they create new + /// <seealso cref="ParseTreePatternMatcher"/> objects each time and have to compile the + /// pattern in string form before using it. + /// <p/> + /// The lexer and parser that you pass into the <seealso cref="ParseTreePatternMatcher"/> + /// constructor are used to parse the pattern in string form. The lexer converts + /// the {@code <ID> = <expr>;} into a sequence of four tokens (assuming lexer + /// throws out whitespace or puts it on a hidden channel). Be aware that the + /// input stream is reset for the lexer (but not the parser; a + /// <seealso cref="ParserInterpreter"/> is created to parse the input.). Any user-defined + /// fields you have put into the lexer might get changed when this mechanism asks + /// it to scan the pattern string. + /// <p/> + /// Normally a parser does not accept token {@code <expr>} as a valid + /// {@code expr} but, from the parser passed in, we create a special version of + /// the underlying grammar representation (an <seealso cref="ATN"/>) that allows imaginary + /// tokens representing rules ({@code <expr>}) to match entire rules. We call + /// these <em>bypass alternatives</em>. + /// <p/> + /// Delimiters are {@code <} and {@code >}, with {@code \} as the escape string + /// by default, but you can set them to whatever you want using + /// <seealso cref="#setDelimiters"/>. You must escape both start and stop strings + /// {@code \<} and {@code \>}. + /// </summary> + class ANTLR4CPP_PUBLIC ParseTreePatternMatcher { + public: + class CannotInvokeStartRule : public RuntimeException { + public: + CannotInvokeStartRule(const RuntimeException &e); + ~CannotInvokeStartRule(); + }; + + // Fixes https://github.com/antlr/antlr4/issues/413 + // "Tree pattern compilation doesn't check for a complete parse" + class StartRuleDoesNotConsumeFullPattern : public RuntimeException { + public: + StartRuleDoesNotConsumeFullPattern() = default; + StartRuleDoesNotConsumeFullPattern(StartRuleDoesNotConsumeFullPattern const&) = default; + ~StartRuleDoesNotConsumeFullPattern(); + + StartRuleDoesNotConsumeFullPattern& operator=(StartRuleDoesNotConsumeFullPattern const&) = default; + }; + + /// Constructs a <seealso cref="ParseTreePatternMatcher"/> or from a <seealso cref="Lexer"/> and + /// <seealso cref="Parser"/> object. The lexer input stream is altered for tokenizing + /// the tree patterns. The parser is used as a convenient mechanism to get + /// the grammar name, plus token, rule names. + ParseTreePatternMatcher(Lexer *lexer, Parser *parser); + virtual ~ParseTreePatternMatcher(); + + /// <summary> + /// Set the delimiters used for marking rule and token tags within concrete + /// syntax used by the tree pattern parser. + /// </summary> + /// <param name="start"> The start delimiter. </param> + /// <param name="stop"> The stop delimiter. </param> + /// <param name="escapeLeft"> The escape sequence to use for escaping a start or stop delimiter. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code start} is {@code null} or empty. </exception> + /// <exception cref="IllegalArgumentException"> if {@code stop} is {@code null} or empty. </exception> + virtual void setDelimiters(const std::string &start, const std::string &stop, const std::string &escapeLeft); + + /// <summary> + /// Does {@code pattern} matched as rule {@code patternRuleIndex} match {@code tree}? </summary> + virtual bool matches(ParseTree *tree, const std::string &pattern, int patternRuleIndex); + + /// <summary> + /// Does {@code pattern} matched as rule patternRuleIndex match tree? Pass in a + /// compiled pattern instead of a string representation of a tree pattern. + /// </summary> + virtual bool matches(ParseTree *tree, const ParseTreePattern &pattern); + + /// <summary> + /// Compare {@code pattern} matched as rule {@code patternRuleIndex} against + /// {@code tree} and return a <seealso cref="ParseTreeMatch"/> object that contains the + /// matched elements, or the node at which the match failed. + /// </summary> + virtual ParseTreeMatch match(ParseTree *tree, const std::string &pattern, int patternRuleIndex); + + /// <summary> + /// Compare {@code pattern} matched against {@code tree} and return a + /// <seealso cref="ParseTreeMatch"/> object that contains the matched elements, or the + /// node at which the match failed. Pass in a compiled pattern instead of a + /// string representation of a tree pattern. + /// </summary> + virtual ParseTreeMatch match(ParseTree *tree, const ParseTreePattern &pattern); + + /// <summary> + /// For repeated use of a tree pattern, compile it to a + /// <seealso cref="ParseTreePattern"/> using this method. + /// </summary> + virtual ParseTreePattern compile(const std::string &pattern, int patternRuleIndex); + + /// <summary> + /// Used to convert the tree pattern string into a series of tokens. The + /// input stream is reset. + /// </summary> + virtual Lexer* getLexer(); + + /// <summary> + /// Used to collect to the grammar file name, token names, rule names for + /// used to parse the pattern into a parse tree. + /// </summary> + virtual Parser* getParser(); + + // ---- SUPPORT CODE ---- + + virtual std::vector<std::unique_ptr<Token>> tokenize(const std::string &pattern); + + /// Split "<ID> = <e:expr>;" into 4 chunks for tokenizing by tokenize(). + virtual std::vector<Chunk> split(const std::string &pattern); + + protected: + std::string _start; + std::string _stop; + std::string _escape; // e.g., \< and \> must escape BOTH! + + /// Recursively walk {@code tree} against {@code patternTree}, filling + /// {@code match.}<seealso cref="ParseTreeMatch#labels labels"/>. + /// + /// <returns> the first node encountered in {@code tree} which does not match + /// a corresponding node in {@code patternTree}, or {@code null} if the match + /// was successful. The specific node returned depends on the matching + /// algorithm used by the implementation, and may be overridden. </returns> + virtual ParseTree* matchImpl(ParseTree *tree, ParseTree *patternTree, std::map<std::string, std::vector<ParseTree *>> &labels); + + /// Is t <expr> subtree? + virtual RuleTagToken* getRuleTagToken(ParseTree *t); + + private: + Lexer *_lexer; + Parser *_parser; + + void InitializeInstanceFields(); + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/RuleTagToken.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/RuleTagToken.cpp new file mode 100644 index 0000000000..6f3fb73446 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/RuleTagToken.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/RuleTagToken.h" + +using namespace antlr4::tree::pattern; + +RuleTagToken::RuleTagToken(const std::string &/*ruleName*/, int _bypassTokenType) : bypassTokenType(_bypassTokenType) { +} + +RuleTagToken::RuleTagToken(const std::string &ruleName, size_t bypassTokenType, const std::string &label) + : ruleName(ruleName), bypassTokenType(bypassTokenType), label(label) { + if (ruleName.empty()) { + throw IllegalArgumentException("ruleName cannot be null or empty."); + } + +} + +std::string RuleTagToken::getRuleName() const { + return ruleName; +} + +std::string RuleTagToken::getLabel() const { + return label; +} + +size_t RuleTagToken::getChannel() const { + return DEFAULT_CHANNEL; +} + +std::string RuleTagToken::getText() const { + if (label != "") { + return std::string("<") + label + std::string(":") + ruleName + std::string(">"); + } + + return std::string("<") + ruleName + std::string(">"); +} + +size_t RuleTagToken::getType() const { + return bypassTokenType; +} + +size_t RuleTagToken::getLine() const { + return 0; +} + +size_t RuleTagToken::getCharPositionInLine() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getTokenIndex() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getStartIndex() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getStopIndex() const { + return INVALID_INDEX; +} + +antlr4::TokenSource *RuleTagToken::getTokenSource() const { + return nullptr; +} + +antlr4::CharStream *RuleTagToken::getInputStream() const { + return nullptr; +} + +std::string RuleTagToken::toString() const { + return ruleName + ":" + std::to_string(bypassTokenType); +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/RuleTagToken.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/RuleTagToken.h new file mode 100644 index 0000000000..cb0e50399e --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/RuleTagToken.h @@ -0,0 +1,117 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Token.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A <seealso cref="Token"/> object representing an entire subtree matched by a parser + /// rule; e.g., {@code <expr>}. These tokens are created for <seealso cref="TagChunk"/> + /// chunks where the tag corresponds to a parser rule. + /// </summary> + class ANTLR4CPP_PUBLIC RuleTagToken : public Token { + /// <summary> + /// This is the backing field for <seealso cref="#getRuleName"/>. + /// </summary> + private: + const std::string ruleName; + + /// The token type for the current token. This is the token type assigned to + /// the bypass alternative for the rule during ATN deserialization. + const size_t bypassTokenType; + + /// This is the backing field for <seealso cref="#getLabe"/>. + const std::string label; + + public: + /// <summary> + /// Constructs a new instance of <seealso cref="RuleTagToken"/> with the specified rule + /// name and bypass token type and no label. + /// </summary> + /// <param name="ruleName"> The name of the parser rule this rule tag matches. </param> + /// <param name="bypassTokenType"> The bypass token type assigned to the parser rule. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code ruleName} is {@code null} + /// or empty. </exception> + RuleTagToken(const std::string &ruleName, int bypassTokenType); //this(ruleName, bypassTokenType, nullptr); + + /// <summary> + /// Constructs a new instance of <seealso cref="RuleTagToken"/> with the specified rule + /// name, bypass token type, and label. + /// </summary> + /// <param name="ruleName"> The name of the parser rule this rule tag matches. </param> + /// <param name="bypassTokenType"> The bypass token type assigned to the parser rule. </param> + /// <param name="label"> The label associated with the rule tag, or {@code null} if + /// the rule tag is unlabeled. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code ruleName} is {@code null} + /// or empty. </exception> + RuleTagToken(const std::string &ruleName, size_t bypassTokenType, const std::string &label); + + /// <summary> + /// Gets the name of the rule associated with this rule tag. + /// </summary> + /// <returns> The name of the parser rule associated with this rule tag. </returns> + std::string getRuleName() const; + + /// <summary> + /// Gets the label associated with the rule tag. + /// </summary> + /// <returns> The name of the label associated with the rule tag, or + /// {@code null} if this is an unlabeled rule tag. </returns> + std::string getLabel() const; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// Rule tag tokens are always placed on the <seealso cref="#DEFAULT_CHANNE"/>. + /// </summary> + virtual size_t getChannel() const override; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// This method returns the rule tag formatted with {@code <} and {@code >} + /// delimiters. + /// </summary> + virtual std::string getText() const override; + + /// Rule tag tokens have types assigned according to the rule bypass + /// transitions created during ATN deserialization. + virtual size_t getType() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns 0. + virtual size_t getLine() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getCharPositionInLine() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getTokenIndex() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getStartIndex() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns INVALID_INDEX. + virtual size_t getStopIndex() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns {@code null}. + virtual TokenSource *getTokenSource() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> always returns {@code null}. + virtual CharStream *getInputStream() const override; + + /// The implementation for <seealso cref="RuleTagToken"/> returns a string of the form {@code ruleName:bypassTokenType}. + virtual std::string toString() const override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TagChunk.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TagChunk.cpp new file mode 100644 index 0000000000..63e97aeaa2 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TagChunk.cpp @@ -0,0 +1,39 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/TagChunk.h" + +using namespace antlr4::tree::pattern; + +TagChunk::TagChunk(const std::string &tag) : TagChunk("", tag) { +} + +TagChunk::TagChunk(const std::string &label, const std::string &tag) : _tag(tag), _label(label) { + if (tag.empty()) { + throw IllegalArgumentException("tag cannot be null or empty"); + } + +} + +TagChunk::~TagChunk() { +} + +std::string TagChunk::getTag() { + return _tag; +} + +std::string TagChunk::getLabel() { + return _label; +} + +std::string TagChunk::toString() { + if (!_label.empty()) { + return _label + ":" + _tag; + } + + return _tag; +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TagChunk.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TagChunk.h new file mode 100644 index 0000000000..1cdae78995 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TagChunk.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Chunk.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// Represents a placeholder tag in a tree pattern. A tag can have any of the + /// following forms. + /// + /// <ul> + /// <li>{@code expr}: An unlabeled placeholder for a parser rule {@code expr}.</li> + /// <li>{@code ID}: An unlabeled placeholder for a token of type {@code ID}.</li> + /// <li>{@code e:expr}: A labeled placeholder for a parser rule {@code expr}.</li> + /// <li>{@code id:ID}: A labeled placeholder for a token of type {@code ID}.</li> + /// </ul> + /// + /// This class does not perform any validation on the tag or label names aside + /// from ensuring that the tag is a non-null, non-empty string. + /// </summary> + class ANTLR4CPP_PUBLIC TagChunk : public Chunk { + public: + /// <summary> + /// Construct a new instance of <seealso cref="TagChunk"/> using the specified tag and + /// no label. + /// </summary> + /// <param name="tag"> The tag, which should be the name of a parser rule or token + /// type. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code tag} is {@code null} or + /// empty. </exception> + TagChunk(const std::string &tag); + virtual ~TagChunk(); + + /// <summary> + /// Construct a new instance of <seealso cref="TagChunk"/> using the specified label + /// and tag. + /// </summary> + /// <param name="label"> The label for the tag. If this is {@code null}, the + /// <seealso cref="TagChunk"/> represents an unlabeled tag. </param> + /// <param name="tag"> The tag, which should be the name of a parser rule or token + /// type. + /// </param> + /// <exception cref="IllegalArgumentException"> if {@code tag} is {@code null} or + /// empty. </exception> + TagChunk(const std::string &label, const std::string &tag); + + /// <summary> + /// Get the tag for this chunk. + /// </summary> + /// <returns> The tag for the chunk. </returns> + std::string getTag(); + + /// <summary> + /// Get the label, if any, assigned to this chunk. + /// </summary> + /// <returns> The label assigned to this chunk, or {@code null} if no label is + /// assigned to the chunk. </returns> + std::string getLabel(); + + /// <summary> + /// This method returns a text representation of the tag chunk. Labeled tags + /// are returned in the form {@code label:tag}, and unlabeled tags are + /// returned as just the tag name. + /// </summary> + virtual std::string toString() override; + + private: + /// This is the backing field for <seealso cref="#getTag"/>. + const std::string _tag; + /// <summary> + /// This is the backing field for <seealso cref="#getLabe"/>. + /// </summary> + const std::string _label; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TextChunk.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TextChunk.cpp new file mode 100644 index 0000000000..8e2e6689d7 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TextChunk.cpp @@ -0,0 +1,28 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/TextChunk.h" + +using namespace antlr4::tree::pattern; + +TextChunk::TextChunk(const std::string &text) : text(text) { + if (text == "") { + throw IllegalArgumentException("text cannot be nul"); + } + +} + +TextChunk::~TextChunk() { +} + +std::string TextChunk::getText() { + return text; +} + +std::string TextChunk::toString() { + return std::string("'") + text + std::string("'"); +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TextChunk.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TextChunk.h new file mode 100644 index 0000000000..bb7fc7f966 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TextChunk.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Chunk.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// Represents a span of raw text (concrete syntax) between tags in a tree + /// pattern string. + /// </summary> + class ANTLR4CPP_PUBLIC TextChunk : public Chunk { + private: + /// <summary> + /// This is the backing field for <seealso cref="#getText"/>. + /// </summary> + const std::string text; + + /// <summary> + /// Constructs a new instance of <seealso cref="TextChunk"/> with the specified text. + /// </summary> + /// <param name="text"> The text of this chunk. </param> + /// <exception cref="IllegalArgumentException"> if {@code text} is {@code null}. </exception> + public: + TextChunk(const std::string &text); + virtual ~TextChunk(); + + /// <summary> + /// Gets the raw text of this chunk. + /// </summary> + /// <returns> The text of the chunk. </returns> + std::string getText(); + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// The implementation for <seealso cref="TextChunk"/> returns the result of + /// <seealso cref="#getText()"/> in single quotes. + /// </summary> + virtual std::string toString() override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TokenTagToken.cpp b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TokenTagToken.cpp new file mode 100644 index 0000000000..f5153c8357 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TokenTagToken.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/pattern/TokenTagToken.h" + +using namespace antlr4::tree::pattern; + +TokenTagToken::TokenTagToken(const std::string &/*tokenName*/, int type) + : CommonToken(type), tokenName(""), label("") { +} + +TokenTagToken::TokenTagToken(const std::string &tokenName, int type, const std::string &label) + : CommonToken(type), tokenName(tokenName), label(label) { +} + +std::string TokenTagToken::getTokenName() const { + return tokenName; +} + +std::string TokenTagToken::getLabel() const { + return label; +} + +std::string TokenTagToken::getText() const { + if (!label.empty()) { + return "<" + label + ":" + tokenName + ">"; + } + + return "<" + tokenName + ">"; +} + +std::string TokenTagToken::toString() const { + return tokenName + ":" + std::to_string(_type); +} diff --git a/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TokenTagToken.h b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TokenTagToken.h new file mode 100644 index 0000000000..da9e11cd36 --- /dev/null +++ b/contrib/libs/antlr4_cpp_runtime/src/tree/pattern/TokenTagToken.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "CommonToken.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// <summary> + /// A <seealso cref="Token"/> object representing a token of a particular type; e.g., + /// {@code <ID>}. These tokens are created for <seealso cref="TagChunk"/> chunks where the + /// tag corresponds to a lexer rule or token type. + /// </summary> + class ANTLR4CPP_PUBLIC TokenTagToken : public CommonToken { + /// <summary> + /// This is the backing field for <seealso cref="#getTokenName"/>. + /// </summary> + private: + const std::string tokenName; + /// <summary> + /// This is the backing field for <seealso cref="#getLabe"/>. + /// </summary> + const std::string label; + + /// <summary> + /// Constructs a new instance of <seealso cref="TokenTagToken"/> for an unlabeled tag + /// with the specified token name and type. + /// </summary> + /// <param name="tokenName"> The token name. </param> + /// <param name="type"> The token type. </param> + public: + TokenTagToken(const std::string &tokenName, int type); //this(tokenName, type, nullptr); + + /// <summary> + /// Constructs a new instance of <seealso cref="TokenTagToken"/> with the specified + /// token name, type, and label. + /// </summary> + /// <param name="tokenName"> The token name. </param> + /// <param name="type"> The token type. </param> + /// <param name="label"> The label associated with the token tag, or {@code null} if + /// the token tag is unlabeled. </param> + TokenTagToken(const std::string &tokenName, int type, const std::string &label); + + /// <summary> + /// Gets the token name. </summary> + /// <returns> The token name. </returns> + std::string getTokenName() const; + + /// <summary> + /// Gets the label associated with the rule tag. + /// </summary> + /// <returns> The name of the label associated with the rule tag, or + /// {@code null} if this is an unlabeled rule tag. </returns> + std::string getLabel() const; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// The implementation for <seealso cref="TokenTagToken"/> returns the token tag + /// formatted with {@code <} and {@code >} delimiters. + /// </summary> + virtual std::string getText() const override; + + /// <summary> + /// {@inheritDoc} + /// <p/> + /// The implementation for <seealso cref="TokenTagToken"/> returns a string of the form + /// {@code tokenName:type}. + /// </summary> + virtual std::string toString() const override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 |