From c6ad2948bb98d42f8e0883ef82cd14cd2d5eda60 Mon Sep 17 00:00:00 2001 From: Patrick Schönberger Date: Sat, 14 Aug 2021 14:56:12 +0200 Subject: add antlr source code and ReadMe --- .../runtime/src/tree/pattern/Chunk.cpp | 9 + .../runtime/src/tree/pattern/Chunk.h | 44 +++ .../runtime/src/tree/pattern/ParseTreeMatch.cpp | 69 ++++ .../runtime/src/tree/pattern/ParseTreeMatch.h | 132 ++++++++ .../runtime/src/tree/pattern/ParseTreePattern.cpp | 64 ++++ .../runtime/src/tree/pattern/ParseTreePattern.h | 105 ++++++ .../src/tree/pattern/ParseTreePatternMatcher.cpp | 371 +++++++++++++++++++++ .../src/tree/pattern/ParseTreePatternMatcher.h | 185 ++++++++++ .../runtime/src/tree/pattern/RuleTagToken.cpp | 77 +++++ .../runtime/src/tree/pattern/RuleTagToken.h | 117 +++++++ .../runtime/src/tree/pattern/TagChunk.cpp | 39 +++ .../runtime/src/tree/pattern/TagChunk.h | 86 +++++ .../runtime/src/tree/pattern/TextChunk.cpp | 28 ++ .../runtime/src/tree/pattern/TextChunk.h | 51 +++ .../runtime/src/tree/pattern/TokenTagToken.cpp | 36 ++ .../runtime/src/tree/pattern/TokenTagToken.h | 80 +++++ 16 files changed, 1493 insertions(+) create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp create mode 100644 antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h (limited to 'antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern') diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp new file mode 100644 index 0000000..5320f91 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.cpp @@ -0,0 +1,9 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/pattern/Chunk.h" + +antlr4::tree::pattern::Chunk::~Chunk() { +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h new file mode 100644 index 0000000..42e7838 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/Chunk.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// A chunk is either a token tag, a rule tag, or a span of literal text within a + /// tree pattern. + ///

+ /// The method returns a list of + /// chunks in preparation for creating a token stream by + /// . From there, we get a parse + /// tree from with . These + /// chunks are converted to , , or the + /// regular tokens of the text surrounding the tags. + ///

+ class ANTLR4CPP_PUBLIC Chunk { + public: + Chunk() = default; + Chunk(Chunk const&) = default; + virtual ~Chunk(); + + Chunk& operator=(Chunk const&) = default; + + /// This method returns a text representation of the tag chunk. Labeled tags + /// are returned in the form {@code label:tag}, and unlabeled tags are + /// returned as just the tag name. + virtual std::string toString() { + std::string str; + return str; + } + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp new file mode 100644 index 0000000..ce34b3f --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/ParseTreeMatch.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; + +ParseTreeMatch::ParseTreeMatch(ParseTree *tree, const ParseTreePattern &pattern, + const std::map> &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 ParseTreeMatch::getAll(const std::string &label) { + auto iterator = _labels.find(label); + if (iterator == _labels.end()) { + return {}; + } + + return iterator->second; +} + +std::map>& ParseTreeMatch::getLabels() { + return _labels; +} + +ParseTree *ParseTreeMatch::getMismatchedNode() { + return _mismatchedNode; +} + +bool ParseTreeMatch::succeeded() { + return _mismatchedNode == nullptr; +} + +const ParseTreePattern& ParseTreeMatch::getPattern() { + return _pattern; +} + +ParseTree * ParseTreeMatch::getTree() { + return _tree; +} + +std::string ParseTreeMatch::toString() { + if (succeeded()) { + return "Match succeeded; found " + std::to_string(_labels.size()) + " labels"; + } else { + return "Match failed; found " + std::to_string(_labels.size()) + " labels"; + } +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h new file mode 100644 index 0000000..eefde46 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreeMatch.h @@ -0,0 +1,132 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// Represents the result of matching a ParseTree against a tree pattern. + class ANTLR4CPP_PUBLIC ParseTreeMatch { + private: + /// This is the backing field for getTree(). + ParseTree *_tree; + + /// This is the backing field for getPattern(). + const ParseTreePattern &_pattern; + + /// This is the backing field for getLabels(). + std::map> _labels; + + /// This is the backing field for getMismatchedNode(). + ParseTree *_mismatchedNode; + + public: + /// + /// Constructs a new instance of from the specified + /// parse tree and pattern. + /// + /// The parse tree to match against the pattern. + /// The parse tree pattern. + /// A mapping from label names to collections of + /// objects located by the tree pattern matching process. + /// The first node which failed to match the tree + /// pattern during the matching process. + /// + /// if {@code tree} is {@code null} + /// if {@code pattern} is {@code null} + /// if {@code labels} is {@code null} + ParseTreeMatch(ParseTree *tree, ParseTreePattern const& pattern, + const std::map> &labels, ParseTree *mismatchedNode); + ParseTreeMatch(ParseTreeMatch const&) = default; + virtual ~ParseTreeMatch(); + + /// + /// Get the last node associated with a specific {@code label}. + ///

+ /// For example, for pattern {@code }, {@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}. + ///

+ /// Pattern tags like {@code } and {@code } without labels are + /// considered to be labeled with {@code ID} and {@code expr}, respectively. + ///

+ /// The label to check. + /// + /// The last to match a tag with the specified + /// label, or {@code null} if no parse tree matched a tag with the label. + virtual ParseTree* get(const std::string &label); + + /// + /// Return all nodes matching a rule or token tag with the specified label. + ///

+ /// 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 all of the following. + /// + ///

    + ///
  • Parse tree nodes matching tags of the form {@code } and + /// {@code }.
  • + ///
  • Parse tree nodes matching tags of the form {@code }.
  • + ///
  • Parse tree nodes matching tags of the form {@code }.
  • + ///
+ ///
+ /// The label. + /// + /// A collection of all nodes matching tags with + /// the specified {@code label}. If no nodes matched the label, an empty list + /// is returned. + virtual std::vector getAll(const std::string &label); + + /// + /// Return a mapping from label → [list of nodes]. + ///

+ /// 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 . + ///

+ /// 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. + virtual std::map>& getLabels(); + + /// + /// Get the node at which we first detected a mismatch. + /// + /// the node at which we first detected a mismatch, or {@code null} + /// if the match was successful. + virtual ParseTree* getMismatchedNode(); + + /// + /// Gets a value indicating whether the match operation succeeded. + /// + /// {@code true} if the match operation succeeded; otherwise, + /// {@code false}. + virtual bool succeeded(); + + /// + /// Get the tree pattern we are matching against. + /// + /// The tree pattern we are matching against. + virtual const ParseTreePattern& getPattern(); + + /// + /// Get the parse tree we are trying to match to a pattern. + /// + /// The we are trying to match to a pattern. + virtual ParseTree* getTree(); + + virtual std::string toString(); + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp new file mode 100644 index 0000000..50f44c8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.cpp @@ -0,0 +1,64 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/ParseTree.h" +#include "tree/pattern/ParseTreePatternMatcher.h" +#include "tree/pattern/ParseTreeMatch.h" + +#include "tree/xpath/XPath.h" +#include "tree/xpath/XPathElement.h" + +#include "tree/pattern/ParseTreePattern.h" + +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; + +using namespace antlrcpp; + +ParseTreePattern::ParseTreePattern(ParseTreePatternMatcher *matcher, const std::string &pattern, int patternRuleIndex_, + ParseTree *patternTree) + : patternRuleIndex(patternRuleIndex_), _pattern(pattern), _patternTree(patternTree), _matcher(matcher) { +} + +ParseTreePattern::~ParseTreePattern() { +} + +ParseTreeMatch ParseTreePattern::match(ParseTree *tree) { + return _matcher->match(tree, *this); +} + +bool ParseTreePattern::matches(ParseTree *tree) { + return _matcher->match(tree, *this).succeeded(); +} + +std::vector ParseTreePattern::findAll(ParseTree *tree, const std::string &xpath) { + xpath::XPath finder(_matcher->getParser(), xpath); + std::vector subtrees = finder.evaluate(tree); + std::vector matches; + for (auto *t : subtrees) { + ParseTreeMatch aMatch = match(t); + if (aMatch.succeeded()) { + matches.push_back(aMatch); + } + } + return matches; +} + + +ParseTreePatternMatcher *ParseTreePattern::getMatcher() const { + return _matcher; +} + +std::string ParseTreePattern::getPattern() const { + return _pattern; +} + +int ParseTreePattern::getPatternRuleIndex() const { + return patternRuleIndex; +} + +ParseTree* ParseTreePattern::getPatternTree() const { + return _patternTree; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h new file mode 100644 index 0000000..d5b86ff --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePattern.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "antlr4-common.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// A pattern like {@code = ;} converted to a by + /// . + /// + class ANTLR4CPP_PUBLIC ParseTreePattern { + public: + /// + /// Construct a new instance of the class. + /// + /// The which created this + /// tree pattern. + /// The tree pattern in concrete syntax form. + /// The parser rule which serves as the root of the + /// tree pattern. + /// The tree pattern in form. + ParseTreePattern(ParseTreePatternMatcher *matcher, const std::string &pattern, int patternRuleIndex, + ParseTree *patternTree); + ParseTreePattern(ParseTreePattern const&) = default; + virtual ~ParseTreePattern(); + + /// + /// Match a specific parse tree against this tree pattern. + /// + /// The parse tree to match against this tree pattern. + /// A object describing the result of the + /// match operation. The method can be + /// used to determine whether or not the match was successful. + virtual ParseTreeMatch match(ParseTree *tree); + + /// + /// Determine whether or not a parse tree matches this tree pattern. + /// + /// The parse tree to match against this tree pattern. + /// {@code true} if {@code tree} is a match for the current tree + /// pattern; otherwise, {@code false}. + 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 findAll(ParseTree *tree, const std::string &xpath); + + /// + /// Get the which created this tree pattern. + /// + /// The which created this tree + /// pattern. + virtual ParseTreePatternMatcher *getMatcher() const; + + /// + /// Get the tree pattern in concrete syntax form. + /// + /// The tree pattern in concrete syntax form. + virtual std::string getPattern() const; + + /// + /// Get the parser rule which serves as the outermost rule for the tree + /// pattern. + /// + /// The parser rule which serves as the outermost rule for the tree + /// pattern. + virtual int getPatternRuleIndex() const; + + /// + /// Get the tree pattern as a . The rule and token tags from + /// the pattern are present in the parse tree as terminal nodes with a symbol + /// of type or . + /// + /// The tree pattern as a . + virtual ParseTree* getPatternTree() const; + + private: + const int patternRuleIndex; + + /// This is the backing field for . + const std::string _pattern; + + /// This is the backing field for . + ParseTree *_patternTree; + + /// This is the backing field for . + ParseTreePatternMatcher *const _matcher; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp new file mode 100644 index 0000000..2e58a96 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp @@ -0,0 +1,371 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/pattern/ParseTreePattern.h" +#include "tree/pattern/ParseTreeMatch.h" +#include "tree/TerminalNode.h" +#include "CommonTokenStream.h" +#include "ParserInterpreter.h" +#include "tree/pattern/TokenTagToken.h" +#include "ParserRuleContext.h" +#include "tree/pattern/RuleTagToken.h" +#include "tree/pattern/TagChunk.h" +#include "atn/ATN.h" +#include "Lexer.h" +#include "BailErrorStrategy.h" + +#include "ListTokenSource.h" +#include "tree/pattern/TextChunk.h" +#include "ANTLRInputStream.h" +#include "support/Arrays.h" +#include "Exceptions.h" +#include "support/StringUtils.h" +#include "support/CPPUtils.h" + +#include "tree/pattern/ParseTreePatternMatcher.h" + +using namespace antlr4; +using namespace antlr4::tree; +using namespace antlr4::tree::pattern; +using namespace antlrcpp; + +ParseTreePatternMatcher::CannotInvokeStartRule::CannotInvokeStartRule(const RuntimeException &e) : RuntimeException(e.what()) { +} + +ParseTreePatternMatcher::CannotInvokeStartRule::~CannotInvokeStartRule() { +} + +ParseTreePatternMatcher::StartRuleDoesNotConsumeFullPattern::~StartRuleDoesNotConsumeFullPattern() { +} + +ParseTreePatternMatcher::ParseTreePatternMatcher(Lexer *lexer, Parser *parser) : _lexer(lexer), _parser(parser) { + InitializeInstanceFields(); +} + +ParseTreePatternMatcher::~ParseTreePatternMatcher() { +} + +void ParseTreePatternMatcher::setDelimiters(const std::string &start, const std::string &stop, const std::string &escapeLeft) { + if (start.empty()) { + throw IllegalArgumentException("start cannot be null or empty"); + } + + if (stop.empty()) { + throw IllegalArgumentException("stop cannot be null or empty"); + } + + _start = start; + _stop = stop; + _escape = escapeLeft; +} + +bool ParseTreePatternMatcher::matches(ParseTree *tree, const std::string &pattern, int patternRuleIndex) { + ParseTreePattern p = compile(pattern, patternRuleIndex); + return matches(tree, p); +} + +bool ParseTreePatternMatcher::matches(ParseTree *tree, const ParseTreePattern &pattern) { + std::map> 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> 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()); + tree = parserInterp.parse(patternRuleIndex); + } catch (ParseCancellationException &e) { +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026 + // rethrow_if_nested is not available before VS 2015. + throw e; +#else + std::rethrow_if_nested(e); // Unwrap the nested exception. +#endif + } catch (RecognitionException &re) { + throw re; +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026 + } catch (std::exception &e) { + // throw_with_nested is not available before VS 2015. + throw e; +#else + } catch (std::exception & /*e*/) { + std::throw_with_nested((const char*)"Cannot invoke start rule"); // Wrap any other exception. We should however probably use one of the ANTLR exceptions here. +#endif + } + + // Make sure tree pattern compilation checks for a complete parse + if (tokens.LA(1) != Token::EOF) { + throw StartRuleDoesNotConsumeFullPattern(); + } + + return ParseTreePattern(this, pattern, patternRuleIndex, tree); +} + +Lexer* ParseTreePatternMatcher::getLexer() { + return _lexer; +} + +Parser* ParseTreePatternMatcher::getParser() { + return _parser; +} + +ParseTree* ParseTreePatternMatcher::matchImpl(ParseTree *tree, ParseTree *patternTree, + std::map> &labels) { + if (tree == nullptr) { + throw IllegalArgumentException("tree cannot be nul"); + } + + if (patternTree == nullptr) { + throw IllegalArgumentException("patternTree cannot be nul"); + } + + // x and , x and y, or x and x; or could be mismatched types + if (is(tree) && is(patternTree)) { + TerminalNode *t1 = dynamic_cast(tree); + TerminalNode *t2 = dynamic_cast(patternTree); + + ParseTree *mismatchedNode = nullptr; + // both are tokens and they have same type + if (t1->getSymbol()->getType() == t2->getSymbol()->getType()) { + if (is(t2->getSymbol())) { // x and + TokenTagToken *tokenTagToken = dynamic_cast(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(tree) && is(patternTree)) { + ParserRuleContext *r1 = dynamic_cast(tree); + ParserRuleContext *r2 = dynamic_cast(patternTree); + ParseTree *mismatchedNode = nullptr; + + // (expr ...) and + 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(t->children[0])) { + TerminalNode *c = dynamic_cast(t->children[0]); + if (is(c->getSymbol())) { + return dynamic_cast(c->getSymbol()); + } + } + return nullptr; +} + +std::vector> ParseTreePatternMatcher::tokenize(const std::string &pattern) { + // split pattern into chunks: sea (raw input) and islands (, ) + std::vector chunks = split(pattern); + + // create token stream from text and tags + std::vector> tokens; + for (auto chunk : chunks) { + if (is(&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 t(_lexer->nextToken()); + while (t->getType() != Token::EOF) { + tokens.push_back(std::move(t)); + t = _lexer->nextToken(); + } + _lexer->setInputStream(nullptr); + } + } + + return tokens; +} + +std::vector ParseTreePatternMatcher::split(const std::string &pattern) { + size_t p = 0; + size_t n = pattern.length(); + std::vector chunks; + + // find all start and stop indexes first, then collect + std::vector starts; + std::vector 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 + 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 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(&c)) { + TextChunk &tc = (TextChunk&)c; + std::string unescaped = tc.getText(); + unescaped.erase(std::remove(unescaped.begin(), unescaped.end(), '\\'), unescaped.end()); + if (unescaped.length() < tc.getText().length()) { + chunks[i] = TextChunk(unescaped); + } + } + } + + return chunks; +} + +void ParseTreePatternMatcher::InitializeInstanceFields() { + _start = "<"; + _stop = ">"; + _escape = "\\"; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h new file mode 100644 index 0000000..e77c7bc --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/ParseTreePatternMatcher.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Exceptions.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// A tree pattern matching mechanism for ANTLR s. + ///

+ /// Patterns are strings of source input text with special tags representing + /// token or rule references such as: + ///

+ /// {@code = ;} + ///

+ /// Given a pattern start rule such as {@code statement}, this object constructs + /// a with placeholders for the {@code ID} and {@code expr} + /// subtree. Then the routines can compare an actual + /// from a parse with this pattern. Tag {@code } matches + /// any {@code ID} token and tag {@code } references the result of the + /// {@code expr} rule (generally an instance of {@code ExprContext}. + ///

+ /// 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}. + ///

+ /// The routines return {@code true} or {@code false} based + /// upon a match for the tree rooted at the parameter sent in. The + /// routines return a 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 + /// set to the first tree node that did not + /// match. + ///

+ /// For efficiency, you can compile a tree pattern in string form to a + /// object. + ///

+ /// See {@code TestParseTreeMatcher} for lots of examples. + /// has two static helper methods: + /// and that + /// are easy to use but not super efficient because they create new + /// objects each time and have to compile the + /// pattern in string form before using it. + ///

+ /// The lexer and parser that you pass into the + /// constructor are used to parse the pattern in string form. The lexer converts + /// the {@code = ;} 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 + /// 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. + ///

+ /// Normally a parser does not accept token {@code } as a valid + /// {@code expr} but, from the parser passed in, we create a special version of + /// the underlying grammar representation (an ) that allows imaginary + /// tokens representing rules ({@code }) to match entire rules. We call + /// these bypass alternatives. + ///

+ /// Delimiters are {@code <} and {@code >}, with {@code \} as the escape string + /// by default, but you can set them to whatever you want using + /// . You must escape both start and stop strings + /// {@code \<} and {@code \>}. + ///

+ 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 or from a and + /// 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(); + + /// + /// Set the delimiters used for marking rule and token tags within concrete + /// syntax used by the tree pattern parser. + /// + /// The start delimiter. + /// The stop delimiter. + /// The escape sequence to use for escaping a start or stop delimiter. + /// + /// if {@code start} is {@code null} or empty. + /// if {@code stop} is {@code null} or empty. + virtual void setDelimiters(const std::string &start, const std::string &stop, const std::string &escapeLeft); + + /// + /// Does {@code pattern} matched as rule {@code patternRuleIndex} match {@code tree}? + virtual bool matches(ParseTree *tree, const std::string &pattern, int patternRuleIndex); + + /// + /// Does {@code pattern} matched as rule patternRuleIndex match tree? Pass in a + /// compiled pattern instead of a string representation of a tree pattern. + /// + virtual bool matches(ParseTree *tree, const ParseTreePattern &pattern); + + /// + /// Compare {@code pattern} matched as rule {@code patternRuleIndex} against + /// {@code tree} and return a object that contains the + /// matched elements, or the node at which the match failed. + /// + virtual ParseTreeMatch match(ParseTree *tree, const std::string &pattern, int patternRuleIndex); + + /// + /// Compare {@code pattern} matched against {@code tree} and return a + /// 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. + /// + virtual ParseTreeMatch match(ParseTree *tree, const ParseTreePattern &pattern); + + /// + /// For repeated use of a tree pattern, compile it to a + /// using this method. + /// + virtual ParseTreePattern compile(const std::string &pattern, int patternRuleIndex); + + /// + /// Used to convert the tree pattern string into a series of tokens. The + /// input stream is reset. + /// + virtual Lexer* getLexer(); + + /// + /// Used to collect to the grammar file name, token names, rule names for + /// used to parse the pattern into a parse tree. + /// + virtual Parser* getParser(); + + // ---- SUPPORT CODE ---- + + virtual std::vector> tokenize(const std::string &pattern); + + /// Split " = ;" into 4 chunks for tokenizing by tokenize(). + virtual std::vector 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.}. + /// + /// 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. + virtual ParseTree* matchImpl(ParseTree *tree, ParseTree *patternTree, std::map> &labels); + + /// Is t subtree? + virtual RuleTagToken* getRuleTagToken(ParseTree *t); + + private: + Lexer *_lexer; + Parser *_parser; + + void InitializeInstanceFields(); + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp new file mode 100644 index 0000000..4e33f98 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/RuleTagToken.h" + +using namespace antlr4::tree::pattern; + +RuleTagToken::RuleTagToken(const std::string &/*ruleName*/, int _bypassTokenType) : bypassTokenType(_bypassTokenType) { +} + +RuleTagToken::RuleTagToken(const std::string &ruleName, size_t bypassTokenType, const std::string &label) + : ruleName(ruleName), bypassTokenType(bypassTokenType), label(label) { + if (ruleName.empty()) { + throw IllegalArgumentException("ruleName cannot be null or empty."); + } + +} + +std::string RuleTagToken::getRuleName() const { + return ruleName; +} + +std::string RuleTagToken::getLabel() const { + return label; +} + +size_t RuleTagToken::getChannel() const { + return DEFAULT_CHANNEL; +} + +std::string RuleTagToken::getText() const { + if (label != "") { + return std::string("<") + label + std::string(":") + ruleName + std::string(">"); + } + + return std::string("<") + ruleName + std::string(">"); +} + +size_t RuleTagToken::getType() const { + return bypassTokenType; +} + +size_t RuleTagToken::getLine() const { + return 0; +} + +size_t RuleTagToken::getCharPositionInLine() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getTokenIndex() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getStartIndex() const { + return INVALID_INDEX; +} + +size_t RuleTagToken::getStopIndex() const { + return INVALID_INDEX; +} + +antlr4::TokenSource *RuleTagToken::getTokenSource() const { + return nullptr; +} + +antlr4::CharStream *RuleTagToken::getInputStream() const { + return nullptr; +} + +std::string RuleTagToken::toString() const { + return ruleName + ":" + std::to_string(bypassTokenType); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h new file mode 100644 index 0000000..368ae41 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/RuleTagToken.h @@ -0,0 +1,117 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Token.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// A object representing an entire subtree matched by a parser + /// rule; e.g., {@code }. These tokens are created for + /// chunks where the tag corresponds to a parser rule. + /// + class ANTLR4CPP_PUBLIC RuleTagToken : public Token { + /// + /// This is the backing field for . + /// + 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 . + const std::string label; + + public: + /// + /// Constructs a new instance of with the specified rule + /// name and bypass token type and no label. + /// + /// The name of the parser rule this rule tag matches. + /// The bypass token type assigned to the parser rule. + /// + /// if {@code ruleName} is {@code null} + /// or empty. + RuleTagToken(const std::string &ruleName, int bypassTokenType); //this(ruleName, bypassTokenType, nullptr); + + /// + /// Constructs a new instance of with the specified rule + /// name, bypass token type, and label. + /// + /// The name of the parser rule this rule tag matches. + /// The bypass token type assigned to the parser rule. + /// The label associated with the rule tag, or {@code null} if + /// the rule tag is unlabeled. + /// + /// if {@code ruleName} is {@code null} + /// or empty. + RuleTagToken(const std::string &ruleName, size_t bypassTokenType, const std::string &label); + + /// + /// Gets the name of the rule associated with this rule tag. + /// + /// The name of the parser rule associated with this rule tag. + std::string getRuleName() const; + + /// + /// Gets the label associated with the rule tag. + /// + /// The name of the label associated with the rule tag, or + /// {@code null} if this is an unlabeled rule tag. + std::string getLabel() const; + + /// + /// {@inheritDoc} + ///

+ /// Rule tag tokens are always placed on the . + ///

+ virtual size_t getChannel() const override; + + /// + /// {@inheritDoc} + ///

+ /// This method returns the rule tag formatted with {@code <} and {@code >} + /// delimiters. + ///

+ 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 always returns 0. + virtual size_t getLine() const override; + + /// The implementation for always returns INVALID_INDEX. + virtual size_t getCharPositionInLine() const override; + + /// The implementation for always returns INVALID_INDEX. + virtual size_t getTokenIndex() const override; + + /// The implementation for always returns INVALID_INDEX. + virtual size_t getStartIndex() const override; + + /// The implementation for always returns INVALID_INDEX. + virtual size_t getStopIndex() const override; + + /// The implementation for always returns {@code null}. + virtual TokenSource *getTokenSource() const override; + + /// The implementation for always returns {@code null}. + virtual CharStream *getInputStream() const override; + + /// The implementation for returns a string of the form {@code ruleName:bypassTokenType}. + virtual std::string toString() const override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp new file mode 100644 index 0000000..77f2b4c --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.cpp @@ -0,0 +1,39 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/TagChunk.h" + +using namespace antlr4::tree::pattern; + +TagChunk::TagChunk(const std::string &tag) : TagChunk("", tag) { +} + +TagChunk::TagChunk(const std::string &label, const std::string &tag) : _tag(tag), _label(label) { + if (tag.empty()) { + throw IllegalArgumentException("tag cannot be null or empty"); + } + +} + +TagChunk::~TagChunk() { +} + +std::string TagChunk::getTag() { + return _tag; +} + +std::string TagChunk::getLabel() { + return _label; +} + +std::string TagChunk::toString() { + if (!_label.empty()) { + return _label + ":" + _tag; + } + + return _tag; +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h new file mode 100644 index 0000000..3d0c9f8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TagChunk.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Chunk.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// Represents a placeholder tag in a tree pattern. A tag can have any of the + /// following forms. + /// + ///
    + ///
  • {@code expr}: An unlabeled placeholder for a parser rule {@code expr}.
  • + ///
  • {@code ID}: An unlabeled placeholder for a token of type {@code ID}.
  • + ///
  • {@code e:expr}: A labeled placeholder for a parser rule {@code expr}.
  • + ///
  • {@code id:ID}: A labeled placeholder for a token of type {@code ID}.
  • + ///
+ /// + /// 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. + ///
+ class ANTLR4CPP_PUBLIC TagChunk : public Chunk { + public: + /// + /// Construct a new instance of using the specified tag and + /// no label. + /// + /// The tag, which should be the name of a parser rule or token + /// type. + /// + /// if {@code tag} is {@code null} or + /// empty. + TagChunk(const std::string &tag); + virtual ~TagChunk(); + + /// + /// Construct a new instance of using the specified label + /// and tag. + /// + /// The label for the tag. If this is {@code null}, the + /// represents an unlabeled tag. + /// The tag, which should be the name of a parser rule or token + /// type. + /// + /// if {@code tag} is {@code null} or + /// empty. + TagChunk(const std::string &label, const std::string &tag); + + /// + /// Get the tag for this chunk. + /// + /// The tag for the chunk. + std::string getTag(); + + /// + /// Get the label, if any, assigned to this chunk. + /// + /// The label assigned to this chunk, or {@code null} if no label is + /// assigned to the chunk. + std::string getLabel(); + + /// + /// 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() override; + + private: + /// This is the backing field for . + const std::string _tag; + /// + /// This is the backing field for . + /// + const std::string _label; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp new file mode 100644 index 0000000..f8dcfb0 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.cpp @@ -0,0 +1,28 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "Exceptions.h" + +#include "tree/pattern/TextChunk.h" + +using namespace antlr4::tree::pattern; + +TextChunk::TextChunk(const std::string &text) : text(text) { + if (text == "") { + throw IllegalArgumentException("text cannot be nul"); + } + +} + +TextChunk::~TextChunk() { +} + +std::string TextChunk::getText() { + return text; +} + +std::string TextChunk::toString() { + return std::string("'") + text + std::string("'"); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h new file mode 100644 index 0000000..1cbc0dd --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TextChunk.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "Chunk.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// Represents a span of raw text (concrete syntax) between tags in a tree + /// pattern string. + /// + class ANTLR4CPP_PUBLIC TextChunk : public Chunk { + private: + /// + /// This is the backing field for . + /// + const std::string text; + + /// + /// Constructs a new instance of with the specified text. + /// + /// The text of this chunk. + /// if {@code text} is {@code null}. + public: + TextChunk(const std::string &text); + virtual ~TextChunk(); + + /// + /// Gets the raw text of this chunk. + /// + /// The text of the chunk. + std::string getText(); + + /// + /// {@inheritDoc} + ///

+ /// The implementation for returns the result of + /// in single quotes. + ///

+ virtual std::string toString() override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp new file mode 100644 index 0000000..7d6cc9a --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "tree/pattern/TokenTagToken.h" + +using namespace antlr4::tree::pattern; + +TokenTagToken::TokenTagToken(const std::string &/*tokenName*/, int type) + : CommonToken(type), tokenName(""), label("") { +} + +TokenTagToken::TokenTagToken(const std::string &tokenName, int type, const std::string &label) + : CommonToken(type), tokenName(tokenName), label(label) { +} + +std::string TokenTagToken::getTokenName() const { + return tokenName; +} + +std::string TokenTagToken::getLabel() const { + return label; +} + +std::string TokenTagToken::getText() const { + if (!label.empty()) { + return "<" + label + ":" + tokenName + ">"; + } + + return "<" + tokenName + ">"; +} + +std::string TokenTagToken::toString() const { + return tokenName + ":" + std::to_string(_type); +} diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h new file mode 100644 index 0000000..9013fb8 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/tree/pattern/TokenTagToken.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#pragma once + +#include "CommonToken.h" + +namespace antlr4 { +namespace tree { +namespace pattern { + + /// + /// A object representing a token of a particular type; e.g., + /// {@code }. These tokens are created for chunks where the + /// tag corresponds to a lexer rule or token type. + /// + class ANTLR4CPP_PUBLIC TokenTagToken : public CommonToken { + /// + /// This is the backing field for . + /// + private: + const std::string tokenName; + /// + /// This is the backing field for . + /// + const std::string label; + + /// + /// Constructs a new instance of for an unlabeled tag + /// with the specified token name and type. + /// + /// The token name. + /// The token type. + public: + TokenTagToken(const std::string &tokenName, int type); //this(tokenName, type, nullptr); + + /// + /// Constructs a new instance of with the specified + /// token name, type, and label. + /// + /// The token name. + /// The token type. + /// The label associated with the token tag, or {@code null} if + /// the token tag is unlabeled. + TokenTagToken(const std::string &tokenName, int type, const std::string &label); + + /// + /// Gets the token name. + /// The token name. + std::string getTokenName() const; + + /// + /// Gets the label associated with the rule tag. + /// + /// The name of the label associated with the rule tag, or + /// {@code null} if this is an unlabeled rule tag. + std::string getLabel() const; + + /// + /// {@inheritDoc} + ///

+ /// The implementation for returns the token tag + /// formatted with {@code <} and {@code >} delimiters. + ///

+ virtual std::string getText() const override; + + /// + /// {@inheritDoc} + ///

+ /// The implementation for returns a string of the form + /// {@code tokenName:type}. + ///

+ virtual std::string toString() const override; + }; + +} // namespace pattern +} // namespace tree +} // namespace antlr4 -- cgit v1.2.3