diff --git a/runtime/Cpp/demo/Mac/antlr4-cpp-demo/main.cpp b/runtime/Cpp/demo/Mac/antlr4-cpp-demo/main.cpp index 2af0951e7..d96976928 100644 --- a/runtime/Cpp/demo/Mac/antlr4-cpp-demo/main.cpp +++ b/runtime/Cpp/demo/Mac/antlr4-cpp-demo/main.cpp @@ -12,18 +12,20 @@ #include "TLexer.h" #include "TParser.h" +#include "Strings.h" + using namespace antlrcpptest; using namespace org::antlr::v4::runtime; int main(int argc, const char * argv[]) { - ANTLRInputStream input(L"divide and conquer"); + ANTLRInputStream input(L"divideĊ´ and conquer"); TLexer lexer(&input); CommonTokenStream tokens(&lexer); TParser parser(&tokens); std::shared_ptr tree = parser.main(); - std::wcout << tree->toStringTree(&parser) << std::endl; + std::cout << antlrcpp::ws2s(tree->toStringTree(&parser)) << std::endl; return 0; } diff --git a/runtime/Cpp/demo/Mac/antlrcpp.xcodeproj/project.pbxproj b/runtime/Cpp/demo/Mac/antlrcpp.xcodeproj/project.pbxproj index c00b7ca3c..fcd3dc51a 100644 --- a/runtime/Cpp/demo/Mac/antlrcpp.xcodeproj/project.pbxproj +++ b/runtime/Cpp/demo/Mac/antlrcpp.xcodeproj/project.pbxproj @@ -541,12 +541,12 @@ /* Begin PBXFileReference section */ 2747A7081CA691310030247B /* ConfigLookup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConfigLookup.cpp; sourceTree = ""; }; - 2747A7091CA691310030247B /* ConfigLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigLookup.h; sourceTree = ""; }; + 2747A7091CA691310030247B /* ConfigLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigLookup.h; sourceTree = ""; wrapsLines = 0; }; 2747A7121CA6C46C0030247B /* InputHandlingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputHandlingTests.mm; sourceTree = ""; wrapsLines = 0; }; 274FC6D81CA96B6C008D4374 /* MiscClassTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MiscClassTests.mm; sourceTree = ""; wrapsLines = 0; }; 276927231C9ED49100E4EBF8 /* antlrcpp-Prefix.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = "antlrcpp-Prefix.h"; path = "../../runtime/antlrcpp-Prefix.h"; sourceTree = ""; }; 278A66FA1C95838E002D667E /* ANTLRErrorListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ANTLRErrorListener.cpp; path = ../../runtime/ANTLRErrorListener.cpp; sourceTree = SOURCE_ROOT; }; - 27A23EA11CC2A8D60036D8A3 /* TLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TLexer.cpp; path = ../generated/TLexer.cpp; sourceTree = ""; }; + 27A23EA11CC2A8D60036D8A3 /* TLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TLexer.cpp; path = ../generated/TLexer.cpp; sourceTree = ""; wrapsLines = 0; }; 27A23EA21CC2A8D60036D8A3 /* TLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TLexer.h; path = ../generated/TLexer.h; sourceTree = ""; }; 27C6665D1C9584050021E494 /* ANTLRErrorListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ANTLRErrorListener.h; path = ../../runtime/ANTLRErrorListener.h; sourceTree = SOURCE_ROOT; wrapsLines = 0; }; 27C6665E1C9584050021E494 /* ANTLRErrorStrategy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ANTLRErrorStrategy.cpp; path = ../../runtime/ANTLRErrorStrategy.cpp; sourceTree = SOURCE_ROOT; }; diff --git a/runtime/Cpp/demo/TLexer.g4 b/runtime/Cpp/demo/TLexer.g4 index ed8558d84..e1a6e4f1f 100644 --- a/runtime/Cpp/demo/TLexer.g4 +++ b/runtime/Cpp/demo/TLexer.g4 @@ -38,7 +38,7 @@ Digit: [0..9]; ID: LETTER (LETTER | '0'..'9')*; fragment LETTER : [a-zA-Z\u0080-\uFFFD] ; -LessThan: '<' -> pushMode(Mode1); +LessThan: '<';// -> pushMode(Mode1); GreaterThan: '>';// -> popMode; Equal: '='; And: 'and'; diff --git a/runtime/Cpp/runtime/ANTLRInputStream.cpp b/runtime/Cpp/runtime/ANTLRInputStream.cpp index cee3776fb..1f3fa873e 100755 --- a/runtime/Cpp/runtime/ANTLRInputStream.cpp +++ b/runtime/Cpp/runtime/ANTLRInputStream.cpp @@ -68,7 +68,7 @@ void ANTLRInputStream::load(std::wistream &stream, std::streamsize readChunkSize readChunkSize = READ_BUFFER_SIZE; } - wchar_t *buffer = new wchar_t[readChunkSize]; + wchar_t *buffer = new wchar_t[readChunkSize]; /* mem check: freed in finally block */ auto onExit = finally([buffer] { delete[] buffer; }); diff --git a/runtime/Cpp/runtime/BailErrorStrategy.h b/runtime/Cpp/runtime/BailErrorStrategy.h index f1d15c9fe..5ee47aad9 100755 --- a/runtime/Cpp/runtime/BailErrorStrategy.h +++ b/runtime/Cpp/runtime/BailErrorStrategy.h @@ -38,11 +38,7 @@ namespace antlr { namespace v4 { namespace runtime { - /// - /// Bail out of parser at first syntax error. Do this to use it: - ///

- /// {@code myparser.setErrorHandler(new BailErrorStrategy());} - ///

