forked from jasder/antlr
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:
parent
f292d14abc
commit
e8325623d9
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; };
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() ;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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' ';
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue