Finished checking all memory allocations.

- All allocations are now checked for proper deallocation.
- Ran LLVM analyzer over the runtime but it found mostly valid stuff and did not find non-freed allocations I left undeleted by intention. So it's not worth much.
- Added move and copy assignment operator overloading, as well as a copy c-tor to ATN class to avoid a copy (and to be able to free content properly) after deserialization.
- Some clean up.
This commit is contained in:
Mike Lischke 2016-04-20 17:51:24 +02:00
parent f292d14abc
commit e8325623d9
49 changed files with 532 additions and 448 deletions

View File

@ -12,18 +12,20 @@
#include "TLexer.h" #include "TLexer.h"
#include "TParser.h" #include "TParser.h"
#include "Strings.h"
using namespace antlrcpptest; using namespace antlrcpptest;
using namespace org::antlr::v4::runtime; using namespace org::antlr::v4::runtime;
int main(int argc, const char * argv[]) { int main(int argc, const char * argv[]) {
ANTLRInputStream input(L"divide and conquer"); ANTLRInputStream input(L"divideŴ and conquer");
TLexer lexer(&input); TLexer lexer(&input);
CommonTokenStream tokens(&lexer); CommonTokenStream tokens(&lexer);
TParser parser(&tokens); TParser parser(&tokens);
std::shared_ptr<tree::ParseTree> tree = parser.main(); std::shared_ptr<tree::ParseTree> tree = parser.main();
std::wcout << tree->toStringTree(&parser) << std::endl; std::cout << antlrcpp::ws2s(tree->toStringTree(&parser)) << std::endl;
return 0; return 0;
} }

View File