+ /// Bail out of parser at first syntax error. Use myparser.setErrorHandler(..) to set a different strategy. class BailErrorStrategy : public DefaultErrorStrategy { /// /// Instead of recovering from exception {@code e}, re-throw it wrapped diff --git a/runtime/Cpp/runtime/DefaultErrorStrategy.cpp b/runtime/Cpp/runtime/DefaultErrorStrategy.cpp index 2ee0d410b..b93139fd3 100755 --- a/runtime/Cpp/runtime/DefaultErrorStrategy.cpp +++ b/runtime/Cpp/runtime/DefaultErrorStrategy.cpp @@ -61,7 +61,6 @@ bool DefaultErrorStrategy::inErrorRecoveryMode(Parser *recognizer) { void DefaultErrorStrategy::endErrorCondition(Parser *recognizer) { errorRecoveryMode = false; - delete lastErrorStates; lastErrorIndex = -1; } @@ -93,8 +92,8 @@ void DefaultErrorStrategy::reportError(Parser *recognizer, const RecognitionExce } void DefaultErrorStrategy::recover(Parser *recognizer, const RecognitionException &e) { - if (lastErrorIndex == (int)recognizer->getInputStream()->index() && lastErrorStates != nullptr && - lastErrorStates->contains(recognizer->getState())) { + if (lastErrorIndex == (int)recognizer->getInputStream()->index() && + lastErrorStates.contains(recognizer->getState())) { // uh oh, another error at same token index and previously-visited // state in ATN; must be a case where LT(1) is in the recovery @@ -103,10 +102,7 @@ void DefaultErrorStrategy::recover(Parser *recognizer, const RecognitionExceptio recognizer->consume(); } lastErrorIndex = (int)recognizer->getInputStream()->index(); - if (lastErrorStates == nullptr) { - lastErrorStates = new misc::IntervalSet(0); - } - lastErrorStates->add(recognizer->getState()); + lastErrorStates.add(recognizer->getState()); misc::IntervalSet followSet = getErrorRecoverySet(recognizer); consumeUntil(recognizer, followSet); } @@ -353,5 +349,4 @@ void DefaultErrorStrategy::consumeUntil(Parser *recognizer, const misc::Interval void DefaultErrorStrategy::InitializeInstanceFields() { errorRecoveryMode = false; lastErrorIndex = -1; - lastErrorStates = nullptr; } diff --git a/runtime/Cpp/runtime/DefaultErrorStrategy.h b/runtime/Cpp/runtime/DefaultErrorStrategy.h index 0494b405b..398ff984a 100755 --- a/runtime/Cpp/runtime/DefaultErrorStrategy.h +++ b/runtime/Cpp/runtime/DefaultErrorStrategy.h @@ -67,7 +67,7 @@ namespace runtime { /// int lastErrorIndex; - misc::IntervalSet *lastErrorStates; + misc::IntervalSet lastErrorStates; /// /// {@inheritDoc} @@ -377,7 +377,7 @@ namespace runtime { /// to use t.toString() (which, for CommonToken, dumps everything about /// the token). This is better than forcing you to override a method in /// your token objects because you don't have to go modify your lexer - /// so that it creates a new Java type. + /// so that it creates a new class. /// virtual std::wstring getTokenErrorDisplay(Token::Ref t); diff --git a/runtime/Cpp/runtime/DiagnosticErrorListener.cpp b/runtime/Cpp/runtime/DiagnosticErrorListener.cpp index 72878e8fa..380d49b02 100755 --- a/runtime/Cpp/runtime/DiagnosticErrorListener.cpp +++ b/runtime/Cpp/runtime/DiagnosticErrorListener.cpp @@ -103,7 +103,7 @@ antlrcpp::BitSet DiagnosticErrorListener::getConflictingAlts(const antlrcpp::Bit antlrcpp::BitSet result; for (size_t i = 0; i < configs->size(); i++) { - atn::ATNConfig *config = configs->get(i); + atn::ATNConfig::Ref config = configs->get(i); result.set((size_t)config->alt); } diff --git a/runtime/Cpp/runtime/FailedPredicateException.cpp b/runtime/Cpp/runtime/FailedPredicateException.cpp index d2f449bc0..f2aefa5fe 100755 --- a/runtime/Cpp/runtime/FailedPredicateException.cpp +++ b/runtime/Cpp/runtime/FailedPredicateException.cpp @@ -34,10 +34,12 @@ #include "PredicateTransition.h" #include "ATN.h" #include "ATNState.h" +#include "CPPUtils.h" #include "FailedPredicateException.h" using namespace org::antlr::v4::runtime; +using namespace antlrcpp; FailedPredicateException::FailedPredicateException(Parser *recognizer) : FailedPredicateException(recognizer, "", "") { } @@ -51,7 +53,7 @@ FailedPredicateException::FailedPredicateException(Parser *recognizer, const std atn::ATNState *s = recognizer->getInterpreter()->atn.states[(size_t)recognizer->getState()]; atn::Transition *transition = s->transition(0); - if (dynamic_cast(transition) != nullptr) { + if (is(transition)) { _ruleIndex = ((atn::PredicateTransition *)transition)->ruleIndex; _predicateIndex = ((atn::PredicateTransition *)transition)->predIndex; } diff --git a/runtime/Cpp/runtime/LexerInterpreter.cpp b/runtime/Cpp/runtime/LexerInterpreter.cpp index e2d75e648..57de7d881 100755 --- a/runtime/Cpp/runtime/LexerInterpreter.cpp +++ b/runtime/Cpp/runtime/LexerInterpreter.cpp @@ -43,16 +43,17 @@ LexerInterpreter::LexerInterpreter(const std::wstring &grammarFileName, const st const std::vector &ruleNames, const std::vector &modeNames, const atn::ATN &atn, CharStream *input) : Lexer(input), grammarFileName(grammarFileName), _tokenNames(tokenNames), _ruleNames(ruleNames), _modeNames(modeNames), - _atn(atn), _sharedContextCache(new atn::PredictionContextCache()) { + _atn(atn) { if (_atn.grammarType != atn::ATNType::LEXER) { throw IllegalArgumentException("The ATN must be a lexer ATN."); } + _sharedContextCache = std::make_shared(); for (size_t i = 0; i < (size_t)atn.getNumberOfDecisions(); ++i) { _decisionToDFA.push_back(dfa::DFA(_atn.getDecisionState((int)i), (int)i)); } - _interpreter = new atn::LexerATNSimulator(_atn, _decisionToDFA, _sharedContextCache); + _interpreter = new atn::LexerATNSimulator(_atn, _decisionToDFA, _sharedContextCache); /* mem-check: deleted in d-tor */ } LexerInterpreter::~LexerInterpreter() diff --git a/runtime/Cpp/runtime/Parser.cpp b/runtime/Cpp/runtime/Parser.cpp index 0d9bfabb4..dadd1b632 100755 --- a/runtime/Cpp/runtime/Parser.cpp +++ b/runtime/Cpp/runtime/Parser.cpp @@ -594,7 +594,7 @@ void Parser::setTrace(bool trace) { } void Parser::InitializeInstanceFields() { - _errHandler.reset(new DefaultErrorStrategy()); + _errHandler = std::make_shared(); _precedenceStack.clear(); _precedenceStack.push_back(0); _buildParseTrees = true; diff --git a/runtime/Cpp/runtime/ParserInterpreter.cpp b/runtime/Cpp/runtime/ParserInterpreter.cpp index 670c5b588..f058dcd31 100755 --- a/runtime/Cpp/runtime/ParserInterpreter.cpp +++ b/runtime/Cpp/runtime/ParserInterpreter.cpp @@ -45,10 +45,12 @@ #include "ATN.h" #include "RuleStopState.h" #include "Token.h" +#include "CPPUtils.h" #include "ParserInterpreter.h" using namespace org::antlr::v4::runtime; +using namespace antlrcpp; ParserInterpreter::ParserInterpreter(const std::wstring &grammarFileName, const std::vector& tokenNames, const std::vector& ruleNames, const atn::ATN &atn, TokenStream *input) @@ -60,7 +62,7 @@ ParserInterpreter::ParserInterpreter(const std::wstring &grammarFileName, const // identify the ATN states where pushNewRecursionContext must be called for (auto state : _atn.states) { - if (!(dynamic_cast(state) != nullptr)) { + if (!is(state)) { continue; } @@ -70,17 +72,17 @@ ParserInterpreter::ParserInterpreter(const std::wstring &grammarFileName, const } atn::ATNState *maybeLoopEndState = state->transition(state->getNumberOfTransitions() - 1)->target; - if (!(dynamic_cast(maybeLoopEndState) != nullptr)) { + if (!is(maybeLoopEndState)) { continue; } - if (maybeLoopEndState->epsilonOnlyTransitions && dynamic_cast(maybeLoopEndState->transition(0)->target) != nullptr) { + if (maybeLoopEndState->epsilonOnlyTransitions && is(maybeLoopEndState->transition(0)->target)) { _pushRecursionContextStates.set((size_t)state->stateNumber); } } // get atn simulator that knows how to do predictions - _interpreter = new atn::ParserATNSimulator(this, atn, _decisionToDFA, _sharedContextCache); + _interpreter = new atn::ParserATNSimulator(this, atn, _decisionToDFA, _sharedContextCache); /* mem-check: deleted in d-tor */ } ParserInterpreter::~ParserInterpreter() { @@ -155,7 +157,7 @@ void ParserInterpreter::visitState(atn::ATNState *p) { atn::Transition *transition = p->transition((size_t)edge - 1); switch (transition->getSerializationType()) { case atn::Transition::EPSILON: - if (_pushRecursionContextStates[(size_t)p->stateNumber] == 1 && !(dynamic_cast(transition->target) != nullptr)) { + if (_pushRecursionContextStates[(size_t)p->stateNumber] == 1 && is(transition->target)) { std::shared_ptr ruleContext = std::make_shared(_parentContextStack.top().first, _parentContextStack.top().second, _ctx->getRuleIndex()); pushNewRecursionContext(ruleContext, _atn.ruleToStartState[(size_t)p->ruleIndex]->stateNumber, diff --git a/runtime/Cpp/runtime/RuleContext.cpp b/runtime/Cpp/runtime/RuleContext.cpp index c007fd830..ddfd90322 100755 --- a/runtime/Cpp/runtime/RuleContext.cpp +++ b/runtime/Cpp/runtime/RuleContext.cpp @@ -191,6 +191,8 @@ std::wstring RuleContext::toString(Recognizer *recog) { } std::wstring RuleContext::toString(Recognizer *recog, RuleContext::Ref stop) { + if (recog == nullptr) + return toString({}, stop); return toString(recog->getRuleNames(), stop); } diff --git a/runtime/Cpp/runtime/TokenStreamRewriter.cpp b/runtime/Cpp/runtime/TokenStreamRewriter.cpp index ea221614b..46330a553 100755 --- a/runtime/Cpp/runtime/TokenStreamRewriter.cpp +++ b/runtime/Cpp/runtime/TokenStreamRewriter.cpp @@ -34,10 +34,12 @@ #include "Token.h" #include "TokenStream.h" #include "Strings.h" +#include "CPPUtils.h" #include "TokenStreamRewriter.h" using namespace org::antlr::v4::runtime; +using namespace antlrcpp; using org::antlr::v4::runtime::misc::Interval; @@ -104,10 +106,20 @@ void TokenStreamRewriter::ReplaceOp::InitializeInstanceFields() { lastIndex = 0; } +//------------------ TokenStreamRewriter ------------------------------------------------------------------------------- + const std::wstring TokenStreamRewriter::DEFAULT_PROGRAM_NAME = L"default"; -TokenStreamRewriter::TokenStreamRewriter(TokenStream *tokens) : tokens(tokens), programs(new std::map>()), lastRewriteTokenIndexes(new std::map()) { - programs->insert({ DEFAULT_PROGRAM_NAME, std::vector(PROGRAM_INIT_SIZE) }); +TokenStreamRewriter::TokenStreamRewriter(TokenStream *tokens) : tokens(tokens) { + _programs.insert({ DEFAULT_PROGRAM_NAME, std::vector(PROGRAM_INIT_SIZE) }); +} + +TokenStreamRewriter::~TokenStreamRewriter() { + for (auto program : _programs) { + for (auto operation : program.second) { + delete operation; + } + } } TokenStream *TokenStreamRewriter::getTokenStream() { @@ -119,9 +131,9 @@ void TokenStreamRewriter::rollback(int instructionIndex) { } void TokenStreamRewriter::rollback(const std::wstring &programName, int instructionIndex) { - std::vector is = (*programs)[programName]; + std::vector is = _programs[programName]; if (is.size() > 0) { - programs->insert({ programName, std::vector(is.begin() + MIN_TOKEN_INDEX, is.begin() + instructionIndex) }); + _programs.insert({ programName, std::vector(is.begin() + MIN_TOKEN_INDEX, is.begin() + instructionIndex) }); } } @@ -163,8 +175,8 @@ void TokenStreamRewriter::insertBefore(const std::wstring &programName, Token *t } void TokenStreamRewriter::insertBefore(const std::wstring &programName, size_t index, const std::wstring& text) { - RewriteOperation *op = new InsertBeforeOp(this, index, text); - std::vector rewrites = getProgram(programName); + RewriteOperation *op = new InsertBeforeOp(this, index, text); /* mem-check: deleted in d-tor */ + std::vector &rewrites = getProgram(programName); op->instructionIndex = (int)rewrites.size(); rewrites.push_back(op); } @@ -190,8 +202,8 @@ void TokenStreamRewriter::replace(const std::wstring &programName, size_t from, throw IllegalArgumentException("replace: range invalid: " + std::to_string(from) + ".." + std::to_string(to) + "(size = " + std::to_string(tokens->size()) + ")"); } - RewriteOperation *op = new ReplaceOp(this, from, to, text); - std::vector rewrites = getProgram(programName); + RewriteOperation *op = new ReplaceOp(this, from, to, text); /* mem-check: deleted in d-tor */ + std::vector &rewrites = getProgram(programName); op->instructionIndex = (int)rewrites.size(); rewrites.push_back(op); } @@ -229,18 +241,18 @@ int TokenStreamRewriter::getLastRewriteTokenIndex() { } int TokenStreamRewriter::getLastRewriteTokenIndex(const std::wstring &programName) { - if (lastRewriteTokenIndexes->find(programName) == lastRewriteTokenIndexes->end()) { + if (_lastRewriteTokenIndexes.find(programName) == _lastRewriteTokenIndexes.end()) { return -1; } - return lastRewriteTokenIndexes->at(programName); + return _lastRewriteTokenIndexes[programName]; } void TokenStreamRewriter::setLastRewriteTokenIndex(const std::wstring &programName, int i) { - lastRewriteTokenIndexes->insert({ programName, i }); + _lastRewriteTokenIndexes.insert({ programName, i }); } -std::vector TokenStreamRewriter::getProgram(const std::wstring &name) { - std::vector is = programs->at(name); +std::vector& TokenStreamRewriter::getProgram(const std::wstring &name) { + std::vector &is = _programs[name]; if (is.empty()) { is = initializeProgram(name); } @@ -249,7 +261,7 @@ std::vector TokenStreamRewriter::getProg std::vector TokenStreamRewriter::initializeProgram(const std::wstring &name) { std::vector is(PROGRAM_INIT_SIZE); - programs->insert({ name, is }); + _programs.insert({ name, is }); return is; } @@ -262,7 +274,7 @@ std::wstring TokenStreamRewriter::getText(const Interval &interval) { } std::wstring TokenStreamRewriter::getText(const std::wstring &programName, const Interval &interval) { - std::vector rewrites = programs->at(programName); + std::vector rewrites = _programs.at(programName); int start = interval.a; int stop = interval.b; @@ -324,7 +336,7 @@ std::unordered_map TokenStreamRe if (op == nullptr) { continue; } - if (dynamic_cast(op) == nullptr) { + if (!is(op)) { continue; } ReplaceOp *rop = static_cast(op); @@ -377,7 +389,7 @@ std::unordered_map TokenStreamRe if (op == nullptr) { continue; } - if (!(dynamic_cast(op) != nullptr)) { + if (!is(op)) { continue; } InsertBeforeOp *iop = static_cast(rewrites[i]); diff --git a/runtime/Cpp/runtime/TokenStreamRewriter.h b/runtime/Cpp/runtime/TokenStreamRewriter.h index 6414d7d0b..dde81d5f7 100755 --- a/runtime/Cpp/runtime/TokenStreamRewriter.h +++ b/runtime/Cpp/runtime/TokenStreamRewriter.h @@ -99,94 +99,13 @@ namespace runtime { /// the first example shows. /// class TokenStreamRewriter { - public: - class RewriteOperation { - private: - TokenStreamRewriter *const outerInstance; - - public: - /// - /// What index into rewrites List are we? - virtual ~RewriteOperation() {}; - /// - /// Token buffer index. - size_t index; - std::wstring text; - - RewriteOperation(TokenStreamRewriter *outerInstance, size_t index); - - RewriteOperation(TokenStreamRewriter *outerInstance, size_t index, const std::wstring& text); - /// - /// Execute the rewrite operation by possibly adding to the buffer. - /// Return the index of the next token to operate on. - /// - int instructionIndex; - - virtual size_t execute(std::wstring *buf); - - virtual std::wstring toString(); - - private: - void InitializeInstanceFields(); - }; - - public: - class InsertBeforeOp : public RewriteOperation { - private: - TokenStreamRewriter *const outerInstance; - - public: - InsertBeforeOp(TokenStreamRewriter *outerInstance, size_t index, const std::wstring& text); - - virtual size_t execute(std::wstring *buf) override; - }; - - public: - class ReplaceOp : public RewriteOperation { - private: - TokenStreamRewriter *const outerInstance; - - public: - size_t lastIndex; - - ReplaceOp(TokenStreamRewriter *outerInstance, size_t from, size_t to, const std::wstring& text); - virtual size_t execute(std::wstring *buf) override; - virtual std::wstring toString() override; - - private: - void InitializeInstanceFields(); - }; - public: static const std::wstring DEFAULT_PROGRAM_NAME; static const int PROGRAM_INIT_SIZE = 100; static const int MIN_TOKEN_INDEX = 0; - // Define the rewrite operation hierarchy - - /// - /// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp - /// instructions. - /// - /// - /// Our source stream - protected: - TokenStream *const tokens; - - /// - /// You may have multiple, named streams of rewrite operations. - /// I'm calling these things "programs." - /// Maps String (name) -> rewrite (List) - /// - std::map> * programs; - - /// - /// Map String (program name) -> Integer index - std::map * lastRewriteTokenIndexes; - - public: TokenStreamRewriter(TokenStream *tokens); - virtual ~TokenStreamRewriter() {}; + virtual ~TokenStreamRewriter(); TokenStream *getTokenStream(); @@ -229,22 +148,9 @@ namespace runtime { virtual void Delete(const std::wstring &programName, Token *from, Token *to); virtual int getLastRewriteTokenIndex(); - - protected: - virtual int getLastRewriteTokenIndex(const std::wstring &programName); - - virtual void setLastRewriteTokenIndex(const std::wstring &programName, int i); - - virtual std::vector getProgram(const std::wstring &name); - - private: - std::vector initializeProgram(const std::wstring &name); - - /// + /// Return the text from the original tokens altered per the /// instructions given to this rewriter. - /// - public: virtual std::wstring getText(); /// @@ -261,6 +167,77 @@ namespace runtime { virtual std::wstring getText(const std::wstring &programName, const misc::Interval &interval); + protected: + class RewriteOperation { + private: + TokenStreamRewriter *const outerInstance; + + public: + /// + /// What index into rewrites List are we? + virtual ~RewriteOperation() {}; + /// + /// Token buffer index. + size_t index; + std::wstring text; + + RewriteOperation(TokenStreamRewriter *outerInstance, size_t index); + + RewriteOperation(TokenStreamRewriter *outerInstance, size_t index, const std::wstring& text); + /// + /// Execute the rewrite operation by possibly adding to the buffer. + /// Return the index of the next token to operate on. + /// + int instructionIndex; + + virtual size_t execute(std::wstring *buf); + + virtual std::wstring toString(); + + private: + void InitializeInstanceFields(); + }; + + class InsertBeforeOp : public RewriteOperation { + private: + TokenStreamRewriter *const outerInstance; + + public: + InsertBeforeOp(TokenStreamRewriter *outerInstance, size_t index, const std::wstring& text); + + virtual size_t execute(std::wstring *buf) override; + }; + + class ReplaceOp : public RewriteOperation { + private: + TokenStreamRewriter *const outerInstance; + + public: + size_t lastIndex; + + ReplaceOp(TokenStreamRewriter *outerInstance, size_t from, size_t to, const std::wstring& text); + virtual size_t execute(std::wstring *buf) override; + virtual std::wstring toString() override; + + private: + void InitializeInstanceFields(); + }; + + /// Our source stream + TokenStream *const tokens; + + /// You may have multiple, named streams of rewrite operations. + /// I'm calling these things "programs." + /// Maps String (name) -> rewrite (List) + std::map> _programs; + + /// + /// Map String (program name) -> Integer index + std::map _lastRewriteTokenIndexes; + virtual int getLastRewriteTokenIndex(const std::wstring &programName); + virtual void setLastRewriteTokenIndex(const std::wstring &programName, int i); + virtual std::vector& getProgram(const std::wstring &name); + /// /// We need to combine operations and report invalid operations (like /// overlapping replaces that are not completed nested). Inserts to @@ -311,7 +288,6 @@ namespace runtime { /// /// Return a map from token index to operation. /// - protected: virtual std::unordered_map reduceToSingleOperationPerIndex(std::vector rewrites); virtual std::wstring catOpText(std::wstring *a, std::wstring *b); @@ -333,6 +309,9 @@ namespace runtime { return ops; } + private: + std::vector initializeProgram(const std::wstring &name); + }; } // namespace runtime diff --git a/runtime/Cpp/runtime/atn/ATN.cpp b/runtime/Cpp/runtime/atn/ATN.cpp index 5b5d5901b..c86b3ca58 100755 --- a/runtime/Cpp/runtime/atn/ATN.cpp +++ b/runtime/Cpp/runtime/atn/ATN.cpp @@ -49,9 +49,65 @@ using namespace antlrcpp; ATN::ATN() : ATN(ATNType::LEXER, 0) { } +/** + * Required to be defined (even though not used) as we have an explicit move assignment operator. + */ +ATN::ATN(const ATN& other) { + states = other.states; + decisionToState = other.decisionToState; + ruleToStartState = other.ruleToStartState; + ruleToStopState = other.ruleToStopState; + grammarType = other.grammarType; + maxTokenType = other.maxTokenType; + ruleToTokenType = other.ruleToTokenType; + ruleToActionIndex = other.ruleToActionIndex; + modeToStartState = other.modeToStartState; +} + ATN::ATN(ATNType grammarType, size_t maxTokenType) : grammarType(grammarType), maxTokenType(maxTokenType) { } +ATN::~ATN() { + for (ATNState *state : states) { + delete state; + } +} + +/** + * Required to be defined (even though not used) as we have an explicit move assignment operator. + */ +ATN& ATN::operator = (ATN& other) noexcept { + states = other.states; + decisionToState = other.decisionToState; + ruleToStartState = other.ruleToStartState; + ruleToStopState = other.ruleToStopState; + grammarType = other.grammarType; + maxTokenType = other.maxTokenType; + ruleToTokenType = other.ruleToTokenType; + ruleToActionIndex = other.ruleToActionIndex; + modeToStartState = other.modeToStartState; + + return *this; +} + +/** + * Explicit move assignment operator to make this the preferred assignment. With implicit copy/move assignment + * operators it seems the copy operator is preferred causing trouble when releasing the allocated ATNState instances. + */ +ATN& ATN::operator = (ATN&& other) noexcept { + states = std::move(other.states); + decisionToState = std::move(other.decisionToState); + ruleToStartState = std::move(other.ruleToStartState); + ruleToStopState = std::move(other.ruleToStopState); + grammarType = std::move(other.grammarType); + maxTokenType = std::move(other.maxTokenType); + ruleToTokenType = std::move(other.ruleToTokenType); + ruleToActionIndex = std::move(other.ruleToActionIndex); + modeToStartState = std::move(other.modeToStartState); + + return *this; +} + misc::IntervalSet ATN::nextTokens(ATNState *s, RuleContext::Ref ctx) const { LL1Analyzer analyzer(*this); return analyzer.LOOK(s, ctx); diff --git a/runtime/Cpp/runtime/atn/ATN.h b/runtime/Cpp/runtime/atn/ATN.h index efd7af245..f8f39fd9f 100755 --- a/runtime/Cpp/runtime/atn/ATN.h +++ b/runtime/Cpp/runtime/atn/ATN.h @@ -45,7 +45,9 @@ namespace atn { /// Used for runtime deserialization of ATNs from strings. ATN(); + ATN(const ATN &other); ATN(ATNType grammarType, size_t maxTokenType); + ~ATN(); std::vector states; @@ -85,6 +87,9 @@ namespace atn { std::vector modeToStartState; + ATN& operator = (ATN &other) noexcept; + ATN& operator = (ATN &&other) noexcept; + /// /// Compute the set of valid tokens that can occur starting in state {@code s}. /// If {@code ctx} is null, the set of tokens will not include what can follow diff --git a/runtime/Cpp/runtime/atn/ATNConfig.cpp b/runtime/Cpp/runtime/atn/ATNConfig.cpp index 721106fc7..c2ab1752f 100755 --- a/runtime/Cpp/runtime/atn/ATNConfig.cpp +++ b/runtime/Cpp/runtime/atn/ATNConfig.cpp @@ -45,25 +45,25 @@ ATNConfig::ATNConfig(ATNState *state, int alt, PredictionContext::Ref context, S reachesIntoOuterContext = 0; } -ATNConfig::ATNConfig(ATNConfig *c) : ATNConfig(c, c->state, c->context, c->semanticContext) { +ATNConfig::ATNConfig(ATNConfig::Ref c) : ATNConfig(c, c->state, c->context, c->semanticContext) { } -ATNConfig::ATNConfig(ATNConfig *c, ATNState *state) : ATNConfig(c, state, c->context, c->semanticContext) { +ATNConfig::ATNConfig(ATNConfig::Ref c, ATNState *state) : ATNConfig(c, state, c->context, c->semanticContext) { } -ATNConfig::ATNConfig(ATNConfig *c, ATNState *state, SemanticContext::Ref semanticContext) +ATNConfig::ATNConfig(ATNConfig::Ref c, ATNState *state, SemanticContext::Ref semanticContext) : ATNConfig(c, state, c->context, semanticContext) { } -ATNConfig::ATNConfig(ATNConfig *c, SemanticContext::Ref semanticContext) +ATNConfig::ATNConfig(ATNConfig::Ref c, SemanticContext::Ref semanticContext) : ATNConfig(c, c->state, c->context, semanticContext) { } -ATNConfig::ATNConfig(ATNConfig *c, ATNState *state, PredictionContext::Ref context) +ATNConfig::ATNConfig(ATNConfig::Ref c, ATNState *state, PredictionContext::Ref context) : ATNConfig(c, state, context, c->semanticContext) { } -ATNConfig::ATNConfig(ATNConfig *c, ATNState *state, PredictionContext::Ref context, SemanticContext::Ref semanticContext) +ATNConfig::ATNConfig(ATNConfig::Ref c, ATNState *state, PredictionContext::Ref context, SemanticContext::Ref semanticContext) : state(state), alt(c->alt), context(context), semanticContext(semanticContext), reachesIntoOuterContext(c->reachesIntoOuterContext) { } diff --git a/runtime/Cpp/runtime/atn/ATNConfig.h b/runtime/Cpp/runtime/atn/ATNConfig.h index ef5b1d126..7ec31a84a 100755 --- a/runtime/Cpp/runtime/atn/ATNConfig.h +++ b/runtime/Cpp/runtime/atn/ATNConfig.h @@ -49,9 +49,10 @@ namespace atn { /// an ATN state. /// class ATNConfig { - /// - /// The ATN state associated with this configuration public: + typedef std::shared_ptr Ref; + + /// The ATN state associated with this configuration. ATNState * state; /// @@ -82,12 +83,12 @@ namespace atn { ATNConfig(ATNState *state, int alt, PredictionContext::Ref context); ATNConfig(ATNState *state, int alt, PredictionContext::Ref context, SemanticContext::Ref semanticContext); - ATNConfig(ATNConfig *c); // dup - ATNConfig(ATNConfig *c, ATNState *state); - ATNConfig(ATNConfig *c, ATNState *state, SemanticContext::Ref semanticContext); - ATNConfig(ATNConfig *c, SemanticContext::Ref semanticContext); - ATNConfig(ATNConfig *c, ATNState *state, PredictionContext::Ref context); - ATNConfig(ATNConfig *c, ATNState *state, PredictionContext::Ref context, SemanticContext::Ref semanticContext); + ATNConfig(ATNConfig::Ref c); // dup + ATNConfig(ATNConfig::Ref c, ATNState *state); + ATNConfig(ATNConfig::Ref c, ATNState *state, SemanticContext::Ref semanticContext); + ATNConfig(ATNConfig::Ref c, SemanticContext::Ref semanticContext); + ATNConfig(ATNConfig::Ref c, ATNState *state, PredictionContext::Ref context); + ATNConfig(ATNConfig::Ref c, ATNState *state, PredictionContext::Ref context, SemanticContext::Ref semanticContext); virtual size_t hashCode() const; diff --git a/runtime/Cpp/runtime/atn/ATNConfigSet.cpp b/runtime/Cpp/runtime/atn/ATNConfigSet.cpp index bb9fcbd52..e62fae11c 100755 --- a/runtime/Cpp/runtime/atn/ATNConfigSet.cpp +++ b/runtime/Cpp/runtime/atn/ATNConfigSet.cpp @@ -38,21 +38,17 @@ using namespace org::antlr::v4::runtime::atn; -size_t SimpleATNConfigHasher::operator()(const ATNConfig &k) const { +size_t SimpleATNConfigHasher::operator()(const ATNConfig::Ref &k) const { size_t hashCode = 7; - hashCode = 31 * hashCode + (size_t)k.state->stateNumber; - hashCode = 31 * hashCode + (size_t)k.alt; - hashCode = 31 * hashCode + k.semanticContext->hashCode(); + hashCode = 31 * hashCode + (size_t)k->state->stateNumber; + hashCode = 31 * hashCode + (size_t)k->alt; + hashCode = 31 * hashCode + k->semanticContext->hashCode(); return hashCode; } -bool SimpleATNConfigComparer::operator () (const ATNConfig &lhs, const ATNConfig &rhs) const { - if (&lhs == &rhs) { // Shortcut: same address = same object. - return true; - } - - return lhs.state->stateNumber == rhs.state->stateNumber && lhs.alt == rhs.alt && - lhs.semanticContext == rhs.semanticContext; +bool SimpleATNConfigComparer::operator () (const ATNConfig::Ref &lhs, const ATNConfig::Ref &rhs) const { + return lhs->state->stateNumber == rhs->state->stateNumber && lhs->alt == rhs->alt && + lhs->semanticContext == rhs->semanticContext; } //------------------ ATNConfigSet -------------------------------------------------------------------------------------- @@ -72,11 +68,11 @@ ATNConfigSet::ATNConfigSet(std::shared_ptr old) : ATNConfigSet(old ATNConfigSet::~ATNConfigSet() { } -bool ATNConfigSet::add(ATNConfig *config) { +bool ATNConfigSet::add(ATNConfig::Ref config) { return add(config, nullptr); } -bool ATNConfigSet::add(ATNConfig *config, PredictionContextMergeCache *mergeCache) { +bool ATNConfigSet::add(ATNConfig::Ref config, PredictionContextMergeCache *mergeCache) { if (_readonly) { throw IllegalStateException("This set is readonly"); } @@ -87,7 +83,7 @@ bool ATNConfigSet::add(ATNConfig *config, PredictionContextMergeCache *mergeCach dipsIntoOuterContext = true; } - ATNConfig *existing = configLookup->getOrAdd(config); + ATNConfig::Ref existing = configLookup->getOrAdd(config); if (existing == config) { // we added this new one _cachedHashCode = 0; configs.push_back(config); // track order here @@ -112,14 +108,14 @@ bool ATNConfigSet::addAll(std::shared_ptr other) { return false; } -std::vector ATNConfigSet::elements() { +std::vector ATNConfigSet::elements() { return configs; } -std::vector* ATNConfigSet::getStates() { - std::vector *states = new std::vector(); +std::vector ATNConfigSet::getStates() { + std::vector states; for (auto c : configs) { - states->push_back(c->state); + states.push_back(c->state); } return states; } @@ -134,7 +130,7 @@ std::vector ATNConfigSet::getPredicates() { return preds; } -ATNConfig* ATNConfigSet::get(size_t i) const { +ATNConfig::Ref ATNConfigSet::get(size_t i) const { return configs[i]; } @@ -182,13 +178,13 @@ bool ATNConfigSet::operator == (const ATNConfigSet &other) { size_t ATNConfigSet::hashCode() { if (isReadonly()) { if (_cachedHashCode == 0) { - _cachedHashCode = std::hash>()(configs); + _cachedHashCode = std::hash>()(configs); } return _cachedHashCode; } - return std::hash>()(configs); + return std::hash>()(configs); } size_t ATNConfigSet::size() { @@ -199,7 +195,7 @@ bool ATNConfigSet::isEmpty() { return configs.empty(); } -bool ATNConfigSet::contains(ATNConfig *o) { +bool ATNConfigSet::contains(ATNConfig::Ref o) { if (configLookup == nullptr) { throw UnsupportedOperationException("This method is not implemented for readonly sets."); } diff --git a/runtime/Cpp/runtime/atn/ATNConfigSet.h b/runtime/Cpp/runtime/atn/ATNConfigSet.h index 675034f5a..f26de6116 100755 --- a/runtime/Cpp/runtime/atn/ATNConfigSet.h +++ b/runtime/Cpp/runtime/atn/ATNConfigSet.h @@ -44,11 +44,11 @@ namespace atn { // Simpler hasher and comparer variants than those in ATNConfig (less fields, no murmur hash). struct SimpleATNConfigHasher { - size_t operator()(const ATNConfig &k) const; + size_t operator()(const ATNConfig::Ref &k) const; }; struct SimpleATNConfigComparer { - bool operator()(const ATNConfig &lhs, const ATNConfig &rhs) const; + bool operator()(const ATNConfig::Ref &lhs, const ATNConfig::Ref &rhs) const; }; /// Specialized set that can track info about the set, with support for combining similar configurations using a @@ -61,7 +61,7 @@ namespace atn { /// /// Track the elements as they are added to the set; supports get(i) - std::vector configs; + std::vector configs; // TO_DO: these fields make me pretty uncomfortable but nice to pack up info together, saves recomputation // TO_DO: can we track conflicts as they are added to save scanning configs later? @@ -86,7 +86,7 @@ namespace atn { virtual ~ATNConfigSet(); - virtual bool add(ATNConfig *config); + virtual bool add(ATNConfig::Ref config); /// /// Adding a new config means merging contexts with existing configs for @@ -98,17 +98,17 @@ namespace atn { /// This method updates and /// when necessary. /// - virtual bool add(ATNConfig *config, PredictionContextMergeCache *mergeCache); + virtual bool add(ATNConfig::Ref config, PredictionContextMergeCache *mergeCache); /// /// Return a List holding list of configs - virtual std::vector elements(); + virtual std::vector elements(); - virtual std::vector *getStates(); + virtual std::vector getStates(); virtual std::vector getPredicates(); - virtual ATNConfig *get(size_t i) const; + virtual ATNConfig::Ref get(size_t i) const; virtual void optimizeConfigs(ATNSimulator *interpreter); @@ -118,7 +118,7 @@ namespace atn { virtual size_t hashCode(); virtual size_t size(); virtual bool isEmpty(); - virtual bool contains(ATNConfig *o); + virtual bool contains(ATNConfig::Ref o); virtual void clear(); virtual bool isReadonly(); virtual void setReadonly(bool readonly); @@ -146,9 +146,9 @@ namespace atn { } // namespace org namespace std { - template <> struct hash> + template <> struct hash> { - size_t operator() (const std::vector &vector) const + size_t operator() (const std::vector &vector) const { std::size_t seed = 0; for (auto &config : vector) { diff --git a/runtime/Cpp/runtime/atn/ATNDeserializer.cpp b/runtime/Cpp/runtime/atn/ATNDeserializer.cpp index f11a8c158..8fa2a2249 100755 --- a/runtime/Cpp/runtime/atn/ATNDeserializer.cpp +++ b/runtime/Cpp/runtime/atn/ATNDeserializer.cpp @@ -294,7 +294,8 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) { } RuleTransition *ruleTransition = static_cast(t); - atn.ruleToStopState[(size_t)ruleTransition->target->ruleIndex]->addTransition(new EpsilonTransition(ruleTransition->followState)); + atn.ruleToStopState[(size_t)ruleTransition->target->ruleIndex]-> + addTransition(new EpsilonTransition(ruleTransition->followState)); /* mem check: freed in ANTState d-tor */ } } @@ -310,7 +311,6 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) { // block end states can only be associated to a single block start state if (startState->endState->startState != nullptr) { throw IllegalStateException(); - } startState->endState->startState = static_cast(state); @@ -360,11 +360,11 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) { } for (std::vector::size_type i = 0; i < atn.ruleToStartState.size(); i++) { - BasicBlockStartState *bypassStart = new BasicBlockStartState(); + BasicBlockStartState *bypassStart = new BasicBlockStartState(); /* mem check: freed in ATN d-tor */ bypassStart->ruleIndex = (int)i; atn.addState(bypassStart); - BlockEndState *bypassStop = new BlockEndState(); + BlockEndState *bypassStop = new BlockEndState(); /* mem check: freed in ATN d-tor */ bypassStop->ruleIndex = (int)i; atn.addState(bypassStop); @@ -383,16 +383,16 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) { continue; } - if (!(dynamic_cast(state) != nullptr)) { + if (!is(state)) { continue; } ATNState *maybeLoopEndState = state->transition(state->getNumberOfTransitions() - 1)->target; - if (!(dynamic_cast(maybeLoopEndState) != nullptr)) { + if (!is(maybeLoopEndState)) { continue; } - if (maybeLoopEndState->epsilonOnlyTransitions && dynamic_cast(maybeLoopEndState->transition(0)->target) != nullptr) { + if (maybeLoopEndState->epsilonOnlyTransitions && is(maybeLoopEndState->transition(0)->target)) { endState = state; break; } @@ -428,13 +428,13 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) { } // link the new states - atn.ruleToStartState[i]->addTransition(new EpsilonTransition(bypassStart)); - bypassStop->addTransition(new EpsilonTransition(endState)); + atn.ruleToStartState[i]->addTransition(new EpsilonTransition(bypassStart)); /* mem check: freed in ATNState d-tor */ + bypassStop->addTransition(new EpsilonTransition(endState)); /* mem check: freed in ATNState d-tor */ - ATNState *matchState = new BasicState(); + ATNState *matchState = new BasicState(); /* mem check: freed in ATN d-tor */ atn.addState(matchState); - matchState->addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i])); - bypassStart->addTransition(new EpsilonTransition(matchState)); + matchState->addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i])); /* mem check: freed in ATNState d-tor */ + bypassStart->addTransition(new EpsilonTransition(matchState)); /* mem check: freed in ATNState d-tor */ } if (deserializationOptions.isVerifyATN()) { @@ -520,6 +520,7 @@ Guid ATNDeserializer::toUUID(const unsigned short *data, int offset) { return Guid((uint16_t *)data + offset, true); } +/* mem check: all created instances are freed in the d-tor of the ATNState they are added to. */ Transition *ATNDeserializer::edgeFactory(const ATN &atn, int type, int src, int trg, int arg1, int arg2, int arg3, const std::vector &sets) { @@ -558,6 +559,7 @@ Transition *ATNDeserializer::edgeFactory(const ATN &atn, int type, int src, int throw IllegalArgumentException("The specified transition type is not valid."); } +/* mem check: all created instances are freed in the d-tor of the ATN. */ ATNState *ATNDeserializer::stateFactory(int type, int ruleIndex) { ATNState *s; switch (type) { diff --git a/runtime/Cpp/runtime/atn/ATNDeserializer.h b/runtime/Cpp/runtime/atn/ATNDeserializer.h index 17840b6a4..001bf5338 100755 --- a/runtime/Cpp/runtime/atn/ATNDeserializer.h +++ b/runtime/Cpp/runtime/atn/ATNDeserializer.h @@ -53,13 +53,14 @@ namespace atn { virtual ATN deserialize(const std::wstring &input); virtual void verifyATN(const ATN &atn); - virtual void checkCondition(bool condition); - virtual void checkCondition(bool condition, const std::string &message); - virtual Transition *edgeFactory(const ATN &atn, int type, int src, int trg, int arg1, int arg2, int arg3, - const std::vector &sets); + static void checkCondition(bool condition); + static void checkCondition(bool condition, const std::string &message); - virtual ATNState *stateFactory(int type, int ruleIndex); + static Transition *edgeFactory(const ATN &atn, int type, int src, int trg, int arg1, int arg2, int arg3, + const std::vector &sets); + + static ATNState *stateFactory(int type, int ruleIndex); protected: /// Determines if a particular serialized representation of an ATN supports diff --git a/runtime/Cpp/runtime/atn/ATNSerializer.cpp b/runtime/Cpp/runtime/atn/ATNSerializer.cpp index d34cadfff..3914d9b74 100755 --- a/runtime/Cpp/runtime/atn/ATNSerializer.cpp +++ b/runtime/Cpp/runtime/atn/ATNSerializer.cpp @@ -92,13 +92,11 @@ std::vector ATNSerializer::serialize() { } int stateType = s->getStateType(); - if (dynamic_cast(s) != nullptr && - (static_cast(s))->nonGreedy) { + if (is(s) && (static_cast(s))->nonGreedy) { nonGreedyStates.push_back(s->stateNumber); } - if (dynamic_cast(s) != nullptr && - (static_cast(s))->isPrecedenceRule) { + if (is(s) && (static_cast(s))->isPrecedenceRule) { precedenceStates.push_back(s->stateNumber); } @@ -114,7 +112,7 @@ std::vector ATNSerializer::serialize() { if (s->getStateType() == ATNState::LOOP_END) { data.push_back((size_t)(static_cast(s))->loopBackState->stateNumber); } - else if (dynamic_cast(s) != nullptr) { + else if (is(s)) { data.push_back((size_t)(static_cast(s))->endState->stateNumber); } @@ -323,6 +321,9 @@ std::vector ATNSerializer::serialize() { //------------------------------------------------------------------------------------------------------------ std::wstring ATNSerializer::decode(const std::wstring &inpdata) { + if (inpdata.size() < 10) + throw IllegalArgumentException("Not enough data to decode"); + uint16_t data[inpdata.size()]; data[0] = inpdata[0]; diff --git a/runtime/Cpp/runtime/atn/ATNSimulator.cpp b/runtime/Cpp/runtime/atn/ATNSimulator.cpp index 66c3a6958..56db87055 100755 --- a/runtime/Cpp/runtime/atn/ATNSimulator.cpp +++ b/runtime/Cpp/runtime/atn/ATNSimulator.cpp @@ -62,18 +62,18 @@ ATN ATNSimulator::deserialize(const std::wstring &data) { } void ATNSimulator::checkCondition(bool condition) { - (new ATNDeserializer())->checkCondition(condition); + ATNDeserializer::checkCondition(condition); } void ATNSimulator::checkCondition(bool condition, const std::string &message) { - ATNDeserializer().checkCondition(condition, message); + ATNDeserializer::checkCondition(condition, message); } Transition *ATNSimulator::edgeFactory(const ATN &atn, int type, int src, int trg, int arg1, int arg2, int arg3, const std::vector &sets) { - return (new ATNDeserializer())->edgeFactory(atn, type, src, trg, arg1, arg2, arg3, sets); + return ATNDeserializer::edgeFactory(atn, type, src, trg, arg1, arg2, arg3, sets); } ATNState *ATNSimulator::stateFactory(int type, int ruleIndex) { - return (new ATNDeserializer())->stateFactory(type, ruleIndex); + return ATNDeserializer::stateFactory(type, ruleIndex); } diff --git a/runtime/Cpp/runtime/atn/ConfigLookup.h b/runtime/Cpp/runtime/atn/ConfigLookup.h index 3da67d422..d08b2c843 100644 --- a/runtime/Cpp/runtime/atn/ConfigLookup.h +++ b/runtime/Cpp/runtime/atn/ConfigLookup.h @@ -29,6 +29,8 @@ #pragma once +#include "ATNConfig.h" + namespace org { namespace antlr { namespace v4 { @@ -46,7 +48,7 @@ namespace atn { ConfigLookupIterator& operator++ () { ++*_iterator; return *this; }; bool operator != (const ConfigLookupIterator& rhs) const { return *_iterator != *rhs._iterator; }; - ATNConfig* operator* () const { return **_iterator; }; + ATNConfig::Ref operator * () const { return **_iterator; }; private: std::shared_ptr _iterator; }; @@ -54,9 +56,9 @@ namespace atn { virtual ~ConfigLookup() {} // Java iterator interface. - virtual ATNConfig* getOrAdd(ATNConfig *config) = 0; + virtual ATNConfig::Ref getOrAdd(ATNConfig::Ref config) = 0; virtual bool isEmpty() const = 0; - virtual bool contains(ATNConfig *config) const = 0; + virtual bool contains(ATNConfig::Ref config) const = 0; virtual void clear() = 0; // STL iterator interface. @@ -69,18 +71,18 @@ namespace atn { public: virtual ConfigLookupIteratorImpl& operator ++ () = 0; virtual bool operator != (const ConfigLookupIteratorImpl&) const = 0; - virtual ATNConfig* operator * () const = 0; + virtual ATNConfig::Ref operator * () const = 0; virtual void* underlyingIterator () = 0; virtual const void* underlyingIterator () const = 0; }; }; template - class ConfigLookupImpl: public ConfigLookup, std::unordered_set { + class ConfigLookupImpl: public ConfigLookup, std::unordered_set { public: - using Set = std::unordered_set; + using Set = std::unordered_set; - virtual ATNConfig* getOrAdd(ATNConfig *config) override { + virtual ATNConfig::Ref getOrAdd(ATNConfig::Ref config) override { auto result = Set::find(config); if (result != Set::end()) // Can potentially be a different config instance which however is considered equal to the given config @@ -95,7 +97,7 @@ namespace atn { return Set::empty(); } - virtual bool contains(ATNConfig *config) const override { + virtual bool contains(ATNConfig::Ref config) const override { return Set::count(config) > 0; } @@ -108,17 +110,21 @@ namespace atn { } ConfigLookupIterator begin() override { - return ConfigLookupIterator(new ConfigLookupImpl::ConfigLookupIteratorImpl(std::unordered_set::begin())); + return ConfigLookupIterator( + new ConfigLookupImpl::ConfigLookupIteratorImpl( + std::unordered_set::begin())); /* mem check: managed by shared_ptr in the iterator */ } ConfigLookupIterator end() override { - return ConfigLookupIterator(new ConfigLookupImpl::ConfigLookupIteratorImpl(std::unordered_set::end())); + return ConfigLookupIterator( + new ConfigLookupImpl::ConfigLookupIteratorImpl( + std::unordered_set::end())); /* mem check: managed by shared_ptr in the iterator */ } protected: class ConfigLookupIteratorImpl : public ConfigLookup::ConfigLookupIteratorImpl { public: - using UnderlyingIterator = typename std::unordered_set::iterator; + using UnderlyingIterator = typename std::unordered_set::iterator; ConfigLookupIteratorImpl(UnderlyingIterator&& iterator) : _iterator(std::move(iterator)) { } @@ -131,7 +137,7 @@ namespace atn { return *reinterpret_cast(underlyingIterator()) != *reinterpret_cast(rhs.underlyingIterator()); } - ATNConfig* operator* () const override { + ATNConfig::Ref operator * () const override { return *_iterator; } diff --git a/runtime/Cpp/runtime/atn/LL1Analyzer.cpp b/runtime/Cpp/runtime/atn/LL1Analyzer.cpp index d42bac927..91a2b13db 100755 --- a/runtime/Cpp/runtime/atn/LL1Analyzer.cpp +++ b/runtime/Cpp/runtime/atn/LL1Analyzer.cpp @@ -60,7 +60,7 @@ std::vector LL1Analyzer::getDecisionLookahead(ATNState *s) co for (size_t alt = 0; alt < s->getNumberOfTransitions(); alt++) { bool seeThruPreds = false; // fail to get lookahead upon pred - std::set lookBusy; + std::unordered_set lookBusy; antlrcpp::BitSet callRuleStack; _LOOK(s->transition(alt)->target, nullptr, PredictionContext::EMPTY, look[alt], lookBusy, callRuleStack, seeThruPreds, false); @@ -83,7 +83,7 @@ misc::IntervalSet LL1Analyzer::LOOK(ATNState *s, ATNState *stopState, RuleContex bool seeThruPreds = true; // ignore preds; get all lookahead PredictionContext::Ref lookContext = ctx != nullptr ? PredictionContext::fromRuleContext(_atn, ctx) : nullptr; - std::set lookBusy; + std::unordered_set lookBusy; antlrcpp::BitSet callRuleStack; _LOOK(s, stopState, lookContext, r, lookBusy, callRuleStack, seeThruPreds, true); @@ -91,12 +91,13 @@ misc::IntervalSet LL1Analyzer::LOOK(ATNState *s, ATNState *stopState, RuleContex } void LL1Analyzer::_LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref ctx, misc::IntervalSet &look, - std::set &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const { - ATNConfig *c = new ATNConfig(s, 0, ctx); + std::unordered_set &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const { + ATNConfig::Ref c = std::make_shared(s, 0, ctx); - if (!lookBusy.insert(c).second) { + if (lookBusy.count(c) > 0) // Keep in mind comparison is based on members of the class, not the actual instance. return; - } + + lookBusy.insert(c); if (s == stopState) { if (ctx == nullptr) { @@ -108,7 +109,7 @@ void LL1Analyzer::_LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref } } - if (dynamic_cast(s) != nullptr) { + if (is(s)) { if (ctx == nullptr) { look.add(Token::EPSILON); return; diff --git a/runtime/Cpp/runtime/atn/LL1Analyzer.h b/runtime/Cpp/runtime/atn/LL1Analyzer.h index 6f5ba77cc..fce7c81de 100755 --- a/runtime/Cpp/runtime/atn/LL1Analyzer.h +++ b/runtime/Cpp/runtime/atn/LL1Analyzer.h @@ -34,6 +34,7 @@ #include "Token.h" #include "BitSet.h" #include "PredictionContext.h" +#include "ATNConfig.h" namespace org { namespace antlr { @@ -131,7 +132,7 @@ namespace atn { /// is {@code null}. protected: virtual void _LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref ctx, misc::IntervalSet &look, - std::set &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const; + std::unordered_set &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const; }; } // namespace atn diff --git a/runtime/Cpp/runtime/atn/LexerATNConfig.cpp b/runtime/Cpp/runtime/atn/LexerATNConfig.cpp index cb1fc4d2e..def568bba 100755 --- a/runtime/Cpp/runtime/atn/LexerATNConfig.cpp +++ b/runtime/Cpp/runtime/atn/LexerATNConfig.cpp @@ -29,13 +29,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "LexerATNConfig.h" #include "MurmurHash.h" #include "DecisionState.h" #include "PredictionContext.h" #include "SemanticContext.h" +#include "CPPUtils.h" + +#include "LexerATNConfig.h" using namespace org::antlr::v4::runtime::atn; +using namespace antlrcpp; LexerATNConfig::LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context) : ATNConfig(state, alt, context, SemanticContext::NONE), passedThroughNonGreedyDecision(false) { @@ -46,17 +49,17 @@ LexerATNConfig::LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref lexerActionIndex = actionIndex; } -LexerATNConfig::LexerATNConfig(LexerATNConfig *c, ATNState *state) +LexerATNConfig::LexerATNConfig(LexerATNConfig::Ref c, ATNState *state) : ATNConfig(c, state, c->context, c->semanticContext), passedThroughNonGreedyDecision(checkNonGreedyDecision(c, state)) { lexerActionIndex = c->lexerActionIndex; } -LexerATNConfig::LexerATNConfig(LexerATNConfig *c, ATNState *state, int actionIndex) +LexerATNConfig::LexerATNConfig(LexerATNConfig::Ref c, ATNState *state, int actionIndex) : ATNConfig(c, state, c->context, c->semanticContext), passedThroughNonGreedyDecision(checkNonGreedyDecision(c, state)) { lexerActionIndex = actionIndex; } -LexerATNConfig::LexerATNConfig(LexerATNConfig *c, ATNState *state, PredictionContext::Ref context) +LexerATNConfig::LexerATNConfig(LexerATNConfig::Ref c, ATNState *state, PredictionContext::Ref context) : ATNConfig(c, state, context, c->semanticContext), passedThroughNonGreedyDecision(checkNonGreedyDecision(c, state)) { lexerActionIndex = c->lexerActionIndex; } @@ -84,7 +87,7 @@ bool LexerATNConfig::operator == (const LexerATNConfig& other) const return ATNConfig::operator == (other); } -bool LexerATNConfig::checkNonGreedyDecision(LexerATNConfig *source, ATNState *target) { +bool LexerATNConfig::checkNonGreedyDecision(LexerATNConfig::Ref source, ATNState *target) { return source->passedThroughNonGreedyDecision || - (dynamic_cast(target) != nullptr && (static_cast(target))->nonGreedy); + (is(target) && (static_cast(target))->nonGreedy); } diff --git a/runtime/Cpp/runtime/atn/LexerATNConfig.h b/runtime/Cpp/runtime/atn/LexerATNConfig.h index 474ebd2c1..790eb0a9f 100755 --- a/runtime/Cpp/runtime/atn/LexerATNConfig.h +++ b/runtime/Cpp/runtime/atn/LexerATNConfig.h @@ -41,15 +41,17 @@ namespace atn { class LexerATNConfig : public ATNConfig { public: + typedef std::shared_ptr Ref; + /// Capture lexer action we traverse. int lexerActionIndex = -1; LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context); LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context, int actionIndex); - LexerATNConfig(LexerATNConfig *c, ATNState *state); - LexerATNConfig(LexerATNConfig *c, ATNState *state, int actionIndex); - LexerATNConfig(LexerATNConfig *c, ATNState *state, PredictionContext::Ref context); + LexerATNConfig(LexerATNConfig::Ref c, ATNState *state); + LexerATNConfig(LexerATNConfig::Ref c, ATNState *state, int actionIndex); + LexerATNConfig(LexerATNConfig::Ref c, ATNState *state, PredictionContext::Ref context); bool hasPassedThroughNonGreedyDecision(); @@ -60,7 +62,7 @@ namespace atn { private: const bool passedThroughNonGreedyDecision; - static bool checkNonGreedyDecision(LexerATNConfig *source, ATNState *target); + static bool checkNonGreedyDecision(LexerATNConfig::Ref source, ATNState *target); }; } // namespace atn diff --git a/runtime/Cpp/runtime/atn/LexerATNSimulator.cpp b/runtime/Cpp/runtime/atn/LexerATNSimulator.cpp index 4f0e54dda..941a751b0 100755 --- a/runtime/Cpp/runtime/atn/LexerATNSimulator.cpp +++ b/runtime/Cpp/runtime/atn/LexerATNSimulator.cpp @@ -75,7 +75,7 @@ LexerATNSimulator::LexerATNSimulator(const ATN &atn, std::vector &deci LexerATNSimulator::LexerATNSimulator(Lexer *recog, const ATN &atn, std::vector &decisionToDFA, std::shared_ptr sharedContextCache) - : ATNSimulator(atn, sharedContextCache), _recog(recog), _decisionToDFA(decisionToDFA), prevAccept(new SimState()) { + : ATNSimulator(atn, sharedContextCache), _recog(recog), _decisionToDFA(decisionToDFA) { InitializeInstanceFields(); } @@ -96,7 +96,7 @@ int LexerATNSimulator::match(CharStream *input, size_t mode) { }); _startIndex = (int)input->index(); - prevAccept->reset(); + prevAccept.reset(); const dfa::DFA &dfa = _decisionToDFA[mode]; if (dfa.s0 == nullptr) { return matchATN(input); @@ -108,9 +108,9 @@ int LexerATNSimulator::match(CharStream *input, size_t mode) { } void LexerATNSimulator::reset() { - prevAccept->reset(); + prevAccept.reset(); _startIndex = 0; // Originally -1, but that would require a signed type with many casts. - // The initial value is never tested, so it doesn't matter which value is set here. + // The initial value is never tested, so it doesn't matter which value is set here. _line = 1; _charPositionInLine = 0; _mode = Lexer::DEFAULT_MODE; @@ -184,7 +184,7 @@ int LexerATNSimulator::execATN(CharStream *input, dfa::DFAState *ds0) { } if (target->isAcceptState) { - captureSimState(prevAccept, input, target); + captureSimState(input, target); if (t == EOF) { break; } @@ -198,7 +198,7 @@ int LexerATNSimulator::execATN(CharStream *input, dfa::DFAState *ds0) { s = target; // flip; current DFA target becomes new src/from state } - return failOrAccept(prevAccept, input, s->configs, t); + return failOrAccept(input, s->configs, t); } dfa::DFAState *LexerATNSimulator::getExistingTargetState(dfa::DFAState *s, ssize_t t) { @@ -233,12 +233,12 @@ dfa::DFAState *LexerATNSimulator::computeTargetState(CharStream *input, dfa::DFA return addDFAEdge(s, t, reach); } -int LexerATNSimulator::failOrAccept(SimState *prevAccept, CharStream *input, std::shared_ptr reach, ssize_t t) { - if (prevAccept->dfaState != nullptr) { - int ruleIndex = prevAccept->dfaState->lexerRuleIndex; - int actionIndex = prevAccept->dfaState->lexerActionIndex; - accept(input, ruleIndex, actionIndex, (size_t)prevAccept->index, prevAccept->line, (size_t)prevAccept->charPos); - return prevAccept->dfaState->prediction; +int LexerATNSimulator::failOrAccept(CharStream *input, std::shared_ptr reach, ssize_t t) { + if (prevAccept.dfaState != nullptr) { + int ruleIndex = prevAccept.dfaState->lexerRuleIndex; + int actionIndex = prevAccept.dfaState->lexerActionIndex; + accept(input, ruleIndex, actionIndex, (size_t)prevAccept.index, prevAccept.line, (size_t)prevAccept.charPos); + return prevAccept.dfaState->prediction; } else { // if no accept and EOF is first char, return EOF if (t == EOF && input->index() == (size_t)_startIndex) { @@ -257,7 +257,7 @@ void LexerATNSimulator::getReachableConfigSet(CharStream *input, std::shared_ptr for (auto c : closure->configs) { bool currentAltReachedAcceptState = c->alt == skipAlt; - if (currentAltReachedAcceptState && (static_cast(c))->hasPassedThroughNonGreedyDecision()) { + if (currentAltReachedAcceptState && (std::static_pointer_cast(c))->hasPassedThroughNonGreedyDecision()) { continue; } @@ -270,7 +270,8 @@ void LexerATNSimulator::getReachableConfigSet(CharStream *input, std::shared_ptr Transition *trans = c->state->transition(ti); ATNState *target = getReachableTarget(trans, (int)t); if (target != nullptr) { - if (this->closure(input, new LexerATNConfig(static_cast(c), target), reach, currentAltReachedAcceptState, true)) { + if (this->closure(input, std::make_shared(std::static_pointer_cast(c), target), + reach, currentAltReachedAcceptState, true)) { // any remaining configs for this alt have a lower priority than // the one that just reached an accept state. skipAlt = c->alt; @@ -318,13 +319,13 @@ std::shared_ptr LexerATNSimulator::computeStartState(CharStream *i std::shared_ptr configs = std::make_shared(); for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { ATNState *target = p->transition(i)->target; - LexerATNConfig *c = new LexerATNConfig(target, (int)(i + 1), initialContext); + LexerATNConfig::Ref c = std::make_shared(target, (int)(i + 1), initialContext); closure(input, c, configs, false, false); } return configs; } -bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std::shared_ptr configs, +bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig::Ref config, std::shared_ptr configs, bool currentAltReachedAcceptState, bool speculative) { if (debug) { std::wcout << L"closure(" << config->toString(true) << L")" << std::endl; @@ -344,7 +345,7 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std:: configs->add(config); return true; } else { - configs->add(new LexerATNConfig(config, config->state, PredictionContext::EMPTY)); + configs->add(std::make_shared(config, config->state, PredictionContext::EMPTY)); currentAltReachedAcceptState = true; } } @@ -354,7 +355,7 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std:: if (config->context->getReturnState(i) != PredictionContext::EMPTY_RETURN_STATE) { std::weak_ptr newContext = config->context->getParent(i); // "pop" return state ATNState *returnState = atn.states[(size_t)config->context->getReturnState(i)]; - LexerATNConfig *c = new LexerATNConfig(returnState, config->alt, newContext.lock()); + LexerATNConfig::Ref c = std::make_shared(returnState, config->alt, newContext.lock()); currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative); } } @@ -373,7 +374,7 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std:: ATNState *p = config->state; for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { Transition *t = p->transition(i); - LexerATNConfig *c = getEpsilonTarget(input, config, t, configs, speculative); + LexerATNConfig::Ref c = getEpsilonTarget(input, config, t, configs, speculative); if (c != nullptr) { currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative); } @@ -382,14 +383,14 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std:: return currentAltReachedAcceptState; } -atn::LexerATNConfig *LexerATNSimulator::getEpsilonTarget(CharStream *input, LexerATNConfig *config, Transition *t, - std::shared_ptr configs, bool speculative) { - LexerATNConfig *c = nullptr; +LexerATNConfig::Ref LexerATNSimulator::getEpsilonTarget(CharStream *input, LexerATNConfig::Ref config, Transition *t, + std::shared_ptr configs, bool speculative) { + LexerATNConfig::Ref c = nullptr; switch (t->getSerializationType()) { case Transition::RULE: { RuleTransition *ruleTransition = static_cast(t); PredictionContext::Ref newContext = SingletonPredictionContext::create(config->context, ruleTransition->followState->stateNumber); - c = new LexerATNConfig(config, t->target, newContext); + c = std::make_shared(config, t->target, newContext); } break; @@ -421,16 +422,16 @@ atn::LexerATNConfig *LexerATNSimulator::getEpsilonTarget(CharStream *input, Lexe } configs->hasSemanticContext = true; if (evaluatePredicate(input, pt->ruleIndex, pt->predIndex, speculative)) { - c = new LexerATNConfig(config, t->target); + c = std::make_shared(config, t->target); } } break; // ignore actions; just exec one per rule upon accept case Transition::ACTION: - c = new LexerATNConfig(config, t->target, (static_cast(t))->actionIndex); + c = std::make_shared(config, t->target, (static_cast(t))->actionIndex); break; case Transition::EPSILON: - c = new LexerATNConfig(config, t->target); + c = std::make_shared(config, t->target); break; } @@ -463,11 +464,11 @@ bool LexerATNSimulator::evaluatePredicate(CharStream *input, int ruleIndex, int return _recog->sempred(nullptr, ruleIndex, predIndex); } -void LexerATNSimulator::captureSimState(SimState *settings, CharStream *input, dfa::DFAState *dfaState) { - settings->index = (int)input->index(); - settings->line = _line; - settings->charPos = _charPositionInLine; - settings->dfaState = dfaState; +void LexerATNSimulator::captureSimState(CharStream *input, dfa::DFAState *dfaState) { + prevAccept.index = (int)input->index(); + prevAccept.line = _line; + prevAccept.charPos = _charPositionInLine; + prevAccept.dfaState = dfaState; } dfa::DFAState *LexerATNSimulator::addDFAEdge(dfa::DFAState *from, ssize_t t, std::shared_ptr q) { @@ -519,8 +520,8 @@ dfa::DFAState *LexerATNSimulator::addDFAState(std::shared_ptr conf */ assert(!configs->hasSemanticContext); - dfa::DFAState *proposed = new dfa::DFAState(configs); - ATNConfig *firstConfigWithRuleStopState = nullptr; + dfa::DFAState *proposed = new dfa::DFAState(configs); /* mem-check: managed by the DFA or deleted below */ + ATNConfig::Ref firstConfigWithRuleStopState = nullptr; for (auto c : configs->configs) { if (is(c->state)) { firstConfigWithRuleStopState = c; @@ -531,7 +532,7 @@ dfa::DFAState *LexerATNSimulator::addDFAState(std::shared_ptr conf if (firstConfigWithRuleStopState != nullptr) { proposed->isAcceptState = true; proposed->lexerRuleIndex = firstConfigWithRuleStopState->state->ruleIndex; - proposed->lexerActionIndex = (static_cast(firstConfigWithRuleStopState))->lexerActionIndex; + proposed->lexerActionIndex = (std::static_pointer_cast(firstConfigWithRuleStopState))->lexerActionIndex; proposed->prediction = atn.ruleToTokenType[(size_t)proposed->lexerRuleIndex]; } @@ -542,6 +543,7 @@ dfa::DFAState *LexerATNSimulator::addDFAState(std::shared_ptr conf auto iterator = dfa.states.find(proposed); if (iterator != dfa.states.end()) { + delete proposed; return iterator->second; } diff --git a/runtime/Cpp/runtime/atn/LexerATNSimulator.h b/runtime/Cpp/runtime/atn/LexerATNSimulator.h index 394086183..9e4b05752 100755 --- a/runtime/Cpp/runtime/atn/LexerATNSimulator.h +++ b/runtime/Cpp/runtime/atn/LexerATNSimulator.h @@ -32,6 +32,7 @@ #pragma once #include "ATNSimulator.h" +#include "LexerATNConfig.h" namespace org { namespace antlr { @@ -110,7 +111,7 @@ namespace atn { /// /// Used during DFA/ATN exec to record the most recent accept configuration info - SimState *const prevAccept; + SimState prevAccept; public: static int match_calls; @@ -153,7 +154,7 @@ namespace atn { /// returns . virtual dfa::DFAState *computeTargetState(CharStream *input, dfa::DFAState *s, ssize_t t); - virtual int failOrAccept(SimState *prevAccept, CharStream *input, std::shared_ptr reach, ssize_t t); + virtual int failOrAccept(CharStream *input, std::shared_ptr reach, ssize_t t); /// /// Given a starting configuration set, figure out all ATN configurations @@ -177,12 +178,12 @@ namespace atn { /// /// {@code true} if an accept state is reached, otherwise /// {@code false}. - virtual bool closure(CharStream *input, LexerATNConfig *config, std::shared_ptr configs, + virtual bool closure(CharStream *input, LexerATNConfig::Ref config, std::shared_ptr configs, bool currentAltReachedAcceptState, bool speculative); // side-effect: can alter configs.hasSemanticContext - virtual LexerATNConfig *getEpsilonTarget(CharStream *input, LexerATNConfig *config, Transition *t, - std::shared_ptr configs, bool speculative); + virtual LexerATNConfig::Ref getEpsilonTarget(CharStream *input, LexerATNConfig::Ref config, Transition *t, + std::shared_ptr configs, bool speculative); /// /// Evaluate a predicate specified in the lexer. @@ -206,7 +207,7 @@ namespace atn { /// {@code true}. virtual bool evaluatePredicate(CharStream *input, int ruleIndex, int predIndex, bool speculative); - virtual void captureSimState(SimState *settings, CharStream *input, dfa::DFAState *dfaState); + virtual void captureSimState(CharStream *input, dfa::DFAState *dfaState); virtual dfa::DFAState *addDFAEdge(dfa::DFAState *from, ssize_t t, std::shared_ptr q); virtual void addDFAEdge(dfa::DFAState *p, ssize_t t, dfa::DFAState *q); diff --git a/runtime/Cpp/runtime/atn/OrderedATNConfigSet.cpp b/runtime/Cpp/runtime/atn/OrderedATNConfigSet.cpp index 942d7c586..a2b11f890 100755 --- a/runtime/Cpp/runtime/atn/OrderedATNConfigSet.cpp +++ b/runtime/Cpp/runtime/atn/OrderedATNConfigSet.cpp @@ -34,5 +34,6 @@ using namespace org::antlr::v4::runtime::atn; OrderedATNConfigSet::OrderedATNConfigSet() : ATNConfigSet() { - configLookup = std::shared_ptr(new ConfigLookupImpl()); + configLookup = std::shared_ptr( + new ConfigLookupImpl()); /* mem-check: managed by shared_ptr in ConfigLookupImpl */ } diff --git a/runtime/Cpp/runtime/atn/OrderedATNConfigSet.h b/runtime/Cpp/runtime/atn/OrderedATNConfigSet.h index 72d6539f6..4b4aa7e70 100755 --- a/runtime/Cpp/runtime/atn/OrderedATNConfigSet.h +++ b/runtime/Cpp/runtime/atn/OrderedATNConfigSet.h @@ -41,18 +41,14 @@ namespace atn { struct OrderedATNConfigHasher { - size_t operator()(const ATNConfig &config) const { - return std::hash()(config); + size_t operator()(const ATNConfig::Ref &config) const { + return std::hash()(config); } }; struct OrderedATNConfigComparer { - bool operator()(const ATNConfig &lhs, const ATNConfig &rhs) const + bool operator()(const ATNConfig::Ref &lhs, const ATNConfig::Ref &rhs) const { - if (&lhs == &rhs) { // Shortcut: same address = same object. - return true; - } - return lhs == rhs; } }; diff --git a/runtime/Cpp/runtime/atn/ParserATNSimulator.cpp b/runtime/Cpp/runtime/atn/ParserATNSimulator.cpp index 59007b592..b993937fd 100755 --- a/runtime/Cpp/runtime/atn/ParserATNSimulator.cpp +++ b/runtime/Cpp/runtime/atn/ParserATNSimulator.cpp @@ -104,9 +104,13 @@ int ParserATNSimulator::adaptivePredict(TokenStream *input, int decision, Parser std::wcout << L"predictATN decision " << dfa.decision << L" exec LA(1)==" << getLookaheadName(input) << L", outerContext=" << outerContext->toString(parser) << std::endl; } bool fullCtx = false; - std::shared_ptr s0_closure = computeStartState(dynamic_cast(dfa.atnStartState), + std::shared_ptr s0_closure = computeStartState(dynamic_cast(dfa.atnStartState), ParserRuleContext::EMPTY, fullCtx); - dfa.s0 = addDFAState(dfa, new dfa::DFAState(s0_closure)); + dfa::DFAState *newState = new dfa::DFAState(s0_closure); /* mem-check: managed by the DFA or deleted below */ + dfa.s0 = addDFAState(dfa, newState); + if (dfa.s0 != newState) { + delete newState; // If there was already a state with this config set we don't need the new one. + } } // We can start with an existing DFA. @@ -243,7 +247,7 @@ dfa::DFAState *ParserATNSimulator::computeTargetState(dfa::DFA &dfa, dfa::DFASta } // create new target state; we'll add to DFA after it's complete - dfa::DFAState *D = new dfa::DFAState(reach); + dfa::DFAState *D = new dfa::DFAState(reach); /* mem-check: managed by the DFA or deleted below */ int predictedAlt = getUniqueAlt(reach); @@ -280,8 +284,11 @@ dfa::DFAState *ParserATNSimulator::computeTargetState(dfa::DFA &dfa, dfa::DFASta } // all adds to dfa are done after we've created full D state - D = addDFAEdge(dfa, previousD, t, D); - return D; + dfa::DFAState *state = addDFAEdge(dfa, previousD, t, D); + if (state != D) { + delete D; // If the new state exists already we don't need it and use the existing one instead. + } + return state; } void ParserATNSimulator::predicateDFAState(dfa::DFAState *dfaState, DecisionState *decisionState) { @@ -435,7 +442,7 @@ std::shared_ptr ParserATNSimulator::computeReachSet(std::shared_pt * ensure that the alternative matching the longest overall sequence is * chosen when multiple such configurations can match the input. */ - std::vector skippedStopStates; + std::vector skippedStopStates; // First figure out where we can reach on input t for (auto c : closure->configs) { @@ -447,10 +454,6 @@ std::shared_ptr ParserATNSimulator::computeReachSet(std::shared_pt assert(c->context->isEmpty()); if (fullCtx || t == EOF) { - if (skippedStopStates.empty()) { - skippedStopStates = std::vector(); - } - skippedStopStates.push_back(c); } @@ -462,7 +465,7 @@ std::shared_ptr ParserATNSimulator::computeReachSet(std::shared_pt Transition *trans = c->state->transition(ti); ATNState *target = getReachableTarget(trans, (int)t); if (target != nullptr) { - intermediate->add(new ATNConfig(c, target), &mergeCache); + intermediate->add(std::make_shared(c, target), &mergeCache); } } } @@ -498,7 +501,7 @@ std::shared_ptr ParserATNSimulator::computeReachSet(std::shared_pt */ if (reach == nullptr) { reach = std::make_shared(fullCtx); - std::set closureBusy; + std::set closureBusy; for (auto c : intermediate->configs) { this->closure(c, reach, closureBusy, false, fullCtx); @@ -557,7 +560,7 @@ std::shared_ptr ParserATNSimulator::removeAllConfigsNotInRuleStopS std::shared_ptr result = std::make_shared(configs->fullCtx); for (auto config : configs->configs) { - if (dynamic_cast(config->state) != nullptr) { + if (is(config->state)) { result->add(config, &mergeCache); continue; } @@ -566,7 +569,7 @@ std::shared_ptr ParserATNSimulator::removeAllConfigsNotInRuleStopS misc::IntervalSet nextTokens = atn.nextTokens(config->state); if (nextTokens.contains(Token::EPSILON)) { ATNState *endOfRuleState = atn.ruleToStopState[(size_t)config->state->ruleIndex]; - result->add(new ATNConfig(config, endOfRuleState), &mergeCache); + result->add(std::make_shared(config, endOfRuleState), &mergeCache); } } } @@ -581,8 +584,8 @@ std::shared_ptr ParserATNSimulator::computeStartState(ATNState *p, for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { ATNState *target = p->transition(i)->target; - ATNConfig *c = new ATNConfig(target, (int)i + 1, initialContext); - std::set closureBusy; + ATNConfig::Ref c = std::make_shared(target, (int)i + 1, initialContext); + std::set closureBusy; closure(c, configs, closureBusy, true, fullCtx); } @@ -652,7 +655,7 @@ std::vector ParserATNSimulator::getPredicatePre assert(pred != nullptr); if (ambigAlts.test(i)) { - pairs.push_back(new dfa::DFAState::PredPrediction(pred, (int)i)); + pairs.push_back(new dfa::DFAState::PredPrediction(pred, (int)i)); /* mem-check: managed by the DFAState it will be assigned to after return */ } if (pred != SemanticContext::NONE) { containsPredicate = true; @@ -710,28 +713,28 @@ BitSet ParserATNSimulator::evalSemanticContext(std::vector configs, - std::set &closureBusy, bool collectPredicates, bool fullCtx) { +void ParserATNSimulator::closure(ATNConfig::Ref config, std::shared_ptr configs, + std::set &closureBusy, bool collectPredicates, bool fullCtx) { const int initialDepth = 0; closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, initialDepth); assert(!fullCtx || !configs->dipsIntoOuterContext); } -void ParserATNSimulator::closureCheckingStopState(ATNConfig *config, std::shared_ptr configs, - std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth) { +void ParserATNSimulator::closureCheckingStopState(ATNConfig::Ref config, std::shared_ptr configs, + std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth) { if (debug) { std::wcout << L"closure(" << config->toString(true) << L")" << std::endl; } - if (dynamic_cast(config->state) != nullptr) { + if (is(config->state)) { // We hit rule end. If we have context info, use it // run thru all possible stack tops in ctx if (!config->context->isEmpty()) { for (size_t i = 0; i < config->context->size(); i++) { if (config->context->getReturnState(i) == PredictionContext::EMPTY_RETURN_STATE) { if (fullCtx) { - configs->add(new ATNConfig(config, config->state, PredictionContext::EMPTY), &mergeCache); + configs->add(std::make_shared(config, config->state, PredictionContext::EMPTY), &mergeCache); continue; } else { // we have no context info, just chase follow links (if greedy) @@ -744,7 +747,7 @@ void ParserATNSimulator::closureCheckingStopState(ATNConfig *config, std::shared } ATNState *returnState = atn.states[(size_t)config->context->getReturnState(i)]; std::weak_ptr newContext = config->context->getParent(i); // "pop" return state - ATNConfig *c = new ATNConfig(returnState, config->alt, newContext.lock(), config->semanticContext); + ATNConfig::Ref c = std::make_shared(returnState, config->alt, newContext.lock(), config->semanticContext); // While we have context to pop back from, we may have // gotten that context AFTER having falling off a rule. // Make sure we track that we are now out of context. @@ -769,8 +772,8 @@ void ParserATNSimulator::closureCheckingStopState(ATNConfig *config, std::shared closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth); } -void ParserATNSimulator::closure_(ATNConfig *config, std::shared_ptr configs, - std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth) { +void ParserATNSimulator::closure_(ATNConfig::Ref config, std::shared_ptr configs, + std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth) { ATNState *p = config->state; // optimization if (!p->onlyHasEpsilonTransitions()) { @@ -779,11 +782,11 @@ void ParserATNSimulator::closure_(ATNConfig *config, std::shared_ptrgetNumberOfTransitions(); i++) { Transition *t = p->transition(i); - bool continueCollecting = !(dynamic_cast(t) != nullptr) && collectPredicates; - ATNConfig *c = getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx); + bool continueCollecting = !is(t) && collectPredicates; + ATNConfig::Ref c = getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx); if (c != nullptr) { int newDepth = depth; - if (dynamic_cast(config->state) != nullptr) { + if (is(config->state)) { assert(!fullCtx); // target fell off end of rule; mark resulting c as having dipped into outer context @@ -806,7 +809,7 @@ void ParserATNSimulator::closure_(ATNConfig *config, std::shared_ptr(t) != nullptr) { + } else if (is(t)) { // latch when newDepth goes negative - once we step out of the entry context we can't return if (newDepth >= 0) { newDepth++; @@ -825,7 +828,7 @@ std::wstring ParserATNSimulator::getRuleName(size_t index) { return L""; } -atn::ATNConfig *ParserATNSimulator::getEpsilonTarget(ATNConfig *config, Transition *t, bool collectPredicates, bool inContext, bool fullCtx) { +ATNConfig::Ref ParserATNSimulator::getEpsilonTarget(ATNConfig::Ref config, Transition *t, bool collectPredicates, bool inContext, bool fullCtx) { switch (t->getSerializationType()) { case Transition::RULE: return ruleTransition(config, static_cast(t)); @@ -840,21 +843,21 @@ atn::ATNConfig *ParserATNSimulator::getEpsilonTarget(ATNConfig *config, Transiti return actionTransition(config, static_cast(t)); case Transition::EPSILON: - return new ATNConfig(config, t->target); + return std::make_shared(config, t->target); default: return nullptr; } } -atn::ATNConfig *ParserATNSimulator::actionTransition(ATNConfig *config, ActionTransition *t) { +ATNConfig::Ref ParserATNSimulator::actionTransition(ATNConfig::Ref config, ActionTransition *t) { if (debug) { std::wcout << L"ACTION edge " << t->ruleIndex << L":" << t->actionIndex << std::endl; } - return new ATNConfig(config, t->target); + return std::make_shared(config, t->target); } -atn::ATNConfig *ParserATNSimulator::precedenceTransition(ATNConfig *config, PrecedencePredicateTransition *pt, +ATNConfig::Ref ParserATNSimulator::precedenceTransition(ATNConfig::Ref config, PrecedencePredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx) { if (debug) { std::wcout << L"PRED (collectPredicates=" << collectPredicates << L") " << pt->precedence << L">=_p" << L", ctx dependent=true" << std::endl; @@ -863,7 +866,7 @@ atn::ATNConfig *ParserATNSimulator::precedenceTransition(ATNConfig *config, Prec } } - ATNConfig *c = nullptr; + ATNConfig::Ref c = nullptr; if (collectPredicates && inContext) { std::shared_ptr predicate = pt->getPredicate(); @@ -877,14 +880,14 @@ atn::ATNConfig *ParserATNSimulator::precedenceTransition(ATNConfig *config, Prec bool predSucceeds = predicate->eval(parser, _outerContext); _input->seek(currentPosition); if (predSucceeds) { - c = new ATNConfig(config, pt->target); // no pred context + c = std::make_shared(config, pt->target); // no pred context } } else { std::shared_ptr newSemCtx = std::make_shared(config->semanticContext, predicate); - c = new ATNConfig(config, pt->target, newSemCtx); + c = std::make_shared(config, pt->target, newSemCtx); } } else { - c = new ATNConfig(config, pt->target); + c = std::make_shared(config, pt->target); } if (debug) { @@ -893,7 +896,7 @@ atn::ATNConfig *ParserATNSimulator::precedenceTransition(ATNConfig *config, Prec return c; } -atn::ATNConfig *ParserATNSimulator::predTransition(ATNConfig *config, PredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx) { +ATNConfig::Ref ParserATNSimulator::predTransition(ATNConfig::Ref config, PredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx) { if (debug) { std::wcout << L"PRED (collectPredicates=" << collectPredicates << L") " << pt->ruleIndex << L":" << pt->predIndex << L", ctx dependent=" << pt->isCtxDependent << std::endl; if (parser != nullptr) { @@ -901,7 +904,7 @@ atn::ATNConfig *ParserATNSimulator::predTransition(ATNConfig *config, PredicateT } } - ATNConfig *c = nullptr; + ATNConfig::Ref c = nullptr; if (collectPredicates && (!pt->isCtxDependent || (pt->isCtxDependent && inContext))) { std::shared_ptr predicate = pt->getPredicate(); if (fullCtx) { @@ -914,14 +917,14 @@ atn::ATNConfig *ParserATNSimulator::predTransition(ATNConfig *config, PredicateT bool predSucceeds = predicate->eval(parser, _outerContext); _input->seek(currentPosition); if (predSucceeds) { - c = new ATNConfig(config, pt->target); // no pred context + c = std::make_shared(config, pt->target); // no pred context } } else { std::shared_ptr newSemCtx = std::make_shared(config->semanticContext, predicate); - c = new ATNConfig(config, pt->target, newSemCtx); + c = std::make_shared(config, pt->target, newSemCtx); } } else { - c = new ATNConfig(config, pt->target); + c = std::make_shared(config, pt->target); } if (debug) { @@ -930,14 +933,14 @@ atn::ATNConfig *ParserATNSimulator::predTransition(ATNConfig *config, PredicateT return c; } -atn::ATNConfig *ParserATNSimulator::ruleTransition(ATNConfig *config, RuleTransition *t) { +ATNConfig::Ref ParserATNSimulator::ruleTransition(ATNConfig::Ref config, RuleTransition *t) { if (debug) { std::wcout << L"CALL rule " << getRuleName((size_t)t->target->ruleIndex) << L", ctx=" << config->context << std::endl; } atn::ATNState *returnState = t->followState; PredictionContext::Ref newContext = SingletonPredictionContext::create(config->context, returnState->stateNumber); - return new atn::ATNConfig(config, t->target, newContext); + return std::make_shared(config, t->target, newContext); } BitSet ParserATNSimulator::getConflictingAlts(std::shared_ptr configs) { @@ -981,12 +984,12 @@ void ParserATNSimulator::dumpDeadEndConfigs(NoViableAltException &nvae) { std::wstring trans = L"no edges"; if (c->state->getNumberOfTransitions() > 0) { Transition *t = c->state->transition(0); - if (dynamic_cast(t) != nullptr) { + if (is(t)) { AtomTransition *at = static_cast(t); trans = L"Atom " + getTokenName(at->_label); - } else if (dynamic_cast(t) != nullptr) { + } else if (is(t)) { SetTransition *st = static_cast(t); - bool is_not = dynamic_cast(st) != nullptr; + bool is_not = is(st); trans = (is_not ? L"~" : L""); trans += L"Set "; trans += st->set.toString(); diff --git a/runtime/Cpp/runtime/atn/ParserATNSimulator.h b/runtime/Cpp/runtime/atn/ParserATNSimulator.h index ce5bc1fba..ece315751 100755 --- a/runtime/Cpp/runtime/atn/ParserATNSimulator.h +++ b/runtime/Cpp/runtime/atn/ParserATNSimulator.h @@ -36,6 +36,7 @@ #include "ATNSimulator.h" #include "PredictionContext.h" #include "SemanticContext.h" +#include "ATNConfig.h" namespace org { namespace antlr { @@ -410,30 +411,30 @@ namespace atn { ambig detection thought :( */ - virtual void closure(ATNConfig *config, std::shared_ptr configs, std::set &closureBusy, + virtual void closure(ATNConfig::Ref config, std::shared_ptr configs, std::set &closureBusy, bool collectPredicates, bool fullCtx); - virtual void closureCheckingStopState(ATNConfig *config, std::shared_ptr configs, - std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth); + virtual void closureCheckingStopState(ATNConfig::Ref config, std::shared_ptr configs, + std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth); /// Do the actual work of walking epsilon edges. - virtual void closure_(ATNConfig *config, std::shared_ptr configs, std::set &closureBusy, + virtual void closure_(ATNConfig::Ref config, std::shared_ptr configs, std::set &closureBusy, bool collectPredicates, bool fullCtx, int depth); public: virtual std::wstring getRuleName(size_t index); protected: - virtual ATNConfig *getEpsilonTarget(ATNConfig *config, Transition *t, bool collectPredicates, bool inContext, bool fullCtx); - virtual ATNConfig *actionTransition(ATNConfig *config, ActionTransition *t); + virtual ATNConfig::Ref getEpsilonTarget(ATNConfig::Ref config, Transition *t, bool collectPredicates, bool inContext, bool fullCtx); + virtual ATNConfig::Ref actionTransition(ATNConfig::Ref config, ActionTransition *t); public: - virtual ATNConfig *precedenceTransition(ATNConfig *config, PrecedencePredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx); + virtual ATNConfig::Ref precedenceTransition(ATNConfig::Ref config, PrecedencePredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx); protected: - virtual ATNConfig *predTransition(ATNConfig *config, PredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx); + virtual ATNConfig::Ref predTransition(ATNConfig::Ref config, PredicateTransition *pt, bool collectPredicates, bool inContext, bool fullCtx); - virtual ATNConfig *ruleTransition(ATNConfig *config, RuleTransition *t); + virtual ATNConfig::Ref ruleTransition(ATNConfig::Ref config, RuleTransition *t); virtual antlrcpp::BitSet getConflictingAlts(std::shared_ptr configs); diff --git a/runtime/Cpp/runtime/atn/PredictionContext.cpp b/runtime/Cpp/runtime/atn/PredictionContext.cpp index f7caf6285..2a97116ca 100755 --- a/runtime/Cpp/runtime/atn/PredictionContext.cpp +++ b/runtime/Cpp/runtime/atn/PredictionContext.cpp @@ -53,6 +53,9 @@ const int PredictionContext::INITIAL_HASH; PredictionContext::PredictionContext(size_t cachedHashCode) : id(globalNodeCount++), cachedHashCode(cachedHashCode) { } +PredictionContext::~PredictionContext() { +} + PredictionContext::Ref PredictionContext::fromRuleContext(const ATN &atn, RuleContext::Ref outerContext) { if (!outerContext) { outerContext = RuleContext::EMPTY; @@ -145,10 +148,10 @@ PredictionContext::Ref PredictionContext::merge(PredictionContext::Ref a, // convert singleton so both are arrays to normalize if (is(a)) { - a.reset(new ArrayPredictionContext(std::dynamic_pointer_cast(a))); + a = std::make_shared(std::dynamic_pointer_cast(a)); } if (is(b)) { - b.reset(new ArrayPredictionContext(std::dynamic_pointer_cast(b))); + b = std::make_shared(std::dynamic_pointer_cast(b)); } return mergeArrays(std::dynamic_pointer_cast(a), std::dynamic_pointer_cast(b), rootIsWildcard, mergeCache); @@ -212,7 +215,7 @@ PredictionContext::Ref PredictionContext::mergeSingletons(SingletonPredictionCon payloads[1] = a->returnState; } std::vector> parents = { singleParent, singleParent }; - PredictionContext::Ref a_(new ArrayPredictionContext(parents, payloads)); + PredictionContext::Ref a_ = std::make_shared(parents, payloads); if (mergeCache != nullptr) { (*mergeCache)[{ a.get(), b.get() }] = a_; } @@ -226,11 +229,11 @@ PredictionContext::Ref PredictionContext::mergeSingletons(SingletonPredictionCon if (a->returnState > b->returnState) { // sort by payload std::vector payloads = { b->returnState, a->returnState }; std::vector> parents = { b->parent, a->parent }; - a_.reset(new ArrayPredictionContext(parents, payloads)); + a_ = std::make_shared(parents, payloads); } else { std::vector payloads = {a->returnState, b->returnState}; std::vector> parents = { a->parent, b->parent }; - a_.reset(new ArrayPredictionContext(parents, payloads)); + a_ = std::make_shared(parents, payloads); } if (mergeCache != nullptr) { @@ -256,13 +259,13 @@ PredictionContext::Ref PredictionContext::mergeRoot(SingletonPredictionContext:: if (a == EMPTY) { // $ + x = [$,x] std::vector payloads = { b->returnState, EMPTY_RETURN_STATE }; std::vector> parents = { b->parent, EMPTY }; - PredictionContext::Ref joined(new ArrayPredictionContext(parents, payloads)); + PredictionContext::Ref joined = std::make_shared(parents, payloads); return joined; } if (b == EMPTY) { // x + $ = [$,x] ($ is always first if present) std::vector payloads = { a->returnState, EMPTY_RETURN_STATE }; std::vector> parents = { a->parent, EMPTY }; - PredictionContext::Ref joined(new ArrayPredictionContext(parents, payloads)); + PredictionContext::Ref joined = std::make_shared(parents, payloads); return joined; } } @@ -288,10 +291,8 @@ PredictionContext::Ref PredictionContext::mergeArrays(std::shared_ptr mergedReturnStates; - mergedReturnStates.resize(a->returnStates.size() + b->returnStates.size()); - std::vector> mergedParents; - mergedParents.resize(a->returnStates.size() + b->returnStates.size()); + std::vector mergedReturnStates(a->returnStates.size() + b->returnStates.size()); + std::vector> mergedParents(a->returnStates.size() + b->returnStates.size()); // walk and merge to yield mergedParents, mergedReturnStates while (i < a->returnStates.size() && j < b->returnStates.size()) { @@ -355,7 +356,7 @@ PredictionContext::Ref PredictionContext::mergeArrays(std::shared_ptr M(new ArrayPredictionContext(mergedParents, mergedReturnStates)); + std::shared_ptr M = std::make_shared(mergedParents, mergedReturnStates); // if we created same array as a or b, return that instead // TO_DO: track whether this is possible above during merge sort for speed @@ -373,7 +374,7 @@ PredictionContext::Ref PredictionContext::mergeArrays(std::shared_ptr(mergedParents, mergedReturnStates); if (mergeCache != nullptr) { (*mergeCache)[{ a.get(), b.get() }] = M; @@ -485,8 +486,7 @@ PredictionContext::Ref PredictionContext::getCachedContext(PredictionContext::Re bool changed = false; - std::vector> parents; - parents.resize(context->size()); + std::vector> parents(context->size()); for (size_t i = 0; i < parents.size(); i++) { std::weak_ptr parent = getCachedContext(context->getParent(i).lock(), contextCache, visited); if (changed || parent.lock() != context->getParent(i).lock()) { diff --git a/runtime/Cpp/runtime/atn/PredictionContext.h b/runtime/Cpp/runtime/atn/PredictionContext.h index c44e4c0b8..dcc0e924a 100755 --- a/runtime/Cpp/runtime/atn/PredictionContext.h +++ b/runtime/Cpp/runtime/atn/PredictionContext.h @@ -92,6 +92,7 @@ namespace atn { protected: PredictionContext(size_t cachedHashCode); + ~PredictionContext(); public: /// Convert a RuleContext tree to a PredictionContext graph. diff --git a/runtime/Cpp/runtime/atn/PredictionMode.cpp b/runtime/Cpp/runtime/atn/PredictionMode.cpp index a62a3ec90..540b4d896 100755 --- a/runtime/Cpp/runtime/atn/PredictionMode.cpp +++ b/runtime/Cpp/runtime/atn/PredictionMode.cpp @@ -38,6 +38,7 @@ using namespace org::antlr::v4::runtime; using namespace org::antlr::v4::runtime::atn; +using namespace antlrcpp; struct AltAndContextConfigHasher { @@ -77,8 +78,8 @@ bool PredictionModeClass::hasSLLConflictTerminatingPrediction(PredictionMode* mo if (configs->hasSemanticContext) { // dup configs, tossing out semantic predicates std::shared_ptr dup = std::make_shared(true); - for (ATNConfig config : configs->configs) { - ATNConfig* c = new ATNConfig(&config, SemanticContext::NONE); + for (auto config : configs->configs) { + ATNConfig::Ref c = std::make_shared(config, SemanticContext::NONE); dup->add(c); } configs = dup; @@ -94,8 +95,8 @@ bool PredictionModeClass::hasSLLConflictTerminatingPrediction(PredictionMode* mo } bool PredictionModeClass::hasConfigInRuleStopState(std::shared_ptr configs) { - for (ATNConfig c : configs->configs) { - if (dynamic_cast(c.state) != NULL) { + for (auto c : configs->configs) { + if (is(c->state)) { return true; } } @@ -104,8 +105,8 @@ bool PredictionModeClass::hasConfigInRuleStopState(std::shared_ptr } bool PredictionModeClass::allConfigsInRuleStopStates(std::shared_ptr configs) { - for (ATNConfig config : configs->configs) { - if (dynamic_cast(config.state) == NULL) { + for (auto config : configs->configs) { + if (!is(config->state)) { return false; } } @@ -171,7 +172,7 @@ antlrcpp::BitSet PredictionModeClass::getAlts(const std::vector PredictionModeClass::getConflictingAltSubsets(std::shared_ptr configs) { - std::unordered_map configToAlts; + std::unordered_map configToAlts; for (auto config : configs->configs) { configToAlts[config].set((size_t)config->alt); } @@ -184,8 +185,8 @@ std::vector PredictionModeClass::getConflictingAltSubsets(std: std::map PredictionModeClass::getStateToAltMap(std::shared_ptr configs) { std::map m; - for (ATNConfig c : configs->configs) { - m[c.state].set((size_t)c.alt); + for (auto c : configs->configs) { + m[c->state].set((size_t)c->alt); } return m; } diff --git a/runtime/Cpp/runtime/dfa/DFA.cpp b/runtime/Cpp/runtime/dfa/DFA.cpp index e368210be..768c3e3dd 100755 --- a/runtime/Cpp/runtime/dfa/DFA.cpp +++ b/runtime/Cpp/runtime/dfa/DFA.cpp @@ -44,6 +44,12 @@ DFA::DFA(atn::DecisionState *atnStartState, int decision) : atnStartState(atnStartState), decision(decision), s0(nullptr) { } +DFA::~DFA() { + for (auto state : states) { + delete state.second; + } +} + std::vector DFA::getStates() { std::vector result; for (auto state : states) diff --git a/runtime/Cpp/runtime/dfa/DFA.h b/runtime/Cpp/runtime/dfa/DFA.h index 488084e4d..014aab0e0 100755 --- a/runtime/Cpp/runtime/dfa/DFA.h +++ b/runtime/Cpp/runtime/dfa/DFA.h @@ -44,21 +44,18 @@ namespace dfa { /// From which ATN state did we create this DFA? atn::DecisionState *const atnStartState; - std::unordered_map states; + std::unordered_map states; // States are owned by this class. DFAState *s0; const int decision; - DFA(atn::DecisionState *atnStartState); //this(atnStartState, 0); - + DFA(atn::DecisionState *atnStartState); DFA(atn::DecisionState *atnStartState, int decision); + ~DFA(); - /// /// Return a list of all states in this DFA, ordered by state number. - /// virtual std::vector getStates(); virtual std::wstring toString(); - virtual std::wstring toString(const std::vector& tokenNames); virtual std::wstring toLexerString(); diff --git a/runtime/Cpp/runtime/dfa/DFAState.cpp b/runtime/Cpp/runtime/dfa/DFAState.cpp index 52a7f8c20..eec4f8be0 100755 --- a/runtime/Cpp/runtime/dfa/DFAState.cpp +++ b/runtime/Cpp/runtime/dfa/DFAState.cpp @@ -64,16 +64,19 @@ DFAState::DFAState(std::shared_ptr configs) : DFAState() { this->configs = configs; } -std::set *DFAState::getAltSet() { - std::set *alts = new std::set(); +DFAState::~DFAState() { + for (auto predicate : predicates) { + delete predicate; + } +} + +std::set DFAState::getAltSet() { + std::set alts; if (configs != nullptr) { for (size_t i = 0; i < configs->size(); i++) { - alts->insert(configs->get(i)->alt); + alts.insert(configs->get(i)->alt); } } - if (alts->size() == 0) { - return nullptr; - } return alts; } diff --git a/runtime/Cpp/runtime/dfa/DFAState.h b/runtime/Cpp/runtime/dfa/DFAState.h index 021c8b723..5061bcaf3 100755 --- a/runtime/Cpp/runtime/dfa/DFAState.h +++ b/runtime/Cpp/runtime/dfa/DFAState.h @@ -125,12 +125,13 @@ namespace dfa { DFAState(); DFAState(int state); DFAState(std::shared_ptr configs); + ~DFAState(); /// /// Get the set of all alts mentioned by all ATN configurations in this /// DFA state. /// - virtual std::set *getAltSet(); + virtual std::set getAltSet(); virtual size_t hashCode() ; diff --git a/runtime/Cpp/runtime/support/Arrays.h b/runtime/Cpp/runtime/support/Arrays.h index 1e379768c..42f1da222 100644 --- a/runtime/Cpp/runtime/support/Arrays.h +++ b/runtime/Cpp/runtime/support/Arrays.h @@ -77,8 +77,7 @@ namespace antlrcpp { template static std::vector copyOf(const std::vector &source, size_t count) { - std::vector result; - result.resize(std::min(source.size(), count)); + std::vector result(std::min(source.size(), count)); std::copy(source.begin(), source.end(), result.begin()); return result; } diff --git a/runtime/Cpp/runtime/tree/ParseTreeProperty.h b/runtime/Cpp/runtime/tree/ParseTreeProperty.h index a94bb7422..681158475 100755 --- a/runtime/Cpp/runtime/tree/ParseTreeProperty.h +++ b/runtime/Cpp/runtime/tree/ParseTreeProperty.h @@ -55,29 +55,28 @@ namespace tree { /// template class ParseTreeProperty { - protected: - std::map *annotations; - - public: - virtual V get(ParseTree *node) { - return annotations->get(node); - } - virtual void put(ParseTree *node, V value) { - annotations->put(node, value); - } - virtual V removeFrom(ParseTree *node) { - return annotations->remove(node); - } - - private: - void InitializeInstanceFields() { - annotations = new std::map(); - } - public: ParseTreeProperty() { InitializeInstanceFields(); } + + virtual V get(ParseTree *node) { + return _annotations.get(node); + } + virtual void put(ParseTree *node, V value) { + _annotations.put(node, value); + } + virtual V removeFrom(ParseTree *node) { + return _annotations->remove(node); + } + + protected: + std::map _annotations; + + private: + void InitializeInstanceFields() { + } + }; } // namespace tree diff --git a/runtime/Cpp/runtime/tree/Trees.cpp b/runtime/Cpp/runtime/tree/Trees.cpp index 7bafb6ebb..e1f9fe0d0 100755 --- a/runtime/Cpp/runtime/tree/Trees.cpp +++ b/runtime/Cpp/runtime/tree/Trees.cpp @@ -47,18 +47,19 @@ std::wstring Trees::toStringTree(std::shared_ptr t) { } std::wstring Trees::toStringTree(std::shared_ptr t, Parser *recog) { + if (recog == nullptr) + return toStringTree(t, {}); return toStringTree(t, recog->getRuleNames()); } std::wstring Trees::toStringTree(std::shared_ptr t, const std::vector &ruleNames) { - std::wstring tmp = Trees::getNodeText(t, ruleNames); - std::wstring s = antlrcpp::escapeWhitespace(tmp, false); + std::wstring temp = antlrcpp::escapeWhitespace(Trees::getNodeText(t, ruleNames), false); if (t->getChildCount() == 0) { - return s; + return temp; } std::wstringstream ss; - ss << L"(" << antlrcpp::escapeWhitespace(getNodeText(t, ruleNames), false) << L' '; + ss << L"(" << temp << L' '; for (size_t i = 0; i < t->getChildCount(); i++) { if (i > 0) { ss << L' '; diff --git a/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.cpp b/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.cpp index be2c142e4..563d9275a 100755 --- a/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.cpp +++ b/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.cpp @@ -101,8 +101,13 @@ ParseTreeMatch ParseTreePatternMatcher::match(std::shared_ptr tree, c ParseTreePattern ParseTreePatternMatcher::compile(const std::wstring &pattern, int patternRuleIndex) { std::vector tokenList = tokenize(pattern); - ListTokenSource *tokenSrc = new ListTokenSource(tokenList); // XXX: mem leak - CommonTokenStream *tokens = new CommonTokenStream(tokenSrc); + + ListTokenSource *tokenSrc = new ListTokenSource(tokenList); /* mem-check: deleted in finally block */ + CommonTokenStream *tokens = new CommonTokenStream(tokenSrc); /* mem-check: deleted in finally block */ + auto onExit = finally([tokenSrc, tokens]() { + delete tokenSrc; + delete tokens; + }); ParserInterpreter parserInterp(_parser->getGrammarFileName(), _parser->getTokenNames(), _parser->getRuleNames(), _parser->getATNWithBypassAlts(), tokens); @@ -230,34 +235,35 @@ std::shared_ptr ParseTreePatternMatcher::getRuleTagToken(std::shar std::vector ParseTreePatternMatcher::tokenize(const std::wstring &pattern) { // split pattern into chunks: sea (raw input) and islands (, ) - std::vector chunks = split(pattern); + std::vector chunks = split(pattern); // create token stream from text and tags std::vector tokens; for (auto chunk : chunks) { - if (dynamic_cast(chunk) != nullptr) { - TagChunk *tagChunk = static_cast(chunk); + if (is(chunk)) { + TagChunk &tagChunk = (TagChunk&)chunk; // add special rule token or conjure up new token from name - if (isupper(tagChunk->getTag()[0])) { - int ttype = _parser->getTokenType(tagChunk->getTag()); + if (isupper(tagChunk.getTag()[0])) { + int ttype = _parser->getTokenType(tagChunk.getTag()); if (ttype == Token::INVALID_TYPE) { - throw IllegalArgumentException(std::string("Unknown token ") + antlrcpp::ws2s(tagChunk->getTag()) + std::string(" in pattern: ") + antlrcpp::ws2s(pattern)); + throw IllegalArgumentException("Unknown token " + antlrcpp::ws2s(tagChunk.getTag()) + + " in pattern: " + antlrcpp::ws2s(pattern)); } - std::shared_ptr t = std::make_shared(tagChunk->getTag(), ttype, tagChunk->getLabel()); + std::shared_ptr t = std::make_shared(tagChunk.getTag(), ttype, tagChunk.getLabel()); tokens.push_back(t); - } else if (islower(tagChunk->getTag()[0])) { - int ruleIndex = _parser->getRuleIndex(tagChunk->getTag()); + } else if (islower(tagChunk.getTag()[0])) { + int ruleIndex = _parser->getRuleIndex(tagChunk.getTag()); if (ruleIndex == -1) { - throw IllegalArgumentException(std::string("Unknown rule ") + antlrcpp::ws2s(tagChunk->getTag()) + " in pattern: " + antlrcpp::ws2s(pattern)); + throw IllegalArgumentException(std::string("Unknown rule ") + antlrcpp::ws2s(tagChunk.getTag()) + " in pattern: " + antlrcpp::ws2s(pattern)); } int ruleImaginaryTokenType = _parser->getATNWithBypassAlts().ruleToTokenType[(size_t)ruleIndex]; - tokens.push_back(std::make_shared(tagChunk->getTag(), ruleImaginaryTokenType, tagChunk->getLabel())); + tokens.push_back(std::make_shared(tagChunk.getTag(), ruleImaginaryTokenType, tagChunk.getLabel())); } else { - throw IllegalArgumentException(std::string("invalid tag: ") + antlrcpp::ws2s(tagChunk->getTag()) + " in pattern: " + antlrcpp::ws2s(pattern)); + throw IllegalArgumentException(std::string("invalid tag: ") + antlrcpp::ws2s(tagChunk.getTag()) + " in pattern: " + antlrcpp::ws2s(pattern)); } } else { - TextChunk *textChunk = static_cast(chunk); - ANTLRInputStream input(textChunk->getText()); + TextChunk &textChunk = (TextChunk&)chunk; + ANTLRInputStream input(textChunk.getText()); _lexer->setInputStream(&input); Token::Ref t = _lexer->nextToken(); while (t->getType() != EOF) { @@ -271,10 +277,10 @@ std::vector ParseTreePatternMatcher::tokenize(const std::wstring &pa return tokens; } -std::vector ParseTreePatternMatcher::split(const std::wstring &pattern) { +std::vector ParseTreePatternMatcher::split(const std::wstring &pattern) { size_t p = 0; size_t n = pattern.length(); - std::vector chunks = std::vector(); + std::vector chunks; // find all start and stop indexes first, then collect std::vector starts; @@ -313,12 +319,12 @@ std::vector ParseTreePatternMatcher::split(const std::wstring &pattern) // collect into chunks now if (ntags == 0) { std::wstring text = pattern.substr(0, n); - chunks.push_back(new TextChunk(text)); + chunks.push_back(TextChunk(text)); } if (ntags > 0 && starts[0] > 0) { // copy text up to first tag into chunks std::wstring text = pattern.substr(0, starts[0]); - chunks.push_back(new TextChunk(text)); + chunks.push_back(TextChunk(text)); } for (size_t i = 0; i < ntags; i++) { // copy inside of @@ -330,30 +336,30 @@ std::vector ParseTreePatternMatcher::split(const std::wstring &pattern) label = tag.substr(0,colon); ruleOrToken = tag.substr(colon + 1, tag.length() - (colon + 1)); } - chunks.push_back(new TagChunk(label, ruleOrToken)); + chunks.push_back(TagChunk(label, ruleOrToken)); if (i + 1 < ntags) { // copy from end of to start of next std::wstring text = pattern.substr(stops[i] + _stop.length(), starts[i + 1] - (stops[i] + _stop.length())); - chunks.push_back(new TextChunk(text)); + 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::wstring text = pattern.substr(afterLastTag, n - afterLastTag); - chunks.push_back(new TextChunk(text)); + 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 (dynamic_cast(c) != nullptr) { - TextChunk *tc = static_cast(c); - std::wstring unescaped = tc->getText(); + Chunk &c = chunks[i]; + if (is(c)) { + TextChunk &tc = (TextChunk&)c; + std::wstring unescaped = tc.getText(); unescaped.erase(std::remove(unescaped.begin(), unescaped.end(), L'\\'), unescaped.end()); - if (unescaped.length() < tc->getText().length()) { - chunks[i] = new TextChunk(unescaped); + if (unescaped.length() < tc.getText().length()) { + chunks[i] = TextChunk(unescaped); } } } diff --git a/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.h b/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.h index 8e343dee3..e1e5f3a69 100755 --- a/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.h +++ b/runtime/Cpp/runtime/tree/pattern/ParseTreePatternMatcher.h @@ -170,7 +170,7 @@ namespace pattern { virtual std::vector tokenize(const std::wstring &pattern); /// Split " = ;" into 4 chunks for tokenizing by tokenize(). - virtual std::vector split(const std::wstring &pattern); + virtual std::vector split(const std::wstring &pattern); protected: std::wstring _start; diff --git a/runtime/Cpp/runtime/tree/pattern/TagChunk.h b/runtime/Cpp/runtime/tree/pattern/TagChunk.h index a674ebf11..d788dd8e6 100755 --- a/runtime/Cpp/runtime/tree/pattern/TagChunk.h +++ b/runtime/Cpp/runtime/tree/pattern/TagChunk.h @@ -65,6 +65,7 @@ namespace pattern { /// const std::wstring _label; + public: /// /// Construct a new instance of using the specified tag and /// no label. @@ -74,8 +75,7 @@ namespace pattern { /// /// if {@code tag} is {@code null} or /// empty. - public: - TagChunk(const std::wstring &tag); //this(nullptr, tag); + TagChunk(const std::wstring &tag); /// /// Construct a new instance of using the specified label