@ -541,12 +541,12 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
2747A7081CA691310030247B /* ConfigLookup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConfigLookup.cpp; sourceTree = "<group>"; }; 2747A7081CA691310030247B /* ConfigLookup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConfigLookup.cpp; sourceTree = "<group>"; };
2747A7091CA691310030247B /* ConfigLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigLookup.h; sourceTree = "<group>"; }; 2747A7091CA691310030247B /* ConfigLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigLookup.h; sourceTree = "<group>"; wrapsLines = 0; };
2747A7121CA6C46C0030247B /* InputHandlingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputHandlingTests.mm; sourceTree = "<group>"; wrapsLines = 0; }; 2747A7121CA6C46C0030247B /* InputHandlingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputHandlingTests.mm; sourceTree = "<group>"; wrapsLines = 0; };
274FC6D81CA96B6C008D4374 /* MiscClassTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MiscClassTests.mm; sourceTree = "<group>"; wrapsLines = 0; }; 274FC6D81CA96B6C008D4374 /* MiscClassTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MiscClassTests.mm; sourceTree = "<group>"; wrapsLines = 0; };
276927231C9ED49100E4EBF8 /* antlrcpp-Prefix.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = "antlrcpp-Prefix.h"; path = "../../runtime/antlrcpp-Prefix.h"; sourceTree = "<group>"; }; 276927231C9ED49100E4EBF8 /* antlrcpp-Prefix.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = "antlrcpp-Prefix.h"; path = "../../runtime/antlrcpp-Prefix.h"; sourceTree = "<group>"; };
278A66FA1C95838E002D667E /* ANTLRErrorListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ANTLRErrorListener.cpp; path = ../../runtime/ANTLRErrorListener.cpp; sourceTree = SOURCE_ROOT; }; 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 = "<group>"; }; 27A23EA11CC2A8D60036D8A3 /* TLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TLexer.cpp; path = ../generated/TLexer.cpp; sourceTree = "<group>"; wrapsLines = 0; };
27A23EA21CC2A8D60036D8A3 /* TLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TLexer.h; path = ../generated/TLexer.h; sourceTree = "<group>"; }; 27A23EA21CC2A8D60036D8A3 /* TLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TLexer.h; path = ../generated/TLexer.h; sourceTree = "<group>"; };
27C6665D1C9584050021E494 /* ANTLRErrorListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ANTLRErrorListener.h; path = ../../runtime/ANTLRErrorListener.h; sourceTree = SOURCE_ROOT; wrapsLines = 0; }; 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; }; 27C6665E1C9584050021E494 /* ANTLRErrorStrategy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ANTLRErrorStrategy.cpp; path = ../../runtime/ANTLRErrorStrategy.cpp; sourceTree = SOURCE_ROOT; };

View File

@ -38,7 +38,7 @@ Digit: [0..9];
ID: LETTER (LETTER | '0'..'9')*; ID: LETTER (LETTER | '0'..'9')*;
fragment LETTER : [a-zA-Z\u0080-\uFFFD] ; fragment LETTER : [a-zA-Z\u0080-\uFFFD] ;
LessThan: '<' -> pushMode(Mode1); LessThan: '<';// -> pushMode(Mode1);
GreaterThan: '>';// -> popMode; GreaterThan: '>';// -> popMode;
Equal: '='; Equal: '=';
And: 'and'; And: 'and';

View File

@ -68,7 +68,7 @@ void ANTLRInputStream::load(std::wistream &stream, std::streamsize readChunkSize
readChunkSize = READ_BUFFER_SIZE; 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] { auto onExit = finally([buffer] {
delete[] buffer; delete[] buffer;
}); });

View File

@ -38,11 +38,7 @@ namespace antlr {
namespace v4 { namespace v4 {
namespace runtime { namespace runtime {
/// <summary> /// Bail out of parser at first syntax error. Use myparser.setErrorHandler(..) to set a different strategy.
/// Bail out of parser at first syntax error. Do this to use it:
/// <p/>
/// {@code myparser.setErrorHandler(new BailErrorStrategy());}
/// </summary>
class BailErrorStrategy : public DefaultErrorStrategy { class BailErrorStrategy : public DefaultErrorStrategy {
/// <summary> /// <summary>
/// Instead of recovering from exception {@code e}, re-throw it wrapped /// Instead of recovering from exception {@code e}, re-throw it wrapped

View File

@ -61,7 +61,6 @@ bool DefaultErrorStrategy::inErrorRecoveryMode(Parser *recognizer) {
void DefaultErrorStrategy::endErrorCondition(Parser *recognizer) { void DefaultErrorStrategy::endErrorCondition(Parser *recognizer) {
errorRecoveryMode = false; errorRecoveryMode = false;
delete lastErrorStates;
lastErrorIndex = -1; lastErrorIndex = -1;
} }
@ -93,8 +92,8 @@ void DefaultErrorStrategy::reportError(Parser *recognizer, const RecognitionExce
} }
void DefaultErrorStrategy::recover(Parser *recognizer, const RecognitionException &e) { void DefaultErrorStrategy::recover(Parser *recognizer, const RecognitionException &e) {
if (lastErrorIndex == (int)recognizer->getInputStream()->index() && lastErrorStates != nullptr && if (lastErrorIndex == (int)recognizer->getInputStream()->index() &&
lastErrorStates->contains(recognizer->getState())) { lastErrorStates.contains(recognizer->getState())) {
// uh oh, another error at same token index and previously-visited // 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 // 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(); recognizer->consume();
} }
lastErrorIndex = (int)recognizer->getInputStream()->index(); lastErrorIndex = (int)recognizer->getInputStream()->index();
if (lastErrorStates == nullptr) { lastErrorStates.add(recognizer->getState());
lastErrorStates = new misc::IntervalSet(0);
}
lastErrorStates->add(recognizer->getState());
misc::IntervalSet followSet = getErrorRecoverySet(recognizer); misc::IntervalSet followSet = getErrorRecoverySet(recognizer);
consumeUntil(recognizer, followSet); consumeUntil(recognizer, followSet);
} }
@ -353,5 +349,4 @@ void DefaultErrorStrategy::consumeUntil(Parser *recognizer, const misc::Interval
void DefaultErrorStrategy::InitializeInstanceFields() { void DefaultErrorStrategy::InitializeInstanceFields() {
errorRecoveryMode = false; errorRecoveryMode = false;
lastErrorIndex = -1; lastErrorIndex = -1;
lastErrorStates = nullptr;
} }

View File

@ -67,7 +67,7 @@ namespace runtime {
/// </summary> /// </summary>
int lastErrorIndex; int lastErrorIndex;
misc::IntervalSet *lastErrorStates; misc::IntervalSet lastErrorStates;
/// <summary> /// <summary>
/// {@inheritDoc} /// {@inheritDoc}
@ -377,7 +377,7 @@ namespace runtime {
/// to use t.toString() (which, for CommonToken, dumps everything about /// to use t.toString() (which, for CommonToken, dumps everything about
/// the token). This is better than forcing you to override a method in /// 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 /// 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.
/// </summary> /// </summary>
virtual std::wstring getTokenErrorDisplay(Token::Ref t); virtual std::wstring getTokenErrorDisplay(Token::Ref t);

View File

@ -103,7 +103,7 @@ antlrcpp::BitSet DiagnosticErrorListener::getConflictingAlts(const antlrcpp::Bit
antlrcpp::BitSet result; antlrcpp::BitSet result;
for (size_t i = 0; i < configs->size(); i++) { 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); result.set((size_t)config->alt);
} }

View File

@ -34,10 +34,12 @@
#include "PredicateTransition.h" #include "PredicateTransition.h"
#include "ATN.h" #include "ATN.h"
#include "ATNState.h" #include "ATNState.h"
#include "CPPUtils.h"
#include "FailedPredicateException.h" #include "FailedPredicateException.h"
using namespace org::antlr::v4::runtime; using namespace org::antlr::v4::runtime;
using namespace antlrcpp;
FailedPredicateException::FailedPredicateException(Parser *recognizer) : FailedPredicateException(recognizer, "", "") { FailedPredicateException::FailedPredicateException(Parser *recognizer) : FailedPredicateException(recognizer, "", "") {
} }
@ -51,7 +53,7 @@ FailedPredicateException::FailedPredicateException(Parser *recognizer, const std
atn::ATNState *s = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[(size_t)recognizer->getState()]; atn::ATNState *s = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[(size_t)recognizer->getState()];
atn::Transition *transition = s->transition(0); atn::Transition *transition = s->transition(0);
if (dynamic_cast<atn::PredicateTransition*>(transition) != nullptr) { if (is<atn::PredicateTransition*>(transition)) {
_ruleIndex = ((atn::PredicateTransition *)transition)->ruleIndex; _ruleIndex = ((atn::PredicateTransition *)transition)->ruleIndex;
_predicateIndex = ((atn::PredicateTransition *)transition)->predIndex; _predicateIndex = ((atn::PredicateTransition *)transition)->predIndex;
} }

View File

@ -43,16 +43,17 @@ LexerInterpreter::LexerInterpreter(const std::wstring &grammarFileName, const st
const std::vector<std::wstring> &ruleNames, const std::vector<std::wstring> &modeNames, const atn::ATN &atn, const std::vector<std::wstring> &ruleNames, const std::vector<std::wstring> &modeNames, const atn::ATN &atn,
CharStream *input) CharStream *input)
: Lexer(input), grammarFileName(grammarFileName), _tokenNames(tokenNames), _ruleNames(ruleNames), _modeNames(modeNames), : Lexer(input), grammarFileName(grammarFileName), _tokenNames(tokenNames), _ruleNames(ruleNames), _modeNames(modeNames),
_atn(atn), _sharedContextCache(new atn::PredictionContextCache()) { _atn(atn) {
if (_atn.grammarType != atn::ATNType::LEXER) { if (_atn.grammarType != atn::ATNType::LEXER) {
throw IllegalArgumentException("The ATN must be a lexer ATN."); throw IllegalArgumentException("The ATN must be a lexer ATN.");
} }
_sharedContextCache = std::make_shared<atn::PredictionContextCache>();
for (size_t i = 0; i < (size_t)atn.getNumberOfDecisions(); ++i) { for (size_t i = 0; i < (size_t)atn.getNumberOfDecisions(); ++i) {
_decisionToDFA.push_back(dfa::DFA(_atn.getDecisionState((int)i), (int)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() LexerInterpreter::~LexerInterpreter()

View File

@ -594,7 +594,7 @@ void Parser::setTrace(bool trace) {
} }
void Parser::InitializeInstanceFields() { void Parser::InitializeInstanceFields() {
_errHandler.reset(new DefaultErrorStrategy()); _errHandler = std::make_shared<DefaultErrorStrategy>();
_precedenceStack.clear(); _precedenceStack.clear();
_precedenceStack.push_back(0); _precedenceStack.push_back(0);
_buildParseTrees = true; _buildParseTrees = true;

View File

@ -45,10 +45,12 @@
#include "ATN.h" #include "ATN.h"
#include "RuleStopState.h" #include "RuleStopState.h"
#include "Token.h" #include "Token.h"
#include "CPPUtils.h"
#include "ParserInterpreter.h" #include "ParserInterpreter.h"
using namespace org::antlr::v4::runtime; using namespace org::antlr::v4::runtime;
using namespace antlrcpp;
ParserInterpreter::ParserInterpreter(const std::wstring &grammarFileName, const std::vector<std::wstring>& tokenNames, ParserInterpreter::ParserInterpreter(const std::wstring &grammarFileName, const std::vector<std::wstring>& tokenNames,
const std::vector<std::wstring>& ruleNames, const atn::ATN &atn, TokenStream *input) const std::vector<std::wstring>& 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 // identify the ATN states where pushNewRecursionContext must be called
for (auto state : _atn.states) { for (auto state : _atn.states) {
if (!(dynamic_cast<atn::StarLoopEntryState*>(state) != nullptr)) { if (!is<atn::StarLoopEntryState*>(state)) {
continue; continue;
} }
@ -70,17 +72,17 @@ ParserInterpreter::ParserInterpreter(const std::wstring &grammarFileName, const
} }
atn::ATNState *maybeLoopEndState = state->transition(state->getNumberOfTransitions() - 1)->target; atn::ATNState *maybeLoopEndState = state->transition(state->getNumberOfTransitions() - 1)->target;
if (!(dynamic_cast<atn::LoopEndState*>(maybeLoopEndState) != nullptr)) { if (!is<atn::LoopEndState*>(maybeLoopEndState)) {
continue; continue;
} }
if (maybeLoopEndState->epsilonOnlyTransitions && dynamic_cast<atn::RuleStopState*>(maybeLoopEndState->transition(0)->target) != nullptr) { if (maybeLoopEndState->epsilonOnlyTransitions && is<atn::RuleStopState*>(maybeLoopEndState->transition(0)->target)) {
_pushRecursionContextStates.set((size_t)state->stateNumber); _pushRecursionContextStates.set((size_t)state->stateNumber);
} }
} }
// get atn simulator that knows how to do predictions // 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() { ParserInterpreter::~ParserInterpreter() {
@ -155,7 +157,7 @@ void ParserInterpreter::visitState(atn::ATNState *p) {
atn::Transition *transition = p->transition((size_t)edge - 1); atn::Transition *transition = p->transition((size_t)edge - 1);
switch (transition->getSerializationType()) { switch (transition->getSerializationType()) {
case atn::Transition::EPSILON: case atn::Transition::EPSILON:
if (_pushRecursionContextStates[(size_t)p->stateNumber] == 1 && !(dynamic_cast<atn::LoopEndState*>(transition->target) != nullptr)) { if (_pushRecursionContextStates[(size_t)p->stateNumber] == 1 && is<atn::LoopEndState*>(transition->target)) {
std::shared_ptr<InterpreterRuleContext> ruleContext = std::make_shared<InterpreterRuleContext>(_parentContextStack.top().first, std::shared_ptr<InterpreterRuleContext> ruleContext = std::make_shared<InterpreterRuleContext>(_parentContextStack.top().first,
_parentContextStack.top().second, _ctx->getRuleIndex()); _parentContextStack.top().second, _ctx->getRuleIndex());
pushNewRecursionContext(ruleContext, _atn.ruleToStartState[(size_t)p->ruleIndex]->stateNumber, pushNewRecursionContext(ruleContext, _atn.ruleToStartState[(size_t)p->ruleIndex]->stateNumber,

View File

@ -191,6 +191,8 @@ std::wstring RuleContext::toString(Recognizer *recog) {
} }
std::wstring RuleContext::toString(Recognizer *recog, RuleContext::Ref stop) { std::wstring RuleContext::toString(Recognizer *recog, RuleContext::Ref stop) {
if (recog == nullptr)
return toString({}, stop);
return toString(recog->getRuleNames(), stop); return toString(recog->getRuleNames(), stop);
} }

View File

@ -34,10 +34,12 @@
#include "Token.h" #include "Token.h"
#include "TokenStream.h" #include "TokenStream.h"
#include "Strings.h" #include "Strings.h"
#include "CPPUtils.h"
#include "TokenStreamRewriter.h" #include "TokenStreamRewriter.h"
using namespace org::antlr::v4::runtime; using namespace org::antlr::v4::runtime;
using namespace antlrcpp;
using org::antlr::v4::runtime::misc::Interval; using org::antlr::v4::runtime::misc::Interval;
@ -104,10 +106,20 @@ void TokenStreamRewriter::ReplaceOp::InitializeInstanceFields() {
lastIndex = 0; lastIndex = 0;
} }
//------------------ TokenStreamRewriter -------------------------------------------------------------------------------
const std::wstring TokenStreamRewriter::DEFAULT_PROGRAM_NAME = L"default"; const std::wstring TokenStreamRewriter::DEFAULT_PROGRAM_NAME = L"default";
TokenStreamRewriter::TokenStreamRewriter(TokenStream *tokens) : tokens(tokens), programs(new std::map<std::wstring, std::vector<RewriteOperation*>>()), lastRewriteTokenIndexes(new std::map<std::wstring, int>()) { TokenStreamRewriter::TokenStreamRewriter(TokenStream *tokens) : tokens(tokens) {
programs->insert({ DEFAULT_PROGRAM_NAME, std::vector<RewriteOperation*>(PROGRAM_INIT_SIZE) }); _programs.insert({ DEFAULT_PROGRAM_NAME, std::vector<RewriteOperation*>(PROGRAM_INIT_SIZE) });
}
TokenStreamRewriter::~TokenStreamRewriter() {
for (auto program : _programs) {
for (auto operation : program.second) {
delete operation;
}
}
} }
TokenStream *TokenStreamRewriter::getTokenStream() { TokenStream *TokenStreamRewriter::getTokenStream() {
@ -119,9 +131,9 @@ void TokenStreamRewriter::rollback(int instructionIndex) {
} }
void TokenStreamRewriter::rollback(const std::wstring &programName, int instructionIndex) { void TokenStreamRewriter::rollback(const std::wstring &programName, int instructionIndex) {
std::vector<RewriteOperation*> is = (*programs)[programName]; std::vector<RewriteOperation*> is = _programs[programName];
if (is.size() > 0) { if (is.size() > 0) {
programs->insert({ programName, std::vector<RewriteOperation*>(is.begin() + MIN_TOKEN_INDEX, is.begin() + instructionIndex) }); _programs.insert({ programName, std::vector<RewriteOperation*>(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) { void TokenStreamRewriter::insertBefore(const std::wstring &programName, size_t index, const std::wstring& text) {
RewriteOperation *op = new InsertBeforeOp(this, index, text); RewriteOperation *op = new InsertBeforeOp(this, index, text); /* mem-check: deleted in d-tor */
std::vector<RewriteOperation*> rewrites = getProgram(programName); std::vector<RewriteOperation*> &rewrites = getProgram(programName);
op->instructionIndex = (int)rewrites.size(); op->instructionIndex = (int)rewrites.size();
rewrites.push_back(op); 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) + throw IllegalArgumentException("replace: range invalid: " + std::to_string(from) + ".." + std::to_string(to) +
"(size = " + std::to_string(tokens->size()) + ")"); "(size = " + std::to_string(tokens->size()) + ")");
} }
RewriteOperation *op = new ReplaceOp(this, from, to, text); RewriteOperation *op = new ReplaceOp(this, from, to, text); /* mem-check: deleted in d-tor */
std::vector<RewriteOperation*> rewrites = getProgram(programName); std::vector<RewriteOperation*> &rewrites = getProgram(programName);
op->instructionIndex = (int)rewrites.size(); op->instructionIndex = (int)rewrites.size();
rewrites.push_back(op); rewrites.push_back(op);
} }
@ -229,18 +241,18 @@ int TokenStreamRewriter::getLastRewriteTokenIndex() {
} }
int TokenStreamRewriter::getLastRewriteTokenIndex(const std::wstring &programName) { int TokenStreamRewriter::getLastRewriteTokenIndex(const std::wstring &programName) {
if (lastRewriteTokenIndexes->find(programName) == lastRewriteTokenIndexes->end()) { if (_lastRewriteTokenIndexes.find(programName) == _lastRewriteTokenIndexes.end()) {
return -1; return -1;
} }
return lastRewriteTokenIndexes->at(programName); return _lastRewriteTokenIndexes[programName];
} }
void TokenStreamRewriter::setLastRewriteTokenIndex(const std::wstring &programName, int i) { void TokenStreamRewriter::setLastRewriteTokenIndex(const std::wstring &programName, int i) {
lastRewriteTokenIndexes->insert({ programName, i }); _lastRewriteTokenIndexes.insert({ programName, i });
} }
std::vector<TokenStreamRewriter::RewriteOperation*> TokenStreamRewriter::getProgram(const std::wstring &name) { std::vector<TokenStreamRewriter::RewriteOperation*>& TokenStreamRewriter::getProgram(const std::wstring &name) {
std::vector<TokenStreamRewriter::RewriteOperation*> is = programs->at(name); std::vector<TokenStreamRewriter::RewriteOperation*> &is = _programs[name];
if (is.empty()) { if (is.empty()) {
is = initializeProgram(name); is = initializeProgram(name);
} }
@ -249,7 +261,7 @@ std::vector<TokenStreamRewriter::RewriteOperation*> TokenStreamRewriter::getProg
std::vector<TokenStreamRewriter::RewriteOperation*> TokenStreamRewriter::initializeProgram(const std::wstring &name) { std::vector<TokenStreamRewriter::RewriteOperation*> TokenStreamRewriter::initializeProgram(const std::wstring &name) {
std::vector<TokenStreamRewriter::RewriteOperation*> is(PROGRAM_INIT_SIZE); std::vector<TokenStreamRewriter::RewriteOperation*> is(PROGRAM_INIT_SIZE);
programs->insert({ name, is }); _programs.insert({ name, is });
return 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::wstring TokenStreamRewriter::getText(const std::wstring &programName, const Interval &interval) {
std::vector<TokenStreamRewriter::RewriteOperation*> rewrites = programs->at(programName); std::vector<TokenStreamRewriter::RewriteOperation*> rewrites = _programs.at(programName);
int start = interval.a; int start = interval.a;
int stop = interval.b; int stop = interval.b;
@ -324,7 +336,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
if (op == nullptr) { if (op == nullptr) {
continue; continue;
} }
if (dynamic_cast<ReplaceOp*>(op) == nullptr) { if (!is<ReplaceOp *>(op)) {
continue; continue;
} }
ReplaceOp *rop = static_cast<ReplaceOp*>(op); ReplaceOp *rop = static_cast<ReplaceOp*>(op);
@ -377,7 +389,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
if (op == nullptr) { if (op == nullptr) {
continue; continue;
} }
if (!(dynamic_cast<InsertBeforeOp*>(op) != nullptr)) { if (!is<InsertBeforeOp*>(op)) {
continue; continue;
} }
InsertBeforeOp *iop = static_cast<InsertBeforeOp*>(rewrites[i]); InsertBeforeOp *iop = static_cast<InsertBeforeOp*>(rewrites[i]);

View File

@ -99,94 +99,13 @@ namespace runtime {
/// the first example shows. /// the first example shows.
/// </summary> /// </summary>
class TokenStreamRewriter { class TokenStreamRewriter {
public:
class RewriteOperation {
private:
TokenStreamRewriter *const outerInstance;
public:
/// <summary>
/// What index into rewrites List are we? </summary>
virtual ~RewriteOperation() {};
/// <summary>
/// Token buffer index. </summary>
size_t index;
std::wstring text;
RewriteOperation(TokenStreamRewriter *outerInstance, size_t index);
RewriteOperation(TokenStreamRewriter *outerInstance, size_t index, const std::wstring& text);
/// <summary>
/// Execute the rewrite operation by possibly adding to the buffer.
/// Return the index of the next token to operate on.
/// </summary>
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: public:
static const std::wstring DEFAULT_PROGRAM_NAME; static const std::wstring DEFAULT_PROGRAM_NAME;
static const int PROGRAM_INIT_SIZE = 100; static const int PROGRAM_INIT_SIZE = 100;
static const int MIN_TOKEN_INDEX = 0; static const int MIN_TOKEN_INDEX = 0;
// Define the rewrite operation hierarchy
/// <summary>
/// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp
/// instructions.
/// </summary>
/// <summary>
/// Our source stream </summary>
protected:
TokenStream *const tokens;
/// <summary>
/// You may have multiple, named streams of rewrite operations.
/// I'm calling these things "programs."
/// Maps String (name) -> rewrite (List)
/// </summary>
std::map<std::wstring, std::vector<RewriteOperation*>> * programs;
/// <summary>
/// Map String (program name) -> Integer index </summary>
std::map<std::wstring, int> * lastRewriteTokenIndexes;
public:
TokenStreamRewriter(TokenStream *tokens); TokenStreamRewriter(TokenStream *tokens);
virtual ~TokenStreamRewriter() {}; virtual ~TokenStreamRewriter();
TokenStream *getTokenStream(); TokenStream *getTokenStream();
@ -229,22 +148,9 @@ namespace runtime {
virtual void Delete(const std::wstring &programName, Token *from, Token *to); virtual void Delete(const std::wstring &programName, Token *from, Token *to);
virtual int getLastRewriteTokenIndex(); virtual int getLastRewriteTokenIndex();
protected:
virtual int getLastRewriteTokenIndex(const std::wstring &programName);
virtual void setLastRewriteTokenIndex(const std::wstring &programName, int i);
virtual std::vector<RewriteOperation*> getProgram(const std::wstring &name);
private:
std::vector<RewriteOperation*> initializeProgram(const std::wstring &name);
/// <summary>
/// Return the text from the original tokens altered per the /// Return the text from the original tokens altered per the
/// instructions given to this rewriter. /// instructions given to this rewriter.
/// </summary>
public:
virtual std::wstring getText(); virtual std::wstring getText();
/// <summary> /// <summary>
@ -261,6 +167,77 @@ namespace runtime {
virtual std::wstring getText(const std::wstring &programName, const misc::Interval &interval); virtual std::wstring getText(const std::wstring &programName, const misc::Interval &interval);
protected:
class RewriteOperation {
private:
TokenStreamRewriter *const outerInstance;
public:
/// <summary>
/// What index into rewrites List are we? </summary>
virtual ~RewriteOperation() {};
/// <summary>
/// Token buffer index. </summary>
size_t index;
std::wstring text;
RewriteOperation(TokenStreamRewriter *outerInstance, size_t index);
RewriteOperation(TokenStreamRewriter *outerInstance, size_t index, const std::wstring& text);
/// <summary>
/// Execute the rewrite operation by possibly adding to the buffer.
/// Return the index of the next token to operate on.
/// </summary>
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<std::wstring, std::vector<RewriteOperation*>> _programs;
/// <summary>
/// Map String (program name) -> Integer index </summary>
std::map<std::wstring, int> _lastRewriteTokenIndexes;
virtual int getLastRewriteTokenIndex(const std::wstring &programName);
virtual void setLastRewriteTokenIndex(const std::wstring &programName, int i);
virtual std::vector<RewriteOperation*>& getProgram(const std::wstring &name);
/// <summary> /// <summary>
/// We need to combine operations and report invalid operations (like /// We need to combine operations and report invalid operations (like
/// overlapping replaces that are not completed nested). Inserts to /// overlapping replaces that are not completed nested). Inserts to
@ -311,7 +288,6 @@ namespace runtime {
/// ///
/// Return a map from token index to operation. /// Return a map from token index to operation.
/// </summary> /// </summary>
protected:
virtual std::unordered_map<size_t, RewriteOperation*> reduceToSingleOperationPerIndex(std::vector<RewriteOperation*> rewrites); virtual std::unordered_map<size_t, RewriteOperation*> reduceToSingleOperationPerIndex(std::vector<RewriteOperation*> rewrites);
virtual std::wstring catOpText(std::wstring *a, std::wstring *b); virtual std::wstring catOpText(std::wstring *a, std::wstring *b);
@ -333,6 +309,9 @@ namespace runtime {
return ops; return ops;
} }
private:
std::vector<RewriteOperation*> initializeProgram(const std::wstring &name);
}; };
} // namespace runtime } // namespace runtime

View File

@ -49,9 +49,65 @@ using namespace antlrcpp;
ATN::ATN() : ATN(ATNType::LEXER, 0) { 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(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 { misc::IntervalSet ATN::nextTokens(ATNState *s, RuleContext::Ref ctx) const {
LL1Analyzer analyzer(*this); LL1Analyzer analyzer(*this);
return analyzer.LOOK(s, ctx); return analyzer.LOOK(s, ctx);

View File

@ -45,7 +45,9 @@ namespace atn {
/// Used for runtime deserialization of ATNs from strings. /// Used for runtime deserialization of ATNs from strings.
ATN(); ATN();
ATN(const ATN &other);
ATN(ATNType grammarType, size_t maxTokenType); ATN(ATNType grammarType, size_t maxTokenType);
~ATN();
std::vector<ATNState*> states; std::vector<ATNState*> states;
@ -85,6 +87,9 @@ namespace atn {
std::vector<TokensStartState*> modeToStartState; std::vector<TokensStartState*> modeToStartState;
ATN& operator = (ATN &other) noexcept;
ATN& operator = (ATN &&other) noexcept;
/// <summary> /// <summary>
/// Compute the set of valid tokens that can occur starting in state {@code s}. /// 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 /// If {@code ctx} is null, the set of tokens will not include what can follow

View File

@ -45,25 +45,25 @@ ATNConfig::ATNConfig(ATNState *state, int alt, PredictionContext::Ref context, S
reachesIntoOuterContext = 0; 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(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(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(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) { : state(state), alt(c->alt), context(context), semanticContext(semanticContext), reachesIntoOuterContext(c->reachesIntoOuterContext) {
} }

View File

@ -49,9 +49,10 @@ namespace atn {
/// an ATN state. /// an ATN state.
/// </summary> /// </summary>
class ATNConfig { class ATNConfig {
/// <summary>
/// The ATN state associated with this configuration </summary>
public: public:
typedef std::shared_ptr<ATNConfig> Ref;
/// The ATN state associated with this configuration.
ATNState * state; ATNState * state;
/// <summary> /// <summary>
@ -82,12 +83,12 @@ namespace atn {
ATNConfig(ATNState *state, int alt, PredictionContext::Ref context); ATNConfig(ATNState *state, int alt, PredictionContext::Ref context);
ATNConfig(ATNState *state, int alt, PredictionContext::Ref context, SemanticContext::Ref semanticContext); ATNConfig(ATNState *state, int alt, PredictionContext::Ref context, SemanticContext::Ref semanticContext);
ATNConfig(ATNConfig *c); // dup ATNConfig(ATNConfig::Ref c); // dup
ATNConfig(ATNConfig *c, ATNState *state); ATNConfig(ATNConfig::Ref c, ATNState *state);
ATNConfig(ATNConfig *c, ATNState *state, SemanticContext::Ref semanticContext); ATNConfig(ATNConfig::Ref c, ATNState *state, SemanticContext::Ref semanticContext);
ATNConfig(ATNConfig *c, SemanticContext::Ref semanticContext); ATNConfig(ATNConfig::Ref c, SemanticContext::Ref semanticContext);
ATNConfig(ATNConfig *c, ATNState *state, PredictionContext::Ref context); ATNConfig(ATNConfig::Ref c, ATNState *state, PredictionContext::Ref context);
ATNConfig(ATNConfig *c, ATNState *state, PredictionContext::Ref context, SemanticContext::Ref semanticContext); ATNConfig(ATNConfig::Ref c, ATNState *state, PredictionContext::Ref context, SemanticContext::Ref semanticContext);
virtual size_t hashCode() const; virtual size_t hashCode() const;

View File

@ -38,21 +38,17 @@
using namespace org::antlr::v4::runtime::atn; 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; size_t hashCode = 7;
hashCode = 31 * hashCode + (size_t)k.state->stateNumber; hashCode = 31 * hashCode + (size_t)k->state->stateNumber;
hashCode = 31 * hashCode + (size_t)k.alt; hashCode = 31 * hashCode + (size_t)k->alt;
hashCode = 31 * hashCode + k.semanticContext->hashCode(); hashCode = 31 * hashCode + k->semanticContext->hashCode();
return hashCode; return hashCode;
} }
bool SimpleATNConfigComparer::operator () (const ATNConfig &lhs, const ATNConfig &rhs) const { bool SimpleATNConfigComparer::operator () (const ATNConfig::Ref &lhs, const ATNConfig::Ref &rhs) const {
if (&lhs == &rhs) { // Shortcut: same address = same object. return lhs->state->stateNumber == rhs->state->stateNumber && lhs->alt == rhs->alt &&
return true; lhs->semanticContext == rhs->semanticContext;
}
return lhs.state->stateNumber == rhs.state->stateNumber && lhs.alt == rhs.alt &&
lhs.semanticContext == rhs.semanticContext;
} }
//------------------ ATNConfigSet -------------------------------------------------------------------------------------- //------------------ ATNConfigSet --------------------------------------------------------------------------------------
@ -72,11 +68,11 @@ ATNConfigSet::ATNConfigSet(std::shared_ptr<ATNConfigSet> old) : ATNConfigSet(old
ATNConfigSet::~ATNConfigSet() { ATNConfigSet::~ATNConfigSet() {
} }
bool ATNConfigSet::add(ATNConfig *config) { bool ATNConfigSet::add(ATNConfig::Ref config) {
return add(config, nullptr); return add(config, nullptr);
} }
bool ATNConfigSet::add(ATNConfig *config, PredictionContextMergeCache *mergeCache) { bool ATNConfigSet::add(ATNConfig::Ref config, PredictionContextMergeCache *mergeCache) {
if (_readonly) { if (_readonly) {
throw IllegalStateException("This set is readonly"); throw IllegalStateException("This set is readonly");
} }
@ -87,7 +83,7 @@ bool ATNConfigSet::add(ATNConfig *config, PredictionContextMergeCache *mergeCach
dipsIntoOuterContext = true; dipsIntoOuterContext = true;
} }
ATNConfig *existing = configLookup->getOrAdd(config); ATNConfig::Ref existing = configLookup->getOrAdd(config);
if (existing == config) { // we added this new one if (existing == config) { // we added this new one
_cachedHashCode = 0; _cachedHashCode = 0;
configs.push_back(config); // track order here configs.push_back(config); // track order here
@ -112,14 +108,14 @@ bool ATNConfigSet::addAll(std::shared_ptr<ATNConfigSet> other) {
return false; return false;
} }
std::vector<ATNConfig*> ATNConfigSet::elements() { std::vector<ATNConfig::Ref> ATNConfigSet::elements() {
return configs; return configs;
} }
std::vector<ATNState*>* ATNConfigSet::getStates() { std::vector<ATNState*> ATNConfigSet::getStates() {
std::vector<ATNState*> *states = new std::vector<ATNState*>(); std::vector<ATNState*> states;
for (auto c : configs) { for (auto c : configs) {
states->push_back(c->state); states.push_back(c->state);
} }
return states; return states;
} }
@ -134,7 +130,7 @@ std::vector<SemanticContext::Ref> ATNConfigSet::getPredicates() {
return preds; return preds;
} }
ATNConfig* ATNConfigSet::get(size_t i) const { ATNConfig::Ref ATNConfigSet::get(size_t i) const {
return configs[i]; return configs[i];
} }
@ -182,13 +178,13 @@ bool ATNConfigSet::operator == (const ATNConfigSet &other) {
size_t ATNConfigSet::hashCode() { size_t ATNConfigSet::hashCode() {
if (isReadonly()) { if (isReadonly()) {
if (_cachedHashCode == 0) { if (_cachedHashCode == 0) {
_cachedHashCode = std::hash<std::vector<ATNConfig *>>()(configs); _cachedHashCode = std::hash<std::vector<ATNConfig::Ref>>()(configs);
} }
return _cachedHashCode; return _cachedHashCode;
} }
return std::hash<std::vector<ATNConfig *>>()(configs); return std::hash<std::vector<ATNConfig::Ref>>()(configs);
} }
size_t ATNConfigSet::size() { size_t ATNConfigSet::size() {
@ -199,7 +195,7 @@ bool ATNConfigSet::isEmpty() {
return configs.empty(); return configs.empty();
} }
bool ATNConfigSet::contains(ATNConfig *o) { bool ATNConfigSet::contains(ATNConfig::Ref o) {
if (configLookup == nullptr) { if (configLookup == nullptr) {
throw UnsupportedOperationException("This method is not implemented for readonly sets."); throw UnsupportedOperationException("This method is not implemented for readonly sets.");
} }

View File

@ -44,11 +44,11 @@ namespace atn {
// Simpler hasher and comparer variants than those in ATNConfig (less fields, no murmur hash). // Simpler hasher and comparer variants than those in ATNConfig (less fields, no murmur hash).
struct SimpleATNConfigHasher struct SimpleATNConfigHasher
{ {
size_t operator()(const ATNConfig &k) const; size_t operator()(const ATNConfig::Ref &k) const;
}; };
struct SimpleATNConfigComparer { 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 /// Specialized set that can track info about the set, with support for combining similar configurations using a
@ -61,7 +61,7 @@ namespace atn {
/// <summary> /// <summary>
/// Track the elements as they are added to the set; supports get(i) </summary> /// Track the elements as they are added to the set; supports get(i) </summary>
std::vector<ATNConfig *> configs; std::vector<ATNConfig::Ref> configs;
// TO_DO: these fields make me pretty uncomfortable but nice to pack up info together, saves recomputation // 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? // TO_DO: can we track conflicts as they are added to save scanning configs later?
@ -86,7 +86,7 @@ namespace atn {
virtual ~ATNConfigSet(); virtual ~ATNConfigSet();
virtual bool add(ATNConfig *config); virtual bool add(ATNConfig::Ref config);
/// <summary> /// <summary>
/// Adding a new config means merging contexts with existing configs for /// Adding a new config means merging contexts with existing configs for
@ -98,17 +98,17 @@ namespace atn {
/// This method updates <seealso cref="#dipsIntoOuterContext"/> and /// This method updates <seealso cref="#dipsIntoOuterContext"/> and
/// <seealso cref="#hasSemanticContext"/> when necessary. /// <seealso cref="#hasSemanticContext"/> when necessary.
/// </summary> /// </summary>
virtual bool add(ATNConfig *config, PredictionContextMergeCache *mergeCache); virtual bool add(ATNConfig::Ref config, PredictionContextMergeCache *mergeCache);
/// <summary> /// <summary>
/// Return a List holding list of configs </summary> /// Return a List holding list of configs </summary>
virtual std::vector<ATNConfig*> elements(); virtual std::vector<ATNConfig::Ref> elements();
virtual std::vector<ATNState*> *getStates(); virtual std::vector<ATNState*> getStates();
virtual std::vector<SemanticContext::Ref> getPredicates(); virtual std::vector<SemanticContext::Ref> getPredicates();
virtual ATNConfig *get(size_t i) const; virtual ATNConfig::Ref get(size_t i) const;
virtual void optimizeConfigs(ATNSimulator *interpreter); virtual void optimizeConfigs(ATNSimulator *interpreter);
@ -118,7 +118,7 @@ namespace atn {
virtual size_t hashCode(); virtual size_t hashCode();
virtual size_t size(); virtual size_t size();
virtual bool isEmpty(); virtual bool isEmpty();
virtual bool contains(ATNConfig *o); virtual bool contains(ATNConfig::Ref o);
virtual void clear(); virtual void clear();
virtual bool isReadonly(); virtual bool isReadonly();
virtual void setReadonly(bool readonly); virtual void setReadonly(bool readonly);
@ -146,9 +146,9 @@ namespace atn {
} // namespace org } // namespace org
namespace std { namespace std {
template <> struct hash<std::vector<ATNConfig *>> template <> struct hash<std::vector<ATNConfig::Ref>>
{ {
size_t operator() (const std::vector<ATNConfig *> &vector) const size_t operator() (const std::vector<ATNConfig::Ref > &vector) const
{ {
std::size_t seed = 0; std::size_t seed = 0;
for (auto &config : vector) { for (auto &config : vector) {

View File

@ -294,7 +294,8 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) {
} }
RuleTransition *ruleTransition = static_cast<RuleTransition*>(t); RuleTransition *ruleTransition = static_cast<RuleTransition*>(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 // block end states can only be associated to a single block start state
if (startState->endState->startState != nullptr) { if (startState->endState->startState != nullptr) {
throw IllegalStateException(); throw IllegalStateException();
} }
startState->endState->startState = static_cast<BlockStartState*>(state); startState->endState->startState = static_cast<BlockStartState*>(state);
@ -360,11 +360,11 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) {
} }
for (std::vector<RuleStartState*>::size_type i = 0; i < atn.ruleToStartState.size(); i++) { for (std::vector<RuleStartState*>::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; bypassStart->ruleIndex = (int)i;
atn.addState(bypassStart); atn.addState(bypassStart);
BlockEndState *bypassStop = new BlockEndState(); BlockEndState *bypassStop = new BlockEndState(); /* mem check: freed in ATN d-tor */
bypassStop->ruleIndex = (int)i; bypassStop->ruleIndex = (int)i;
atn.addState(bypassStop); atn.addState(bypassStop);
@ -383,16 +383,16 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) {
continue; continue;
} }
if (!(dynamic_cast<StarLoopEntryState*>(state) != nullptr)) { if (!is<StarLoopEntryState*>(state)) {
continue; continue;
} }
ATNState *maybeLoopEndState = state->transition(state->getNumberOfTransitions() - 1)->target; ATNState *maybeLoopEndState = state->transition(state->getNumberOfTransitions() - 1)->target;
if (!(dynamic_cast<LoopEndState*>(maybeLoopEndState) != nullptr)) { if (!is<LoopEndState*>(maybeLoopEndState)) {
continue; continue;
} }
if (maybeLoopEndState->epsilonOnlyTransitions && dynamic_cast<RuleStopState*>(maybeLoopEndState->transition(0)->target) != nullptr) { if (maybeLoopEndState->epsilonOnlyTransitions && is<RuleStopState*>(maybeLoopEndState->transition(0)->target)) {
endState = state; endState = state;
break; break;
} }
@ -428,13 +428,13 @@ ATN ATNDeserializer::deserialize(const std::wstring& input) {
} }
// link the new states // link the new states
atn.ruleToStartState[i]->addTransition(new EpsilonTransition(bypassStart)); atn.ruleToStartState[i]->addTransition(new EpsilonTransition(bypassStart)); /* mem check: freed in ATNState d-tor */
bypassStop->addTransition(new EpsilonTransition(endState)); 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); atn.addState(matchState);
matchState->addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i])); matchState->addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i])); /* mem check: freed in ATNState d-tor */
bypassStart->addTransition(new EpsilonTransition(matchState)); bypassStart->addTransition(new EpsilonTransition(matchState)); /* mem check: freed in ATNState d-tor */
} }
if (deserializationOptions.isVerifyATN()) { if (deserializationOptions.isVerifyATN()) {
@ -520,6 +520,7 @@ Guid ATNDeserializer::toUUID(const unsigned short *data, int offset) {
return Guid((uint16_t *)data + offset, true); 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, Transition *ATNDeserializer::edgeFactory(const ATN &atn, int type, int src, int trg, int arg1, int arg2, int arg3,
const std::vector<misc::IntervalSet> &sets) { const std::vector<misc::IntervalSet> &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."); 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 *ATNDeserializer::stateFactory(int type, int ruleIndex) {
ATNState *s; ATNState *s;
switch (type) { switch (type) {

View File

@ -53,13 +53,14 @@ namespace atn {
virtual ATN deserialize(const std::wstring &input); virtual ATN deserialize(const std::wstring &input);
virtual void verifyATN(const ATN &atn); 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, static void checkCondition(bool condition);
const std::vector<misc::IntervalSet> &sets); 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<misc::IntervalSet> &sets);
static ATNState *stateFactory(int type, int ruleIndex);
protected: protected:
/// Determines if a particular serialized representation of an ATN supports /// Determines if a particular serialized representation of an ATN supports

View File

@ -92,13 +92,11 @@ std::vector<size_t> ATNSerializer::serialize() {
} }
int stateType = s->getStateType(); int stateType = s->getStateType();
if (dynamic_cast<DecisionState *>(s) != nullptr && if (is<DecisionState *>(s) && (static_cast<DecisionState *>(s))->nonGreedy) {
(static_cast<DecisionState *>(s))->nonGreedy) {
nonGreedyStates.push_back(s->stateNumber); nonGreedyStates.push_back(s->stateNumber);
} }
if (dynamic_cast<RuleStartState *>(s) != nullptr && if (is<RuleStartState *>(s) && (static_cast<RuleStartState *>(s))->isPrecedenceRule) {
(static_cast<RuleStartState *>(s))->isPrecedenceRule) {
precedenceStates.push_back(s->stateNumber); precedenceStates.push_back(s->stateNumber);
} }
@ -114,7 +112,7 @@ std::vector<size_t> ATNSerializer::serialize() {
if (s->getStateType() == ATNState::LOOP_END) { if (s->getStateType() == ATNState::LOOP_END) {
data.push_back((size_t)(static_cast<LoopEndState *>(s))->loopBackState->stateNumber); data.push_back((size_t)(static_cast<LoopEndState *>(s))->loopBackState->stateNumber);
} }
else if (dynamic_cast<BlockStartState *>(s) != nullptr) { else if (is<BlockStartState *>(s)) {
data.push_back((size_t)(static_cast<BlockStartState *>(s))->endState->stateNumber); data.push_back((size_t)(static_cast<BlockStartState *>(s))->endState->stateNumber);
} }
@ -323,6 +321,9 @@ std::vector<size_t> ATNSerializer::serialize() {
//------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------
std::wstring ATNSerializer::decode(const std::wstring &inpdata) { std::wstring ATNSerializer::decode(const std::wstring &inpdata) {
if (inpdata.size() < 10)
throw IllegalArgumentException("Not enough data to decode");
uint16_t data[inpdata.size()]; uint16_t data[inpdata.size()];
data[0] = inpdata[0]; data[0] = inpdata[0];

View File

@ -62,18 +62,18 @@ ATN ATNSimulator::deserialize(const std::wstring &data) {
} }
void ATNSimulator::checkCondition(bool condition) { void ATNSimulator::checkCondition(bool condition) {
(new ATNDeserializer())->checkCondition(condition); ATNDeserializer::checkCondition(condition);
} }
void ATNSimulator::checkCondition(bool condition, const std::string &message) { 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, Transition *ATNSimulator::edgeFactory(const ATN &atn, int type, int src, int trg, int arg1, int arg2, int arg3,
const std::vector<misc::IntervalSet> &sets) { const std::vector<misc::IntervalSet> &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) { ATNState *ATNSimulator::stateFactory(int type, int ruleIndex) {
return (new ATNDeserializer())->stateFactory(type, ruleIndex); return ATNDeserializer::stateFactory(type, ruleIndex);
} }

View File

@ -29,6 +29,8 @@
#pragma once #pragma once
#include "ATNConfig.h"
namespace org { namespace org {
namespace antlr { namespace antlr {
namespace v4 { namespace v4 {
@ -46,7 +48,7 @@ namespace atn {
ConfigLookupIterator& operator++ () { ++*_iterator; return *this; }; ConfigLookupIterator& operator++ () { ++*_iterator; return *this; };
bool operator != (const ConfigLookupIterator& rhs) const { return *_iterator != *rhs._iterator; }; bool operator != (const ConfigLookupIterator& rhs) const { return *_iterator != *rhs._iterator; };
ATNConfig* operator* () const { return **_iterator; }; ATNConfig::Ref operator * () const { return **_iterator; };
private: private:
std::shared_ptr<ConfigLookupIteratorImpl> _iterator; std::shared_ptr<ConfigLookupIteratorImpl> _iterator;
}; };
@ -54,9 +56,9 @@ namespace atn {
virtual ~ConfigLookup() {} virtual ~ConfigLookup() {}
// Java iterator interface. // Java iterator interface.
virtual ATNConfig* getOrAdd(ATNConfig *config) = 0; virtual ATNConfig::Ref getOrAdd(ATNConfig::Ref config) = 0;
virtual bool isEmpty() const = 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; virtual void clear() = 0;
// STL iterator interface. // STL iterator interface.
@ -69,18 +71,18 @@ namespace atn {
public: public:
virtual ConfigLookupIteratorImpl& operator ++ () = 0; virtual ConfigLookupIteratorImpl& operator ++ () = 0;
virtual bool operator != (const ConfigLookupIteratorImpl&) const = 0; virtual bool operator != (const ConfigLookupIteratorImpl&) const = 0;
virtual ATNConfig* operator * () const = 0; virtual ATNConfig::Ref operator * () const = 0;
virtual void* underlyingIterator () = 0; virtual void* underlyingIterator () = 0;
virtual const void* underlyingIterator () const = 0; virtual const void* underlyingIterator () const = 0;
}; };
}; };
template <typename Hasher, typename Comparer> template <typename Hasher, typename Comparer>
class ConfigLookupImpl: public ConfigLookup, std::unordered_set<ATNConfig*, Hasher, Comparer> { class ConfigLookupImpl: public ConfigLookup, std::unordered_set<ATNConfig::Ref, Hasher, Comparer> {
public: public:
using Set = std::unordered_set<ATNConfig*, Hasher, Comparer>; using Set = std::unordered_set<ATNConfig::Ref, Hasher, Comparer>;
virtual ATNConfig* getOrAdd(ATNConfig *config) override { virtual ATNConfig::Ref getOrAdd(ATNConfig::Ref config) override {
auto result = Set::find(config); auto result = Set::find(config);
if (result != Set::end()) if (result != Set::end())
// Can potentially be a different config instance which however is considered equal to the given config // 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(); return Set::empty();
} }
virtual bool contains(ATNConfig *config) const override { virtual bool contains(ATNConfig::Ref config) const override {
return Set::count(config) > 0; return Set::count(config) > 0;
} }
@ -108,17 +110,21 @@ namespace atn {
} }
ConfigLookupIterator begin() override { ConfigLookupIterator begin() override {
return ConfigLookupIterator(new ConfigLookupImpl<Hasher, Comparer>::ConfigLookupIteratorImpl(std::unordered_set<ATNConfig*, Hasher, Comparer>::begin())); return ConfigLookupIterator(
new ConfigLookupImpl<Hasher, Comparer>::ConfigLookupIteratorImpl(
std::unordered_set<ATNConfig::Ref, Hasher, Comparer>::begin())); /* mem check: managed by shared_ptr in the iterator */
} }
ConfigLookupIterator end() override { ConfigLookupIterator end() override {
return ConfigLookupIterator(new ConfigLookupImpl<Hasher, Comparer>::ConfigLookupIteratorImpl(std::unordered_set<ATNConfig*, Hasher, Comparer>::end())); return ConfigLookupIterator(
new ConfigLookupImpl<Hasher, Comparer>::ConfigLookupIteratorImpl(
std::unordered_set<ATNConfig::Ref, Hasher, Comparer>::end())); /* mem check: managed by shared_ptr in the iterator */
} }
protected: protected:
class ConfigLookupIteratorImpl : public ConfigLookup::ConfigLookupIteratorImpl { class ConfigLookupIteratorImpl : public ConfigLookup::ConfigLookupIteratorImpl {
public: public:
using UnderlyingIterator = typename std::unordered_set<ATNConfig*, Hasher, Comparer>::iterator; using UnderlyingIterator = typename std::unordered_set<ATNConfig::Ref, Hasher, Comparer>::iterator;
ConfigLookupIteratorImpl(UnderlyingIterator&& iterator) : _iterator(std::move(iterator)) { ConfigLookupIteratorImpl(UnderlyingIterator&& iterator) : _iterator(std::move(iterator)) {
} }
@ -131,7 +137,7 @@ namespace atn {
return *reinterpret_cast<const UnderlyingIterator*>(underlyingIterator()) != *reinterpret_cast<const UnderlyingIterator*>(rhs.underlyingIterator()); return *reinterpret_cast<const UnderlyingIterator*>(underlyingIterator()) != *reinterpret_cast<const UnderlyingIterator*>(rhs.underlyingIterator());
} }
ATNConfig* operator* () const override { ATNConfig::Ref operator * () const override {
return *_iterator; return *_iterator;
} }

View File

@ -60,7 +60,7 @@ std::vector<misc::IntervalSet> LL1Analyzer::getDecisionLookahead(ATNState *s) co
for (size_t alt = 0; alt < s->getNumberOfTransitions(); alt++) { for (size_t alt = 0; alt < s->getNumberOfTransitions(); alt++) {
bool seeThruPreds = false; // fail to get lookahead upon pred bool seeThruPreds = false; // fail to get lookahead upon pred
std::set<ATNConfig*> lookBusy; std::unordered_set<ATNConfig::Ref> lookBusy;
antlrcpp::BitSet callRuleStack; antlrcpp::BitSet callRuleStack;
_LOOK(s->transition(alt)->target, nullptr, PredictionContext::EMPTY, _LOOK(s->transition(alt)->target, nullptr, PredictionContext::EMPTY,
look[alt], lookBusy, callRuleStack, seeThruPreds, false); 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 bool seeThruPreds = true; // ignore preds; get all lookahead
PredictionContext::Ref lookContext = ctx != nullptr ? PredictionContext::fromRuleContext(_atn, ctx) : nullptr; PredictionContext::Ref lookContext = ctx != nullptr ? PredictionContext::fromRuleContext(_atn, ctx) : nullptr;
std::set<ATNConfig*> lookBusy; std::unordered_set<ATNConfig::Ref> lookBusy;
antlrcpp::BitSet callRuleStack; antlrcpp::BitSet callRuleStack;
_LOOK(s, stopState, lookContext, r, lookBusy, callRuleStack, seeThruPreds, true); _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, void LL1Analyzer::_LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref ctx, misc::IntervalSet &look,
std::set<ATNConfig*> &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const { std::unordered_set<ATNConfig::Ref> &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const {
ATNConfig *c = new ATNConfig(s, 0, ctx); ATNConfig::Ref c = std::make_shared<ATNConfig>(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; return;
}
lookBusy.insert(c);
if (s == stopState) { if (s == stopState) {
if (ctx == nullptr) { if (ctx == nullptr) {
@ -108,7 +109,7 @@ void LL1Analyzer::_LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref
} }
} }
if (dynamic_cast<RuleStopState*>(s) != nullptr) { if (is<RuleStopState*>(s)) {
if (ctx == nullptr) { if (ctx == nullptr) {
look.add(Token::EPSILON); look.add(Token::EPSILON);
return; return;

View File

@ -34,6 +34,7 @@
#include "Token.h" #include "Token.h"
#include "BitSet.h" #include "BitSet.h"
#include "PredictionContext.h" #include "PredictionContext.h"
#include "ATNConfig.h"
namespace org { namespace org {
namespace antlr { namespace antlr {
@ -131,7 +132,7 @@ namespace atn {
/// is {@code null}. </param> /// is {@code null}. </param>
protected: protected:
virtual void _LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref ctx, misc::IntervalSet &look, virtual void _LOOK(ATNState *s, ATNState *stopState, PredictionContext::Ref ctx, misc::IntervalSet &look,
std::set<ATNConfig*> &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const; std::unordered_set<ATNConfig::Ref> &lookBusy, antlrcpp::BitSet &calledRuleStack, bool seeThruPreds, bool addEOF) const;
}; };
} // namespace atn } // namespace atn

View File

@ -29,13 +29,16 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "LexerATNConfig.h"
#include "MurmurHash.h" #include "MurmurHash.h"
#include "DecisionState.h" #include "DecisionState.h"
#include "PredictionContext.h" #include "PredictionContext.h"
#include "SemanticContext.h" #include "SemanticContext.h"
#include "CPPUtils.h"
#include "LexerATNConfig.h"
using namespace org::antlr::v4::runtime::atn; using namespace org::antlr::v4::runtime::atn;
using namespace antlrcpp;
LexerATNConfig::LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context) LexerATNConfig::LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context)
: ATNConfig(state, alt, context, SemanticContext::NONE), passedThroughNonGreedyDecision(false) { : ATNConfig(state, alt, context, SemanticContext::NONE), passedThroughNonGreedyDecision(false) {
@ -46,17 +49,17 @@ LexerATNConfig::LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref
lexerActionIndex = actionIndex; 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)) { : ATNConfig(c, state, c->context, c->semanticContext), passedThroughNonGreedyDecision(checkNonGreedyDecision(c, state)) {
lexerActionIndex = c->lexerActionIndex; 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)) { : ATNConfig(c, state, c->context, c->semanticContext), passedThroughNonGreedyDecision(checkNonGreedyDecision(c, state)) {
lexerActionIndex = actionIndex; 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)) { : ATNConfig(c, state, context, c->semanticContext), passedThroughNonGreedyDecision(checkNonGreedyDecision(c, state)) {
lexerActionIndex = c->lexerActionIndex; lexerActionIndex = c->lexerActionIndex;
} }
@ -84,7 +87,7 @@ bool LexerATNConfig::operator == (const LexerATNConfig& other) const
return ATNConfig::operator == (other); return ATNConfig::operator == (other);
} }
bool LexerATNConfig::checkNonGreedyDecision(LexerATNConfig *source, ATNState *target) { bool LexerATNConfig::checkNonGreedyDecision(LexerATNConfig::Ref source, ATNState *target) {
return source->passedThroughNonGreedyDecision || return source->passedThroughNonGreedyDecision ||
(dynamic_cast<DecisionState*>(target) != nullptr && (static_cast<DecisionState*>(target))->nonGreedy); (is<DecisionState*>(target) && (static_cast<DecisionState*>(target))->nonGreedy);
} }

View File

@ -41,15 +41,17 @@ namespace atn {
class LexerATNConfig : public ATNConfig { class LexerATNConfig : public ATNConfig {
public: public:
typedef std::shared_ptr<LexerATNConfig> Ref;
/// Capture lexer action we traverse. /// Capture lexer action we traverse.
int lexerActionIndex = -1; int lexerActionIndex = -1;
LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context); LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context);
LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context, int actionIndex); LexerATNConfig(ATNState *state, int alt, PredictionContext::Ref context, int actionIndex);
LexerATNConfig(LexerATNConfig *c, ATNState *state); LexerATNConfig(LexerATNConfig::Ref c, ATNState *state);
LexerATNConfig(LexerATNConfig *c, ATNState *state, int actionIndex); LexerATNConfig(LexerATNConfig::Ref c, ATNState *state, int actionIndex);
LexerATNConfig(LexerATNConfig *c, ATNState *state, PredictionContext::Ref context); LexerATNConfig(LexerATNConfig::Ref c, ATNState *state, PredictionContext::Ref context);
bool hasPassedThroughNonGreedyDecision(); bool hasPassedThroughNonGreedyDecision();
@ -60,7 +62,7 @@ namespace atn {
private: private:
const bool passedThroughNonGreedyDecision; const bool passedThroughNonGreedyDecision;
static bool checkNonGreedyDecision(LexerATNConfig *source, ATNState *target); static bool checkNonGreedyDecision(LexerATNConfig::Ref source, ATNState *target);
}; };
} // namespace atn } // namespace atn

View File

@ -75,7 +75,7 @@ LexerATNSimulator::LexerATNSimulator(const ATN &atn, std::vector<dfa::DFA> &deci
LexerATNSimulator::LexerATNSimulator(Lexer *recog, const ATN &atn, std::vector<dfa::DFA> &decisionToDFA, LexerATNSimulator::LexerATNSimulator(Lexer *recog, const ATN &atn, std::vector<dfa::DFA> &decisionToDFA,
std::shared_ptr<PredictionContextCache> sharedContextCache) std::shared_ptr<PredictionContextCache> sharedContextCache)
: ATNSimulator(atn, sharedContextCache), _recog(recog), _decisionToDFA(decisionToDFA), prevAccept(new SimState()) { : ATNSimulator(atn, sharedContextCache), _recog(recog), _decisionToDFA(decisionToDFA) {
InitializeInstanceFields(); InitializeInstanceFields();
} }
@ -96,7 +96,7 @@ int LexerATNSimulator::match(CharStream *input, size_t mode) {
}); });
_startIndex = (int)input->index(); _startIndex = (int)input->index();
prevAccept->reset(); prevAccept.reset();
const dfa::DFA &dfa = _decisionToDFA[mode]; const dfa::DFA &dfa = _decisionToDFA[mode];
if (dfa.s0 == nullptr) { if (dfa.s0 == nullptr) {
return matchATN(input); return matchATN(input);
@ -108,9 +108,9 @@ int LexerATNSimulator::match(CharStream *input, size_t mode) {
} }
void LexerATNSimulator::reset() { void LexerATNSimulator::reset() {
prevAccept->reset(); prevAccept.reset();
_startIndex = 0; // Originally -1, but that would require a signed type with many casts. _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; _line = 1;
_charPositionInLine = 0; _charPositionInLine = 0;
_mode = Lexer::DEFAULT_MODE; _mode = Lexer::DEFAULT_MODE;
@ -184,7 +184,7 @@ int LexerATNSimulator::execATN(CharStream *input, dfa::DFAState *ds0) {
} }
if (target->isAcceptState) { if (target->isAcceptState) {
captureSimState(prevAccept, input, target); captureSimState(input, target);
if (t == EOF) { if (t == EOF) {
break; break;
} }
@ -198,7 +198,7 @@ int LexerATNSimulator::execATN(CharStream *input, dfa::DFAState *ds0) {
s = target; // flip; current DFA target becomes new src/from state 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) { 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); return addDFAEdge(s, t, reach);
} }
int LexerATNSimulator::failOrAccept(SimState *prevAccept, CharStream *input, std::shared_ptr<ATNConfigSet> reach, ssize_t t) { int LexerATNSimulator::failOrAccept(CharStream *input, std::shared_ptr<ATNConfigSet> reach, ssize_t t) {
if (prevAccept->dfaState != nullptr) { if (prevAccept.dfaState != nullptr) {
int ruleIndex = prevAccept->dfaState->lexerRuleIndex; int ruleIndex = prevAccept.dfaState->lexerRuleIndex;
int actionIndex = prevAccept->dfaState->lexerActionIndex; int actionIndex = prevAccept.dfaState->lexerActionIndex;
accept(input, ruleIndex, actionIndex, (size_t)prevAccept->index, prevAccept->line, (size_t)prevAccept->charPos); accept(input, ruleIndex, actionIndex, (size_t)prevAccept.index, prevAccept.line, (size_t)prevAccept.charPos);
return prevAccept->dfaState->prediction; return prevAccept.dfaState->prediction;
} else { } else {
// if no accept and EOF is first char, return EOF // if no accept and EOF is first char, return EOF
if (t == EOF && input->index() == (size_t)_startIndex) { 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) { for (auto c : closure->configs) {
bool currentAltReachedAcceptState = c->alt == skipAlt; bool currentAltReachedAcceptState = c->alt == skipAlt;
if (currentAltReachedAcceptState && (static_cast<LexerATNConfig*>(c))->hasPassedThroughNonGreedyDecision()) { if (currentAltReachedAcceptState && (std::static_pointer_cast<LexerATNConfig>(c))->hasPassedThroughNonGreedyDecision()) {
continue; continue;
} }
@ -270,7 +270,8 @@ void LexerATNSimulator::getReachableConfigSet(CharStream *input, std::shared_ptr
Transition *trans = c->state->transition(ti); Transition *trans = c->state->transition(ti);
ATNState *target = getReachableTarget(trans, (int)t); ATNState *target = getReachableTarget(trans, (int)t);
if (target != nullptr) { if (target != nullptr) {
if (this->closure(input, new LexerATNConfig(static_cast<LexerATNConfig*>(c), target), reach, currentAltReachedAcceptState, true)) { if (this->closure(input, std::make_shared<LexerATNConfig>(std::static_pointer_cast<LexerATNConfig>(c), target),
reach, currentAltReachedAcceptState, true)) {
// any remaining configs for this alt have a lower priority than // any remaining configs for this alt have a lower priority than
// the one that just reached an accept state. // the one that just reached an accept state.
skipAlt = c->alt; skipAlt = c->alt;
@ -318,13 +319,13 @@ std::shared_ptr<ATNConfigSet> LexerATNSimulator::computeStartState(CharStream *i
std::shared_ptr<ATNConfigSet> configs = std::make_shared<OrderedATNConfigSet>(); std::shared_ptr<ATNConfigSet> configs = std::make_shared<OrderedATNConfigSet>();
for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { for (size_t i = 0; i < p->getNumberOfTransitions(); i++) {
ATNState *target = p->transition(i)->target; ATNState *target = p->transition(i)->target;
LexerATNConfig *c = new LexerATNConfig(target, (int)(i + 1), initialContext); LexerATNConfig::Ref c = std::make_shared<LexerATNConfig>(target, (int)(i + 1), initialContext);
closure(input, c, configs, false, false); closure(input, c, configs, false, false);
} }
return configs; return configs;
} }
bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std::shared_ptr<ATNConfigSet> configs, bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs,
bool currentAltReachedAcceptState, bool speculative) { bool currentAltReachedAcceptState, bool speculative) {
if (debug) { if (debug) {
std::wcout << L"closure(" << config->toString(true) << L")" << std::endl; 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); configs->add(config);
return true; return true;
} else { } else {
configs->add(new LexerATNConfig(config, config->state, PredictionContext::EMPTY)); configs->add(std::make_shared<LexerATNConfig>(config, config->state, PredictionContext::EMPTY));
currentAltReachedAcceptState = true; currentAltReachedAcceptState = true;
} }
} }
@ -354,7 +355,7 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std::
if (config->context->getReturnState(i) != PredictionContext::EMPTY_RETURN_STATE) { if (config->context->getReturnState(i) != PredictionContext::EMPTY_RETURN_STATE) {
std::weak_ptr<PredictionContext> newContext = config->context->getParent(i); // "pop" return state std::weak_ptr<PredictionContext> newContext = config->context->getParent(i); // "pop" return state
ATNState *returnState = atn.states[(size_t)config->context->getReturnState(i)]; 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<LexerATNConfig>(returnState, config->alt, newContext.lock());
currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative); currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative);
} }
} }
@ -373,7 +374,7 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std::
ATNState *p = config->state; ATNState *p = config->state;
for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { for (size_t i = 0; i < p->getNumberOfTransitions(); i++) {
Transition *t = p->transition(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) { if (c != nullptr) {
currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative); currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative);
} }
@ -382,14 +383,14 @@ bool LexerATNSimulator::closure(CharStream *input, LexerATNConfig *config, std::
return currentAltReachedAcceptState; return currentAltReachedAcceptState;
} }
atn::LexerATNConfig *LexerATNSimulator::getEpsilonTarget(CharStream *input, LexerATNConfig *config, Transition *t, LexerATNConfig::Ref LexerATNSimulator::getEpsilonTarget(CharStream *input, LexerATNConfig::Ref config, Transition *t,
std::shared_ptr<ATNConfigSet> configs, bool speculative) { std::shared_ptr<ATNConfigSet> configs, bool speculative) {
LexerATNConfig *c = nullptr; LexerATNConfig::Ref c = nullptr;
switch (t->getSerializationType()) { switch (t->getSerializationType()) {
case Transition::RULE: { case Transition::RULE: {
RuleTransition *ruleTransition = static_cast<RuleTransition*>(t); RuleTransition *ruleTransition = static_cast<RuleTransition*>(t);
PredictionContext::Ref newContext = SingletonPredictionContext::create(config->context, ruleTransition->followState->stateNumber); PredictionContext::Ref newContext = SingletonPredictionContext::create(config->context, ruleTransition->followState->stateNumber);
c = new LexerATNConfig(config, t->target, newContext); c = std::make_shared<LexerATNConfig>(config, t->target, newContext);
} }
break; break;
@ -421,16 +422,16 @@ atn::LexerATNConfig *LexerATNSimulator::getEpsilonTarget(CharStream *input, Lexe
} }
configs->hasSemanticContext = true; configs->hasSemanticContext = true;
if (evaluatePredicate(input, pt->ruleIndex, pt->predIndex, speculative)) { if (evaluatePredicate(input, pt->ruleIndex, pt->predIndex, speculative)) {
c = new LexerATNConfig(config, t->target); c = std::make_shared<LexerATNConfig>(config, t->target);
} }
} }
break; break;
// ignore actions; just exec one per rule upon accept // ignore actions; just exec one per rule upon accept
case Transition::ACTION: case Transition::ACTION:
c = new LexerATNConfig(config, t->target, (static_cast<ActionTransition*>(t))->actionIndex); c = std::make_shared<LexerATNConfig>(config, t->target, (static_cast<ActionTransition*>(t))->actionIndex);
break; break;
case Transition::EPSILON: case Transition::EPSILON:
c = new LexerATNConfig(config, t->target); c = std::make_shared<LexerATNConfig>(config, t->target);
break; break;
} }
@ -463,11 +464,11 @@ bool LexerATNSimulator::evaluatePredicate(CharStream *input, int ruleIndex, int
return _recog->sempred(nullptr, ruleIndex, predIndex); return _recog->sempred(nullptr, ruleIndex, predIndex);
} }
void LexerATNSimulator::captureSimState(SimState *settings, CharStream *input, dfa::DFAState *dfaState) { void LexerATNSimulator::captureSimState(CharStream *input, dfa::DFAState *dfaState) {
settings->index = (int)input->index(); prevAccept.index = (int)input->index();
settings->line = _line; prevAccept.line = _line;
settings->charPos = _charPositionInLine; prevAccept.charPos = _charPositionInLine;
settings->dfaState = dfaState; prevAccept.dfaState = dfaState;
} }
dfa::DFAState *LexerATNSimulator::addDFAEdge(dfa::DFAState *from, ssize_t t, std::shared_ptr<ATNConfigSet> q) { dfa::DFAState *LexerATNSimulator::addDFAEdge(dfa::DFAState *from, ssize_t t, std::shared_ptr<ATNConfigSet> q) {
@ -519,8 +520,8 @@ dfa::DFAState *LexerATNSimulator::addDFAState(std::shared_ptr<ATNConfigSet> conf
*/ */
assert(!configs->hasSemanticContext); assert(!configs->hasSemanticContext);
dfa::DFAState *proposed = new dfa::DFAState(configs); dfa::DFAState *proposed = new dfa::DFAState(configs); /* mem-check: managed by the DFA or deleted below */
ATNConfig *firstConfigWithRuleStopState = nullptr; ATNConfig::Ref firstConfigWithRuleStopState = nullptr;
for (auto c : configs->configs) { for (auto c : configs->configs) {
if (is<RuleStopState*>(c->state)) { if (is<RuleStopState*>(c->state)) {
firstConfigWithRuleStopState = c; firstConfigWithRuleStopState = c;
@ -531,7 +532,7 @@ dfa::DFAState *LexerATNSimulator::addDFAState(std::shared_ptr<ATNConfigSet> conf
if (firstConfigWithRuleStopState != nullptr) { if (firstConfigWithRuleStopState != nullptr) {
proposed->isAcceptState = true; proposed->isAcceptState = true;
proposed->lexerRuleIndex = firstConfigWithRuleStopState->state->ruleIndex; proposed->lexerRuleIndex = firstConfigWithRuleStopState->state->ruleIndex;
proposed->lexerActionIndex = (static_cast<LexerATNConfig*>(firstConfigWithRuleStopState))->lexerActionIndex; proposed->lexerActionIndex = (std::static_pointer_cast<LexerATNConfig>(firstConfigWithRuleStopState))->lexerActionIndex;
proposed->prediction = atn.ruleToTokenType[(size_t)proposed->lexerRuleIndex]; proposed->prediction = atn.ruleToTokenType[(size_t)proposed->lexerRuleIndex];
} }
@ -542,6 +543,7 @@ dfa::DFAState *LexerATNSimulator::addDFAState(std::shared_ptr<ATNConfigSet> conf
auto iterator = dfa.states.find(proposed); auto iterator = dfa.states.find(proposed);
if (iterator != dfa.states.end()) { if (iterator != dfa.states.end()) {
delete proposed;
return iterator->second; return iterator->second;
} }

View File

@ -32,6 +32,7 @@
#pragma once #pragma once
#include "ATNSimulator.h" #include "ATNSimulator.h"
#include "LexerATNConfig.h"
namespace org { namespace org {
namespace antlr { namespace antlr {
@ -110,7 +111,7 @@ namespace atn {
/// <summary> /// <summary>
/// Used during DFA/ATN exec to record the most recent accept configuration info </summary> /// Used during DFA/ATN exec to record the most recent accept configuration info </summary>
SimState *const prevAccept; SimState prevAccept;
public: public:
static int match_calls; static int match_calls;
@ -153,7 +154,7 @@ namespace atn {
/// returns <seealso cref="#ERROR"/>. </returns> /// returns <seealso cref="#ERROR"/>. </returns>
virtual dfa::DFAState *computeTargetState(CharStream *input, dfa::DFAState *s, ssize_t t); virtual dfa::DFAState *computeTargetState(CharStream *input, dfa::DFAState *s, ssize_t t);
virtual int failOrAccept(SimState *prevAccept, CharStream *input, std::shared_ptr<ATNConfigSet> reach, ssize_t t); virtual int failOrAccept(CharStream *input, std::shared_ptr<ATNConfigSet> reach, ssize_t t);
/// <summary> /// <summary>
/// Given a starting configuration set, figure out all ATN configurations /// Given a starting configuration set, figure out all ATN configurations
@ -177,12 +178,12 @@ namespace atn {
/// </summary> /// </summary>
/// <returns> {@code true} if an accept state is reached, otherwise /// <returns> {@code true} if an accept state is reached, otherwise
/// {@code false}. </returns> /// {@code false}. </returns>
virtual bool closure(CharStream *input, LexerATNConfig *config, std::shared_ptr<ATNConfigSet> configs, virtual bool closure(CharStream *input, LexerATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs,
bool currentAltReachedAcceptState, bool speculative); bool currentAltReachedAcceptState, bool speculative);
// side-effect: can alter configs.hasSemanticContext // side-effect: can alter configs.hasSemanticContext
virtual LexerATNConfig *getEpsilonTarget(CharStream *input, LexerATNConfig *config, Transition *t, virtual LexerATNConfig::Ref getEpsilonTarget(CharStream *input, LexerATNConfig::Ref config, Transition *t,
std::shared_ptr<ATNConfigSet> configs, bool speculative); std::shared_ptr<ATNConfigSet> configs, bool speculative);
/// <summary> /// <summary>
/// Evaluate a predicate specified in the lexer. /// Evaluate a predicate specified in the lexer.
@ -206,7 +207,7 @@ namespace atn {
/// {@code true}. </returns> /// {@code true}. </returns>
virtual bool evaluatePredicate(CharStream *input, int ruleIndex, int predIndex, bool speculative); 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<ATNConfigSet> q); virtual dfa::DFAState *addDFAEdge(dfa::DFAState *from, ssize_t t, std::shared_ptr<ATNConfigSet> q);
virtual void addDFAEdge(dfa::DFAState *p, ssize_t t, dfa::DFAState *q); virtual void addDFAEdge(dfa::DFAState *p, ssize_t t, dfa::DFAState *q);

View File

@ -34,5 +34,6 @@
using namespace org::antlr::v4::runtime::atn; using namespace org::antlr::v4::runtime::atn;
OrderedATNConfigSet::OrderedATNConfigSet() : ATNConfigSet() { OrderedATNConfigSet::OrderedATNConfigSet() : ATNConfigSet() {
configLookup = std::shared_ptr<ConfigLookup>(new ConfigLookupImpl<OrderedATNConfigHasher, OrderedATNConfigComparer>()); configLookup = std::shared_ptr<ConfigLookup>(
new ConfigLookupImpl<OrderedATNConfigHasher, OrderedATNConfigComparer>()); /* mem-check: managed by shared_ptr in ConfigLookupImpl */
} }

View File

@ -41,18 +41,14 @@ namespace atn {
struct OrderedATNConfigHasher struct OrderedATNConfigHasher
{ {
size_t operator()(const ATNConfig &config) const { size_t operator()(const ATNConfig::Ref &config) const {
return std::hash<ATNConfig>()(config); return std::hash<ATNConfig::Ref>()(config);
} }
}; };
struct OrderedATNConfigComparer { 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; return lhs == rhs;
} }
}; };

View File

@ -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; std::wcout << L"predictATN decision " << dfa.decision << L" exec LA(1)==" << getLookaheadName(input) << L", outerContext=" << outerContext->toString(parser) << std::endl;
} }
bool fullCtx = false; bool fullCtx = false;
std::shared_ptr<ATNConfigSet> s0_closure = computeStartState(dynamic_cast<ATNState*>(dfa.atnStartState), std::shared_ptr<ATNConfigSet> s0_closure = computeStartState(dynamic_cast<ATNState *>(dfa.atnStartState),
ParserRuleContext::EMPTY, fullCtx); 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. // 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 // 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); 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 // all adds to dfa are done after we've created full D state
D = addDFAEdge(dfa, previousD, t, D); dfa::DFAState *state = addDFAEdge(dfa, previousD, t, D);
return 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) { void ParserATNSimulator::predicateDFAState(dfa::DFAState *dfaState, DecisionState *decisionState) {
@ -435,7 +442,7 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::computeReachSet(std::shared_pt
* ensure that the alternative matching the longest overall sequence is * ensure that the alternative matching the longest overall sequence is
* chosen when multiple such configurations can match the input. * chosen when multiple such configurations can match the input.
*/ */
std::vector<ATNConfig*> skippedStopStates; std::vector<ATNConfig::Ref> skippedStopStates;
// First figure out where we can reach on input t // First figure out where we can reach on input t
for (auto c : closure->configs) { for (auto c : closure->configs) {
@ -447,10 +454,6 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::computeReachSet(std::shared_pt
assert(c->context->isEmpty()); assert(c->context->isEmpty());
if (fullCtx || t == EOF) { if (fullCtx || t == EOF) {
if (skippedStopStates.empty()) {
skippedStopStates = std::vector<ATNConfig*>();
}
skippedStopStates.push_back(c); skippedStopStates.push_back(c);
} }
@ -462,7 +465,7 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::computeReachSet(std::shared_pt
Transition *trans = c->state->transition(ti); Transition *trans = c->state->transition(ti);
ATNState *target = getReachableTarget(trans, (int)t); ATNState *target = getReachableTarget(trans, (int)t);
if (target != nullptr) { if (target != nullptr) {
intermediate->add(new ATNConfig(c, target), &mergeCache); intermediate->add(std::make_shared<ATNConfig>(c, target), &mergeCache);
} }
} }
} }
@ -498,7 +501,7 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::computeReachSet(std::shared_pt
*/ */
if (reach == nullptr) { if (reach == nullptr) {
reach = std::make_shared<ATNConfigSet>(fullCtx); reach = std::make_shared<ATNConfigSet>(fullCtx);
std::set<ATNConfig*> closureBusy; std::set<ATNConfig::Ref> closureBusy;
for (auto c : intermediate->configs) { for (auto c : intermediate->configs) {
this->closure(c, reach, closureBusy, false, fullCtx); this->closure(c, reach, closureBusy, false, fullCtx);
@ -557,7 +560,7 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::removeAllConfigsNotInRuleStopS
std::shared_ptr<ATNConfigSet> result = std::make_shared<ATNConfigSet>(configs->fullCtx); std::shared_ptr<ATNConfigSet> result = std::make_shared<ATNConfigSet>(configs->fullCtx);
for (auto config : configs->configs) { for (auto config : configs->configs) {
if (dynamic_cast<RuleStopState*>(config->state) != nullptr) { if (is<RuleStopState*>(config->state)) {
result->add(config, &mergeCache); result->add(config, &mergeCache);
continue; continue;
} }
@ -566,7 +569,7 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::removeAllConfigsNotInRuleStopS
misc::IntervalSet nextTokens = atn.nextTokens(config->state); misc::IntervalSet nextTokens = atn.nextTokens(config->state);
if (nextTokens.contains(Token::EPSILON)) { if (nextTokens.contains(Token::EPSILON)) {
ATNState *endOfRuleState = atn.ruleToStopState[(size_t)config->state->ruleIndex]; ATNState *endOfRuleState = atn.ruleToStopState[(size_t)config->state->ruleIndex];
result->add(new ATNConfig(config, endOfRuleState), &mergeCache); result->add(std::make_shared<ATNConfig>(config, endOfRuleState), &mergeCache);
} }
} }
} }
@ -581,8 +584,8 @@ std::shared_ptr<ATNConfigSet> ParserATNSimulator::computeStartState(ATNState *p,
for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { for (size_t i = 0; i < p->getNumberOfTransitions(); i++) {
ATNState *target = p->transition(i)->target; ATNState *target = p->transition(i)->target;
ATNConfig *c = new ATNConfig(target, (int)i + 1, initialContext); ATNConfig::Ref c = std::make_shared<ATNConfig>(target, (int)i + 1, initialContext);
std::set<ATNConfig*> closureBusy; std::set<ATNConfig::Ref> closureBusy;
closure(c, configs, closureBusy, true, fullCtx); closure(c, configs, closureBusy, true, fullCtx);
} }
@ -652,7 +655,7 @@ std::vector<dfa::DFAState::PredPrediction *> ParserATNSimulator::getPredicatePre
assert(pred != nullptr); assert(pred != nullptr);
if (ambigAlts.test(i)) { 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) { if (pred != SemanticContext::NONE) {
containsPredicate = true; containsPredicate = true;
@ -710,28 +713,28 @@ BitSet ParserATNSimulator::evalSemanticContext(std::vector<dfa::DFAState::PredPr
return predictions; return predictions;
} }
void ParserATNSimulator::closure(ATNConfig *config, std::shared_ptr<ATNConfigSet> configs, void ParserATNSimulator::closure(ATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs,
std::set<ATNConfig*> &closureBusy, bool collectPredicates, bool fullCtx) { std::set<ATNConfig::Ref> &closureBusy, bool collectPredicates, bool fullCtx) {
const int initialDepth = 0; const int initialDepth = 0;
closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, initialDepth); closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, initialDepth);
assert(!fullCtx || !configs->dipsIntoOuterContext); assert(!fullCtx || !configs->dipsIntoOuterContext);
} }
void ParserATNSimulator::closureCheckingStopState(ATNConfig *config, std::shared_ptr<ATNConfigSet> configs, void ParserATNSimulator::closureCheckingStopState(ATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs,
std::set<ATNConfig*> &closureBusy, bool collectPredicates, bool fullCtx, int depth) { std::set<ATNConfig::Ref> &closureBusy, bool collectPredicates, bool fullCtx, int depth) {
if (debug) { if (debug) {
std::wcout << L"closure(" << config->toString(true) << L")" << std::endl; std::wcout << L"closure(" << config->toString(true) << L")" << std::endl;
} }
if (dynamic_cast<RuleStopState*>(config->state) != nullptr) { if (is<RuleStopState*>(config->state)) {
// We hit rule end. If we have context info, use it // We hit rule end. If we have context info, use it
// run thru all possible stack tops in ctx // run thru all possible stack tops in ctx
if (!config->context->isEmpty()) { if (!config->context->isEmpty()) {
for (size_t i = 0; i < config->context->size(); i++) { for (size_t i = 0; i < config->context->size(); i++) {
if (config->context->getReturnState(i) == PredictionContext::EMPTY_RETURN_STATE) { if (config->context->getReturnState(i) == PredictionContext::EMPTY_RETURN_STATE) {
if (fullCtx) { if (fullCtx) {
configs->add(new ATNConfig(config, config->state, PredictionContext::EMPTY), &mergeCache); configs->add(std::make_shared<ATNConfig>(config, config->state, PredictionContext::EMPTY), &mergeCache);
continue; continue;
} else { } else {
// we have no context info, just chase follow links (if greedy) // 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)]; ATNState *returnState = atn.states[(size_t)config->context->getReturnState(i)];
std::weak_ptr<PredictionContext> newContext = config->context->getParent(i); // "pop" return state std::weak_ptr<PredictionContext> 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<ATNConfig>(returnState, config->alt, newContext.lock(), config->semanticContext);
// While we have context to pop back from, we may have // While we have context to pop back from, we may have
// gotten that context AFTER having falling off a rule. // gotten that context AFTER having falling off a rule.
// Make sure we track that we are now out of context. // 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); closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth);
} }
void ParserATNSimulator::closure_(ATNConfig *config, std::shared_ptr<ATNConfigSet> configs, void ParserATNSimulator::closure_(ATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs,
std::set<ATNConfig*> &closureBusy, bool collectPredicates, bool fullCtx, int depth) { std::set<ATNConfig::Ref> &closureBusy, bool collectPredicates, bool fullCtx, int depth) {
ATNState *p = config->state; ATNState *p = config->state;
// optimization // optimization
if (!p->onlyHasEpsilonTransitions()) { if (!p->onlyHasEpsilonTransitions()) {
@ -779,11 +782,11 @@ void ParserATNSimulator::closure_(ATNConfig *config, std::shared_ptr<ATNConfigSe
for (size_t i = 0; i < p->getNumberOfTransitions(); i++) { for (size_t i = 0; i < p->getNumberOfTransitions(); i++) {
Transition *t = p->transition(i); Transition *t = p->transition(i);
bool continueCollecting = !(dynamic_cast<ActionTransition*>(t) != nullptr) && collectPredicates; bool continueCollecting = !is<ActionTransition*>(t) && collectPredicates;
ATNConfig *c = getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx); ATNConfig::Ref c = getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx);
if (c != nullptr) { if (c != nullptr) {
int newDepth = depth; int newDepth = depth;
if (dynamic_cast<RuleStopState*>(config->state) != nullptr) { if (is<RuleStopState*>(config->state)) {
assert(!fullCtx); assert(!fullCtx);
// target fell off end of rule; mark resulting c as having dipped into outer context // 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<ATNConfigSe
if (debug) { if (debug) {
std::wcout << L"dips into outer ctx: " << c << std::endl; std::wcout << L"dips into outer ctx: " << c << std::endl;
} }
} else if (dynamic_cast<RuleTransition*>(t) != nullptr) { } else if (is<RuleTransition*>(t)) {
// latch when newDepth goes negative - once we step out of the entry context we can't return // latch when newDepth goes negative - once we step out of the entry context we can't return
if (newDepth >= 0) { if (newDepth >= 0) {
newDepth++; newDepth++;
@ -825,7 +828,7 @@ std::wstring ParserATNSimulator::getRuleName(size_t index) {
return L"<rule " + std::to_wstring(index) + L">"; return L"<rule " + std::to_wstring(index) + 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()) { switch (t->getSerializationType()) {
case Transition::RULE: case Transition::RULE:
return ruleTransition(config, static_cast<RuleTransition*>(t)); return ruleTransition(config, static_cast<RuleTransition*>(t));
@ -840,21 +843,21 @@ atn::ATNConfig *ParserATNSimulator::getEpsilonTarget(ATNConfig *config, Transiti
return actionTransition(config, static_cast<ActionTransition*>(t)); return actionTransition(config, static_cast<ActionTransition*>(t));
case Transition::EPSILON: case Transition::EPSILON:
return new ATNConfig(config, t->target); return std::make_shared<ATNConfig>(config, t->target);
default: default:
return nullptr; return nullptr;
} }
} }
atn::ATNConfig *ParserATNSimulator::actionTransition(ATNConfig *config, ActionTransition *t) { ATNConfig::Ref ParserATNSimulator::actionTransition(ATNConfig::Ref config, ActionTransition *t) {
if (debug) { if (debug) {
std::wcout << L"ACTION edge " << t->ruleIndex << L":" << t->actionIndex << std::endl; std::wcout << L"ACTION edge " << t->ruleIndex << L":" << t->actionIndex << std::endl;
} }
return new ATNConfig(config, t->target); return std::make_shared<ATNConfig>(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) { bool collectPredicates, bool inContext, bool fullCtx) {
if (debug) { if (debug) {
std::wcout << L"PRED (collectPredicates=" << collectPredicates << L") " << pt->precedence << L">=_p" << L", ctx dependent=true" << std::endl; 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) { if (collectPredicates && inContext) {
std::shared_ptr<SemanticContext::PrecedencePredicate> predicate = pt->getPredicate(); std::shared_ptr<SemanticContext::PrecedencePredicate> predicate = pt->getPredicate();
@ -877,14 +880,14 @@ atn::ATNConfig *ParserATNSimulator::precedenceTransition(ATNConfig *config, Prec
bool predSucceeds = predicate->eval(parser, _outerContext); bool predSucceeds = predicate->eval(parser, _outerContext);
_input->seek(currentPosition); _input->seek(currentPosition);
if (predSucceeds) { if (predSucceeds) {
c = new ATNConfig(config, pt->target); // no pred context c = std::make_shared<ATNConfig>(config, pt->target); // no pred context
} }
} else { } else {
std::shared_ptr<SemanticContext::AND> newSemCtx = std::make_shared<SemanticContext::AND>(config->semanticContext, predicate); std::shared_ptr<SemanticContext::AND> newSemCtx = std::make_shared<SemanticContext::AND>(config->semanticContext, predicate);
c = new ATNConfig(config, pt->target, newSemCtx); c = std::make_shared<ATNConfig>(config, pt->target, newSemCtx);
} }
} else { } else {
c = new ATNConfig(config, pt->target); c = std::make_shared<ATNConfig>(config, pt->target);
} }
if (debug) { if (debug) {
@ -893,7 +896,7 @@ atn::ATNConfig *ParserATNSimulator::precedenceTransition(ATNConfig *config, Prec
return c; 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) { if (debug) {
std::wcout << L"PRED (collectPredicates=" << collectPredicates << L") " << pt->ruleIndex << L":" << pt->predIndex << L", ctx dependent=" << pt->isCtxDependent << std::endl; std::wcout << L"PRED (collectPredicates=" << collectPredicates << L") " << pt->ruleIndex << L":" << pt->predIndex << L", ctx dependent=" << pt->isCtxDependent << std::endl;
if (parser != nullptr) { 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))) { if (collectPredicates && (!pt->isCtxDependent || (pt->isCtxDependent && inContext))) {
std::shared_ptr<SemanticContext::Predicate> predicate = pt->getPredicate(); std::shared_ptr<SemanticContext::Predicate> predicate = pt->getPredicate();
if (fullCtx) { if (fullCtx) {
@ -914,14 +917,14 @@ atn::ATNConfig *ParserATNSimulator::predTransition(ATNConfig *config, PredicateT
bool predSucceeds = predicate->eval(parser, _outerContext); bool predSucceeds = predicate->eval(parser, _outerContext);
_input->seek(currentPosition); _input->seek(currentPosition);
if (predSucceeds) { if (predSucceeds) {
c = new ATNConfig(config, pt->target); // no pred context c = std::make_shared<ATNConfig>(config, pt->target); // no pred context
} }
} else { } else {
std::shared_ptr<SemanticContext::AND> newSemCtx = std::make_shared<SemanticContext::AND>(config->semanticContext, predicate); std::shared_ptr<SemanticContext::AND> newSemCtx = std::make_shared<SemanticContext::AND>(config->semanticContext, predicate);
c = new ATNConfig(config, pt->target, newSemCtx); c = std::make_shared<ATNConfig>(config, pt->target, newSemCtx);
} }
} else { } else {
c = new ATNConfig(config, pt->target); c = std::make_shared<ATNConfig>(config, pt->target);
} }
if (debug) { if (debug) {
@ -930,14 +933,14 @@ atn::ATNConfig *ParserATNSimulator::predTransition(ATNConfig *config, PredicateT
return c; return c;
} }
atn::ATNConfig *ParserATNSimulator::ruleTransition(ATNConfig *config, RuleTransition *t) { ATNConfig::Ref ParserATNSimulator::ruleTransition(ATNConfig::Ref config, RuleTransition *t) {
if (debug) { if (debug) {
std::wcout << L"CALL rule " << getRuleName((size_t)t->target->ruleIndex) << L", ctx=" << config->context << std::endl; std::wcout << L"CALL rule " << getRuleName((size_t)t->target->ruleIndex) << L", ctx=" << config->context << std::endl;
} }
atn::ATNState *returnState = t->followState; atn::ATNState *returnState = t->followState;
PredictionContext::Ref newContext = SingletonPredictionContext::create(config->context, returnState->stateNumber); PredictionContext::Ref newContext = SingletonPredictionContext::create(config->context, returnState->stateNumber);
return new atn::ATNConfig(config, t->target, newContext); return std::make_shared<ATNConfig>(config, t->target, newContext);
} }
BitSet ParserATNSimulator::getConflictingAlts(std::shared_ptr<ATNConfigSet> configs) { BitSet ParserATNSimulator::getConflictingAlts(std::shared_ptr<ATNConfigSet> configs) {
@ -981,12 +984,12 @@ void ParserATNSimulator::dumpDeadEndConfigs(NoViableAltException &nvae) {
std::wstring trans = L"no edges"; std::wstring trans = L"no edges";
if (c->state->getNumberOfTransitions() > 0) { if (c->state->getNumberOfTransitions() > 0) {
Transition *t = c->state->transition(0); Transition *t = c->state->transition(0);
if (dynamic_cast<AtomTransition*>(t) != nullptr) { if (is<AtomTransition*>(t)) {
AtomTransition *at = static_cast<AtomTransition*>(t); AtomTransition *at = static_cast<AtomTransition*>(t);
trans = L"Atom " + getTokenName(at->_label); trans = L"Atom " + getTokenName(at->_label);
} else if (dynamic_cast<SetTransition*>(t) != nullptr) { } else if (is<SetTransition*>(t)) {
SetTransition *st = static_cast<SetTransition*>(t); SetTransition *st = static_cast<SetTransition*>(t);
bool is_not = dynamic_cast<NotSetTransition*>(st) != nullptr; bool is_not = is<NotSetTransition*>(st);
trans = (is_not ? L"~" : L""); trans = (is_not ? L"~" : L"");
trans += L"Set "; trans += L"Set ";
trans += st->set.toString(); trans += st->set.toString();

View File

@ -36,6 +36,7 @@
#include "ATNSimulator.h" #include "ATNSimulator.h"
#include "PredictionContext.h" #include "PredictionContext.h"
#include "SemanticContext.h" #include "SemanticContext.h"
#include "ATNConfig.h"
namespace org { namespace org {
namespace antlr { namespace antlr {
@ -410,30 +411,30 @@ namespace atn {
ambig detection thought :( ambig detection thought :(
*/ */
virtual void closure(ATNConfig *config, std::shared_ptr<ATNConfigSet> configs, std::set<ATNConfig*> &closureBusy, virtual void closure(ATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs, std::set<ATNConfig::Ref> &closureBusy,
bool collectPredicates, bool fullCtx); bool collectPredicates, bool fullCtx);
virtual void closureCheckingStopState(ATNConfig *config, std::shared_ptr<ATNConfigSet> configs, virtual void closureCheckingStopState(ATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs,
std::set<ATNConfig*> &closureBusy, bool collectPredicates, bool fullCtx, int depth); std::set<ATNConfig::Ref> &closureBusy, bool collectPredicates, bool fullCtx, int depth);
/// Do the actual work of walking epsilon edges. /// Do the actual work of walking epsilon edges.
virtual void closure_(ATNConfig *config, std::shared_ptr<ATNConfigSet> configs, std::set<ATNConfig*> &closureBusy, virtual void closure_(ATNConfig::Ref config, std::shared_ptr<ATNConfigSet> configs, std::set<ATNConfig::Ref> &closureBusy,
bool collectPredicates, bool fullCtx, int depth); bool collectPredicates, bool fullCtx, int depth);
public: public:
virtual std::wstring getRuleName(size_t index); virtual std::wstring getRuleName(size_t index);
protected: protected:
virtual ATNConfig *getEpsilonTarget(ATNConfig *config, Transition *t, bool collectPredicates, bool inContext, bool fullCtx); virtual ATNConfig::Ref getEpsilonTarget(ATNConfig::Ref config, Transition *t, bool collectPredicates, bool inContext, bool fullCtx);
virtual ATNConfig *actionTransition(ATNConfig *config, ActionTransition *t); virtual ATNConfig::Ref actionTransition(ATNConfig::Ref config, ActionTransition *t);
public: 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: 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<ATNConfigSet> configs); virtual antlrcpp::BitSet getConflictingAlts(std::shared_ptr<ATNConfigSet> configs);

View File

@ -53,6 +53,9 @@ const int PredictionContext::INITIAL_HASH;
PredictionContext::PredictionContext(size_t cachedHashCode) : id(globalNodeCount++), cachedHashCode(cachedHashCode) { PredictionContext::PredictionContext(size_t cachedHashCode) : id(globalNodeCount++), cachedHashCode(cachedHashCode) {
} }
PredictionContext::~PredictionContext() {
}
PredictionContext::Ref PredictionContext::fromRuleContext(const ATN &atn, RuleContext::Ref outerContext) { PredictionContext::Ref PredictionContext::fromRuleContext(const ATN &atn, RuleContext::Ref outerContext) {
if (!outerContext) { if (!outerContext) {
outerContext = RuleContext::EMPTY; outerContext = RuleContext::EMPTY;
@ -145,10 +148,10 @@ PredictionContext::Ref PredictionContext::merge(PredictionContext::Ref a,
// convert singleton so both are arrays to normalize // convert singleton so both are arrays to normalize
if (is<SingletonPredictionContext>(a)) { if (is<SingletonPredictionContext>(a)) {
a.reset(new ArrayPredictionContext(std::dynamic_pointer_cast<SingletonPredictionContext>(a))); a = std::make_shared<ArrayPredictionContext>(std::dynamic_pointer_cast<SingletonPredictionContext>(a));
} }
if (is<SingletonPredictionContext>(b)) { if (is<SingletonPredictionContext>(b)) {
b.reset(new ArrayPredictionContext(std::dynamic_pointer_cast<SingletonPredictionContext>(b))); b = std::make_shared<ArrayPredictionContext>(std::dynamic_pointer_cast<SingletonPredictionContext>(b));
} }
return mergeArrays(std::dynamic_pointer_cast<ArrayPredictionContext>(a), return mergeArrays(std::dynamic_pointer_cast<ArrayPredictionContext>(a),
std::dynamic_pointer_cast<ArrayPredictionContext>(b), rootIsWildcard, mergeCache); std::dynamic_pointer_cast<ArrayPredictionContext>(b), rootIsWildcard, mergeCache);
@ -212,7 +215,7 @@ PredictionContext::Ref PredictionContext::mergeSingletons(SingletonPredictionCon
payloads[1] = a->returnState; payloads[1] = a->returnState;
} }
std::vector<std::weak_ptr<PredictionContext>> parents = { singleParent, singleParent }; std::vector<std::weak_ptr<PredictionContext>> parents = { singleParent, singleParent };
PredictionContext::Ref a_(new ArrayPredictionContext(parents, payloads)); PredictionContext::Ref a_ = std::make_shared<ArrayPredictionContext>(parents, payloads);
if (mergeCache != nullptr) { if (mergeCache != nullptr) {
(*mergeCache)[{ a.get(), b.get() }] = a_; (*mergeCache)[{ a.get(), b.get() }] = a_;
} }
@ -226,11 +229,11 @@ PredictionContext::Ref PredictionContext::mergeSingletons(SingletonPredictionCon
if (a->returnState > b->returnState) { // sort by payload if (a->returnState > b->returnState) { // sort by payload
std::vector<int> payloads = { b->returnState, a->returnState }; std::vector<int> payloads = { b->returnState, a->returnState };
std::vector<std::weak_ptr<PredictionContext>> parents = { b->parent, a->parent }; std::vector<std::weak_ptr<PredictionContext>> parents = { b->parent, a->parent };
a_.reset(new ArrayPredictionContext(parents, payloads)); a_ = std::make_shared<ArrayPredictionContext>(parents, payloads);
} else { } else {
std::vector<int> payloads = {a->returnState, b->returnState}; std::vector<int> payloads = {a->returnState, b->returnState};
std::vector<std::weak_ptr<PredictionContext>> parents = { a->parent, b->parent }; std::vector<std::weak_ptr<PredictionContext>> parents = { a->parent, b->parent };
a_.reset(new ArrayPredictionContext(parents, payloads)); a_ = std::make_shared<ArrayPredictionContext>(parents, payloads);
} }
if (mergeCache != nullptr) { if (mergeCache != nullptr) {
@ -256,13 +259,13 @@ PredictionContext::Ref PredictionContext::mergeRoot(SingletonPredictionContext::
if (a == EMPTY) { // $ + x = [$,x] if (a == EMPTY) { // $ + x = [$,x]
std::vector<int> payloads = { b->returnState, EMPTY_RETURN_STATE }; std::vector<int> payloads = { b->returnState, EMPTY_RETURN_STATE };
std::vector<std::weak_ptr<PredictionContext>> parents = { b->parent, EMPTY }; std::vector<std::weak_ptr<PredictionContext>> parents = { b->parent, EMPTY };
PredictionContext::Ref joined(new ArrayPredictionContext(parents, payloads)); PredictionContext::Ref joined = std::make_shared<ArrayPredictionContext>(parents, payloads);
return joined; return joined;
} }
if (b == EMPTY) { // x + $ = [$,x] ($ is always first if present) if (b == EMPTY) { // x + $ = [$,x] ($ is always first if present)
std::vector<int> payloads = { a->returnState, EMPTY_RETURN_STATE }; std::vector<int> payloads = { a->returnState, EMPTY_RETURN_STATE };
std::vector<std::weak_ptr<PredictionContext>> parents = { a->parent, EMPTY }; std::vector<std::weak_ptr<PredictionContext>> parents = { a->parent, EMPTY };
PredictionContext::Ref joined(new ArrayPredictionContext(parents, payloads)); PredictionContext::Ref joined = std::make_shared<ArrayPredictionContext>(parents, payloads);
return joined; return joined;
} }
} }
@ -288,10 +291,8 @@ PredictionContext::Ref PredictionContext::mergeArrays(std::shared_ptr<ArrayPredi
size_t j = 0; // walks b size_t j = 0; // walks b
size_t k = 0; // walks target M array size_t k = 0; // walks target M array
std::vector<int> mergedReturnStates; std::vector<int> mergedReturnStates(a->returnStates.size() + b->returnStates.size());
mergedReturnStates.resize(a->returnStates.size() + b->returnStates.size()); std::vector<std::weak_ptr<PredictionContext>> mergedParents(a->returnStates.size() + b->returnStates.size());
std::vector<std::weak_ptr<PredictionContext>> mergedParents;
mergedParents.resize(a->returnStates.size() + b->returnStates.size());
// walk and merge to yield mergedParents, mergedReturnStates // walk and merge to yield mergedParents, mergedReturnStates
while (i < a->returnStates.size() && j < b->returnStates.size()) { while (i < a->returnStates.size() && j < b->returnStates.size()) {
@ -355,7 +356,7 @@ PredictionContext::Ref PredictionContext::mergeArrays(std::shared_ptr<ArrayPredi
mergedReturnStates = Arrays::copyOf(mergedReturnStates, k); mergedReturnStates = Arrays::copyOf(mergedReturnStates, k);
} }
std::shared_ptr<ArrayPredictionContext> M(new ArrayPredictionContext(mergedParents, mergedReturnStates)); std::shared_ptr<ArrayPredictionContext> M = std::make_shared<ArrayPredictionContext>(mergedParents, mergedReturnStates);
// if we created same array as a or b, return that instead // 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 // TO_DO: track whether this is possible above during merge sort for speed
@ -373,7 +374,7 @@ PredictionContext::Ref PredictionContext::mergeArrays(std::shared_ptr<ArrayPredi
} }
if (combineCommonParents(mergedParents)) // Need to recreate the context as the parents array is copied on creation. if (combineCommonParents(mergedParents)) // Need to recreate the context as the parents array is copied on creation.
M.reset(new ArrayPredictionContext(mergedParents, mergedReturnStates)); M = std::make_shared<ArrayPredictionContext>(mergedParents, mergedReturnStates);
if (mergeCache != nullptr) { if (mergeCache != nullptr) {
(*mergeCache)[{ a.get(), b.get() }] = M; (*mergeCache)[{ a.get(), b.get() }] = M;
@ -485,8 +486,7 @@ PredictionContext::Ref PredictionContext::getCachedContext(PredictionContext::Re
bool changed = false; bool changed = false;
std::vector<std::weak_ptr<PredictionContext>> parents; std::vector<std::weak_ptr<PredictionContext>> parents(context->size());
parents.resize(context->size());
for (size_t i = 0; i < parents.size(); i++) { for (size_t i = 0; i < parents.size(); i++) {
std::weak_ptr<PredictionContext> parent = getCachedContext(context->getParent(i).lock(), contextCache, visited); std::weak_ptr<PredictionContext> parent = getCachedContext(context->getParent(i).lock(), contextCache, visited);
if (changed || parent.lock() != context->getParent(i).lock()) { if (changed || parent.lock() != context->getParent(i).lock()) {

View File

@ -92,6 +92,7 @@ namespace atn {
protected: protected:
PredictionContext(size_t cachedHashCode); PredictionContext(size_t cachedHashCode);
~PredictionContext();
public: public:
/// Convert a RuleContext tree to a PredictionContext graph. /// Convert a RuleContext tree to a PredictionContext graph.

View File

@ -38,6 +38,7 @@
using namespace org::antlr::v4::runtime; using namespace org::antlr::v4::runtime;
using namespace org::antlr::v4::runtime::atn; using namespace org::antlr::v4::runtime::atn;
using namespace antlrcpp;
struct AltAndContextConfigHasher struct AltAndContextConfigHasher
{ {
@ -77,8 +78,8 @@ bool PredictionModeClass::hasSLLConflictTerminatingPrediction(PredictionMode* mo
if (configs->hasSemanticContext) { if (configs->hasSemanticContext) {
// dup configs, tossing out semantic predicates // dup configs, tossing out semantic predicates
std::shared_ptr<ATNConfigSet> dup = std::make_shared<ATNConfigSet>(true); std::shared_ptr<ATNConfigSet> dup = std::make_shared<ATNConfigSet>(true);
for (ATNConfig config : configs->configs) { for (auto config : configs->configs) {
ATNConfig* c = new ATNConfig(&config, SemanticContext::NONE); ATNConfig::Ref c = std::make_shared<ATNConfig>(config, SemanticContext::NONE);
dup->add(c); dup->add(c);
} }
configs = dup; configs = dup;
@ -94,8 +95,8 @@ bool PredictionModeClass::hasSLLConflictTerminatingPrediction(PredictionMode* mo
} }
bool PredictionModeClass::hasConfigInRuleStopState(std::shared_ptr<ATNConfigSet> configs) { bool PredictionModeClass::hasConfigInRuleStopState(std::shared_ptr<ATNConfigSet> configs) {
for (ATNConfig c : configs->configs) { for (auto c : configs->configs) {
if (dynamic_cast<RuleStopState*>(c.state) != NULL) { if (is<RuleStopState*>(c->state)) {
return true; return true;
} }
} }
@ -104,8 +105,8 @@ bool PredictionModeClass::hasConfigInRuleStopState(std::shared_ptr<ATNConfigSet>
} }
bool PredictionModeClass::allConfigsInRuleStopStates(std::shared_ptr<ATNConfigSet> configs) { bool PredictionModeClass::allConfigsInRuleStopStates(std::shared_ptr<ATNConfigSet> configs) {
for (ATNConfig config : configs->configs) { for (auto config : configs->configs) {
if (dynamic_cast<RuleStopState*>(config.state) == NULL) { if (!is<RuleStopState*>(config->state)) {
return false; return false;
} }
} }
@ -171,7 +172,7 @@ antlrcpp::BitSet PredictionModeClass::getAlts(const std::vector<antlrcpp::BitSet
} }
std::vector<antlrcpp::BitSet> PredictionModeClass::getConflictingAltSubsets(std::shared_ptr<ATNConfigSet> configs) { std::vector<antlrcpp::BitSet> PredictionModeClass::getConflictingAltSubsets(std::shared_ptr<ATNConfigSet> configs) {
std::unordered_map<ATNConfig *, antlrcpp::BitSet, AltAndContextConfigHasher, AltAndContextConfigComparer> configToAlts; std::unordered_map<ATNConfig::Ref, antlrcpp::BitSet, AltAndContextConfigHasher, AltAndContextConfigComparer> configToAlts;
for (auto config : configs->configs) { for (auto config : configs->configs) {
configToAlts[config].set((size_t)config->alt); configToAlts[config].set((size_t)config->alt);
} }
@ -184,8 +185,8 @@ std::vector<antlrcpp::BitSet> PredictionModeClass::getConflictingAltSubsets(std:
std::map<ATNState*, antlrcpp::BitSet> PredictionModeClass::getStateToAltMap(std::shared_ptr<ATNConfigSet> configs) { std::map<ATNState*, antlrcpp::BitSet> PredictionModeClass::getStateToAltMap(std::shared_ptr<ATNConfigSet> configs) {
std::map<ATNState*, antlrcpp::BitSet> m; std::map<ATNState*, antlrcpp::BitSet> m;
for (ATNConfig c : configs->configs) { for (auto c : configs->configs) {
m[c.state].set((size_t)c.alt); m[c->state].set((size_t)c->alt);
} }
return m; return m;
} }

View File

@ -44,6 +44,12 @@ DFA::DFA(atn::DecisionState *atnStartState, int decision)
: atnStartState(atnStartState), decision(decision), s0(nullptr) { : atnStartState(atnStartState), decision(decision), s0(nullptr) {
} }
DFA::~DFA() {
for (auto state : states) {
delete state.second;
}
}
std::vector<DFAState *> DFA::getStates() { std::vector<DFAState *> DFA::getStates() {
std::vector<DFAState *> result; std::vector<DFAState *> result;
for (auto state : states) for (auto state : states)

View File

@ -44,21 +44,18 @@ namespace dfa {
/// From which ATN state did we create this DFA? /// From which ATN state did we create this DFA?
atn::DecisionState *const atnStartState; atn::DecisionState *const atnStartState;
std::unordered_map<DFAState *, DFAState *> states; std::unordered_map<DFAState *, DFAState *> states; // States are owned by this class.
DFAState *s0; DFAState *s0;
const int decision; const int decision;
DFA(atn::DecisionState *atnStartState); //this(atnStartState, 0); DFA(atn::DecisionState *atnStartState);
DFA(atn::DecisionState *atnStartState, int decision); DFA(atn::DecisionState *atnStartState, int decision);
~DFA();
/// <summary>
/// Return a list of all states in this DFA, ordered by state number. /// Return a list of all states in this DFA, ordered by state number.
/// </summary>
virtual std::vector<DFAState*> getStates(); virtual std::vector<DFAState*> getStates();
virtual std::wstring toString(); virtual std::wstring toString();
virtual std::wstring toString(const std::vector<std::wstring>& tokenNames); virtual std::wstring toString(const std::vector<std::wstring>& tokenNames);
virtual std::wstring toLexerString(); virtual std::wstring toLexerString();

View File

@ -64,16 +64,19 @@ DFAState::DFAState(std::shared_ptr<ATNConfigSet> configs) : DFAState() {
this->configs = configs; this->configs = configs;
} }
std::set<int> *DFAState::getAltSet() { DFAState::~DFAState() {
std::set<int> *alts = new std::set<int>(); for (auto predicate : predicates) {
delete predicate;
}
}
std::set<int> DFAState::getAltSet() {
std::set<int> alts;
if (configs != nullptr) { if (configs != nullptr) {
for (size_t i = 0; i < configs->size(); i++) { 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; return alts;
} }

View File

@ -125,12 +125,13 @@ namespace dfa {
DFAState(); DFAState();
DFAState(int state); DFAState(int state);
DFAState(std::shared_ptr<atn::ATNConfigSet> configs); DFAState(std::shared_ptr<atn::ATNConfigSet> configs);
~DFAState();
/// <summary> /// <summary>
/// Get the set of all alts mentioned by all ATN configurations in this /// Get the set of all alts mentioned by all ATN configurations in this
/// DFA state. /// DFA state.
/// </summary> /// </summary>
virtual std::set<int> *getAltSet(); virtual std::set<int> getAltSet();
virtual size_t hashCode() ; virtual size_t hashCode() ;

View File

@ -77,8 +77,7 @@ namespace antlrcpp {
template <typename T> template <typename T>
static std::vector<T> copyOf(const std::vector<T> &source, size_t count) { static std::vector<T> copyOf(const std::vector<T> &source, size_t count) {
std::vector<T> result; std::vector<T> result(std::min(source.size(), count));
result.resize(std::min(source.size(), count));
std::copy(source.begin(), source.end(), result.begin()); std::copy(source.begin(), source.end(), result.begin());
return result; return result;
} }

View File

@ -55,29 +55,28 @@ namespace tree {
/// </summary> /// </summary>
template<typename V> template<typename V>
class ParseTreeProperty { class ParseTreeProperty {
protected:
std::map<ParseTree*, V> *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<ParseTree*, V>();
}
public: public:
ParseTreeProperty() { ParseTreeProperty() {
InitializeInstanceFields(); 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<ParseTree*, V> _annotations;
private:
void InitializeInstanceFields() {
}
}; };
} // namespace tree } // namespace tree

View File

@ -47,18 +47,19 @@ std::wstring Trees::toStringTree(std::shared_ptr<Tree> t) {
} }
std::wstring Trees::toStringTree(std::shared_ptr<Tree> t, Parser *recog) { std::wstring Trees::toStringTree(std::shared_ptr<Tree> t, Parser *recog) {
if (recog == nullptr)
return toStringTree(t, {});
return toStringTree(t, recog->getRuleNames()); return toStringTree(t, recog->getRuleNames());
} }
std::wstring Trees::toStringTree(std::shared_ptr<Tree> t, const std::vector<std::wstring> &ruleNames) { std::wstring Trees::toStringTree(std::shared_ptr<Tree> t, const std::vector<std::wstring> &ruleNames) {
std::wstring tmp = Trees::getNodeText(t, ruleNames); std::wstring temp = antlrcpp::escapeWhitespace(Trees::getNodeText(t, ruleNames), false);
std::wstring s = antlrcpp::escapeWhitespace(tmp, false);
if (t->getChildCount() == 0) { if (t->getChildCount() == 0) {
return s; return temp;
} }
std::wstringstream ss; 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++) { for (size_t i = 0; i < t->getChildCount(); i++) {
if (i > 0) { if (i > 0) {
ss << L' '; ss << L' ';

View File

@ -101,8 +101,13 @@ ParseTreeMatch ParseTreePatternMatcher::match(std::shared_ptr<ParseTree> tree, c
ParseTreePattern ParseTreePatternMatcher::compile(const std::wstring &pattern, int patternRuleIndex) { ParseTreePattern ParseTreePatternMatcher::compile(const std::wstring &pattern, int patternRuleIndex) {
std::vector<Token::Ref> tokenList = tokenize(pattern); std::vector<Token::Ref> 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(), ParserInterpreter parserInterp(_parser->getGrammarFileName(), _parser->getTokenNames(),
_parser->getRuleNames(), _parser->getATNWithBypassAlts(), tokens); _parser->getRuleNames(), _parser->getATNWithBypassAlts(), tokens);
@ -230,34 +235,35 @@ std::shared_ptr<RuleTagToken> ParseTreePatternMatcher::getRuleTagToken(std::shar
std::vector<Token::Ref> ParseTreePatternMatcher::tokenize(const std::wstring &pattern) { std::vector<Token::Ref> ParseTreePatternMatcher::tokenize(const std::wstring &pattern) {
// split pattern into chunks: sea (raw input) and islands (<ID>, <expr>) // split pattern into chunks: sea (raw input) and islands (<ID>, <expr>)
std::vector<Chunk*> chunks = split(pattern); std::vector<Chunk> chunks = split(pattern);
// create token stream from text and tags // create token stream from text and tags
std::vector<Token::Ref> tokens; std::vector<Token::Ref> tokens;
for (auto chunk : chunks) { for (auto chunk : chunks) {
if (dynamic_cast<TagChunk*>(chunk) != nullptr) { if (is<TagChunk>(chunk)) {
TagChunk *tagChunk = static_cast<TagChunk*>(chunk); TagChunk &tagChunk = (TagChunk&)chunk;
// add special rule token or conjure up new token from name // add special rule token or conjure up new token from name
if (isupper(tagChunk->getTag()[0])) { if (isupper(tagChunk.getTag()[0])) {
int ttype = _parser->getTokenType(tagChunk->getTag()); int ttype = _parser->getTokenType(tagChunk.getTag());
if (ttype == Token::INVALID_TYPE) { 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<TokenTagToken> t = std::make_shared<TokenTagToken>(tagChunk->getTag(), ttype, tagChunk->getLabel()); std::shared_ptr<TokenTagToken> t = std::make_shared<TokenTagToken>(tagChunk.getTag(), ttype, tagChunk.getLabel());
tokens.push_back(t); tokens.push_back(t);
} else if (islower(tagChunk->getTag()[0])) { } else if (islower(tagChunk.getTag()[0])) {
int ruleIndex = _parser->getRuleIndex(tagChunk->getTag()); int ruleIndex = _parser->getRuleIndex(tagChunk.getTag());
if (ruleIndex == -1) { 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]; int ruleImaginaryTokenType = _parser->getATNWithBypassAlts().ruleToTokenType[(size_t)ruleIndex];
tokens.push_back(std::make_shared<RuleTagToken>(tagChunk->getTag(), ruleImaginaryTokenType, tagChunk->getLabel())); tokens.push_back(std::make_shared<RuleTagToken>(tagChunk.getTag(), ruleImaginaryTokenType, tagChunk.getLabel()));
} else { } 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 { } else {
TextChunk *textChunk = static_cast<TextChunk*>(chunk); TextChunk &textChunk = (TextChunk&)chunk;
ANTLRInputStream input(textChunk->getText()); ANTLRInputStream input(textChunk.getText());
_lexer->setInputStream(&input); _lexer->setInputStream(&input);
Token::Ref t = _lexer->nextToken(); Token::Ref t = _lexer->nextToken();
while (t->getType() != EOF) { while (t->getType() != EOF) {
@ -271,10 +277,10 @@ std::vector<Token::Ref> ParseTreePatternMatcher::tokenize(const std::wstring &pa
return tokens; return tokens;
} }
std::vector<Chunk*> ParseTreePatternMatcher::split(const std::wstring &pattern) { std::vector<Chunk> ParseTreePatternMatcher::split(const std::wstring &pattern) {
size_t p = 0; size_t p = 0;
size_t n = pattern.length(); size_t n = pattern.length();
std::vector<Chunk*> chunks = std::vector<Chunk*>(); std::vector<Chunk> chunks;
// find all start and stop indexes first, then collect // find all start and stop indexes first, then collect
std::vector<size_t> starts; std::vector<size_t> starts;
@ -313,12 +319,12 @@ std::vector<Chunk*> ParseTreePatternMatcher::split(const std::wstring &pattern)
// collect into chunks now // collect into chunks now
if (ntags == 0) { if (ntags == 0) {
std::wstring text = pattern.substr(0, n); 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 if (ntags > 0 && starts[0] > 0) { // copy text up to first tag into chunks
std::wstring text = pattern.substr(0, starts[0]); 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++) { for (size_t i = 0; i < ntags; i++) {
// copy inside of <tag> // copy inside of <tag>
@ -330,30 +336,30 @@ std::vector<Chunk*> ParseTreePatternMatcher::split(const std::wstring &pattern)
label = tag.substr(0,colon); label = tag.substr(0,colon);
ruleOrToken = tag.substr(colon + 1, tag.length() - (colon + 1)); 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) { if (i + 1 < ntags) {
// copy from end of <tag> to start of next // copy from end of <tag> to start of next
std::wstring text = pattern.substr(stops[i] + _stop.length(), starts[i + 1] - (stops[i] + _stop.length())); 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) { if (ntags > 0) {
size_t afterLastTag = stops[ntags - 1] + _stop.length(); size_t afterLastTag = stops[ntags - 1] + _stop.length();
if (afterLastTag < n) { // copy text from end of last tag to end if (afterLastTag < n) { // copy text from end of last tag to end
std::wstring text = pattern.substr(afterLastTag, n - afterLastTag); 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 // strip out all backslashes from text chunks but not tags
for (size_t i = 0; i < chunks.size(); i++) { for (size_t i = 0; i < chunks.size(); i++) {
Chunk *c = chunks[i]; Chunk &c = chunks[i];
if (dynamic_cast<TextChunk*>(c) != nullptr) { if (is<TextChunk>(c)) {
TextChunk *tc = static_cast<TextChunk*>(c); TextChunk &tc = (TextChunk&)c;
std::wstring unescaped = tc->getText(); std::wstring unescaped = tc.getText();
unescaped.erase(std::remove(unescaped.begin(), unescaped.end(), L'\\'), unescaped.end()); unescaped.erase(std::remove(unescaped.begin(), unescaped.end(), L'\\'), unescaped.end());
if (unescaped.length() < tc->getText().length()) { if (unescaped.length() < tc.getText().length()) {
chunks[i] = new TextChunk(unescaped); chunks[i] = TextChunk(unescaped);
} }
} }
} }

View File

@ -170,7 +170,7 @@ namespace pattern {
virtual std::vector<Token::Ref> tokenize(const std::wstring &pattern); virtual std::vector<Token::Ref> tokenize(const std::wstring &pattern);
/// Split "<ID> = <e:expr>;" into 4 chunks for tokenizing by tokenize(). /// Split "<ID> = <e:expr>;" into 4 chunks for tokenizing by tokenize().
virtual std::vector<Chunk*> split(const std::wstring &pattern); virtual std::vector<Chunk> split(const std::wstring &pattern);
protected: protected:
std::wstring _start; std::wstring _start;

View File

@ -65,6 +65,7 @@ namespace pattern {
/// </summary> /// </summary>
const std::wstring _label; const std::wstring _label;
public:
/// <summary> /// <summary>
/// Construct a new instance of <seealso cref="TagChunk"/> using the specified tag and /// Construct a new instance of <seealso cref="TagChunk"/> using the specified tag and
/// no label. /// no label.
@ -74,8 +75,7 @@ namespace pattern {
/// </param> /// </param>
/// <exception cref="IllegalArgumentException"> if {@code tag} is {@code null} or /// <exception cref="IllegalArgumentException"> if {@code tag} is {@code null} or
/// empty. </exception> /// empty. </exception>
public: TagChunk(const std::wstring &tag);
TagChunk(const std::wstring &tag); //this(nullptr, tag);
/// <summary> /// <summary>
/// Construct a new instance of <seealso cref="TagChunk"/> using the specified label /// Construct a new instance of <seealso cref="TagChunk"/> using the specified label