From 89cb1aefe10c61fa56883500f3318d47c849b256 Mon Sep 17 00:00:00 2001 From: Justin King Date: Mon, 28 Feb 2022 10:03:09 -0800 Subject: [PATCH] [C++] Lazily deserialize ATN in generated code --- .../Cpp/runtime/src/tree/xpath/XPathLexer.cpp | 225 +++++++------ .../Cpp/runtime/src/tree/xpath/XPathLexer.h | 34 +- .../v4/tool/templates/codegen/Cpp/Cpp.stg | 302 ++++++++++-------- 3 files changed, 314 insertions(+), 247 deletions(-) diff --git a/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.cpp b/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.cpp index 6b0e93d9432..afc52e5f7a9 100644 --- a/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.cpp +++ b/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.cpp @@ -7,9 +7,124 @@ using namespace antlr4; +namespace { + +struct XPathLexer_StaticData final { + XPathLexer_StaticData(std::vector ruleNames, + std::vector channelNames, + std::vector modeNames, + std::vector literalNames, + std::vector symbolicNames) + : ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)), + modeNames(std::move(modeNames)), literalNames(std::move(literalNames)), + symbolicNames(std::move(symbolicNames)), + vocabulary(this->literalNames, this->symbolicNames) {} + + XPathLexer_StaticData(const XPathLexer_StaticData&) = delete; + XPathLexer_StaticData(XPathLexer_StaticData&&) = delete; + XPathLexer_StaticData& operator=(const XPathLexer_StaticData&) = delete; + XPathLexer_StaticData& operator=(XPathLexer_StaticData&&) = delete; + + std::vector decisionToDFA; + antlr4::atn::PredictionContextCache sharedContextCache; + const std::vector ruleNames; + const std::vector channelNames; + const std::vector modeNames; + const std::vector literalNames; + const std::vector symbolicNames; + const antlr4::dfa::Vocabulary vocabulary; + std::vector serializedATN; + std::unique_ptr atn; +}; + +std::once_flag XPathLexer_onceFlag; +XPathLexer_StaticData *XPathLexer_staticData = nullptr; + +void XPathLexer_initialize() { + assert(XPathLexer_staticData == nullptr); + auto staticData = std::make_unique( + std::vector{ + "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", "NameChar", "NameStartChar", + "STRING" + }, + std::vector{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }, + std::vector{ + "DEFAULT_MODE" + }, + std::vector{ + "", "", "", "'//'", "'/'", "'*'", "'!'" + }, + std::vector{ + "", "TOKEN_REF", "RULE_REF", "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", + "STRING" + } + ); + static const uint16_t serializedATNSegment0[] = { + 0x4, 0x0, 0x8, 0x32, 0x6, 0xffff, 0x2, 0x0, 0x7, 0x0, 0x2, 0x1, 0x7, + 0x1, 0x2, 0x2, 0x7, 0x2, 0x2, 0x3, 0x7, 0x3, 0x2, 0x4, 0x7, 0x4, + 0x2, 0x5, 0x7, 0x5, 0x2, 0x6, 0x7, 0x6, 0x2, 0x7, 0x7, 0x7, 0x1, + 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, + 0x1, 0x3, 0x1, 0x3, 0x1, 0x4, 0x1, 0x4, 0x5, 0x4, 0x1d, 0x8, 0x4, + 0xa, 0x4, 0xc, 0x4, 0x20, 0x9, 0x4, 0x1, 0x4, 0x1, 0x4, 0x1, 0x5, + 0x1, 0x5, 0x3, 0x5, 0x26, 0x8, 0x5, 0x1, 0x6, 0x1, 0x6, 0x1, 0x7, + 0x1, 0x7, 0x5, 0x7, 0x2c, 0x8, 0x7, 0xa, 0x7, 0xc, 0x7, 0x2f, 0x9, + 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x2d, 0x0, 0x8, 0x1, 0x3, 0x3, 0x4, + 0x5, 0x5, 0x7, 0x6, 0x9, 0x7, 0xb, 0x0, 0xd, 0x0, 0xf, 0x8, 0x1, + 0x0, 0x2, 0x5, 0x0, 0x30, 0x39, 0x5f, 0x5f, 0xb7, 0xb7, 0x300, 0x36f, + 0x203f, 0x2040, 0xd, 0x0, 0x41, 0x5a, 0x61, 0x7a, 0xc0, 0xd6, 0xd8, + 0xf6, 0xf8, 0x2ff, 0x370, 0x37d, 0x37f, 0x1fff, 0x200c, 0x200d, 0x2070, + 0x218f, 0x2c00, 0x2fef, 0x3001, 0xd7ff, 0xf900, 0xfdcf, 0xfdf0, 0xffff, + 0x0, 0x32, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x5, 0x1, 0x0, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, + 0x0, 0x9, 0x1, 0x0, 0x0, 0x0, 0x0, 0xf, 0x1, 0x0, 0x0, 0x0, 0x1, + 0x11, 0x1, 0x0, 0x0, 0x0, 0x3, 0x14, 0x1, 0x0, 0x0, 0x0, 0x5, 0x16, + 0x1, 0x0, 0x0, 0x0, 0x7, 0x18, 0x1, 0x0, 0x0, 0x0, 0x9, 0x1a, 0x1, + 0x0, 0x0, 0x0, 0xb, 0x25, 0x1, 0x0, 0x0, 0x0, 0xd, 0x27, 0x1, 0x0, + 0x0, 0x0, 0xf, 0x29, 0x1, 0x0, 0x0, 0x0, 0x11, 0x12, 0x5, 0x2f, 0x0, + 0x0, 0x12, 0x13, 0x5, 0x2f, 0x0, 0x0, 0x13, 0x2, 0x1, 0x0, 0x0, 0x0, + 0x14, 0x15, 0x5, 0x2f, 0x0, 0x0, 0x15, 0x4, 0x1, 0x0, 0x0, 0x0, 0x16, + 0x17, 0x5, 0x2a, 0x0, 0x0, 0x17, 0x6, 0x1, 0x0, 0x0, 0x0, 0x18, 0x19, + 0x5, 0x21, 0x0, 0x0, 0x19, 0x8, 0x1, 0x0, 0x0, 0x0, 0x1a, 0x1e, 0x3, + 0xd, 0x6, 0x0, 0x1b, 0x1d, 0x3, 0xb, 0x5, 0x0, 0x1c, 0x1b, 0x1, 0x0, + 0x0, 0x0, 0x1d, 0x20, 0x1, 0x0, 0x0, 0x0, 0x1e, 0x1c, 0x1, 0x0, 0x0, + 0x0, 0x1e, 0x1f, 0x1, 0x0, 0x0, 0x0, 0x1f, 0x21, 0x1, 0x0, 0x0, 0x0, + 0x20, 0x1e, 0x1, 0x0, 0x0, 0x0, 0x21, 0x22, 0x6, 0x4, 0x0, 0x0, 0x22, + 0xa, 0x1, 0x0, 0x0, 0x0, 0x23, 0x26, 0x3, 0xd, 0x6, 0x0, 0x24, 0x26, + 0x7, 0x0, 0x0, 0x0, 0x25, 0x23, 0x1, 0x0, 0x0, 0x0, 0x25, 0x24, 0x1, + 0x0, 0x0, 0x0, 0x26, 0xc, 0x1, 0x0, 0x0, 0x0, 0x27, 0x28, 0x7, 0x1, + 0x0, 0x0, 0x28, 0xe, 0x1, 0x0, 0x0, 0x0, 0x29, 0x2d, 0x5, 0x27, 0x0, + 0x0, 0x2a, 0x2c, 0x9, 0x0, 0x0, 0x0, 0x2b, 0x2a, 0x1, 0x0, 0x0, 0x0, + 0x2c, 0x2f, 0x1, 0x0, 0x0, 0x0, 0x2d, 0x2e, 0x1, 0x0, 0x0, 0x0, 0x2d, + 0x2b, 0x1, 0x0, 0x0, 0x0, 0x2e, 0x30, 0x1, 0x0, 0x0, 0x0, 0x2f, 0x2d, + 0x1, 0x0, 0x0, 0x0, 0x30, 0x31, 0x5, 0x27, 0x0, 0x0, 0x31, 0x10, + 0x1, 0x0, 0x0, 0x0, 0x4, 0x0, 0x1e, 0x25, 0x2d, 0x1, 0x1, 0x4, 0x0, + }; + + size_t serializedATNSize = 0; + serializedATNSize += sizeof(serializedATNSegment0) / sizeof(serializedATNSegment0[0]); + staticData->serializedATN.reserve(serializedATNSize); + + staticData->serializedATN.insert(staticData->serializedATN.end(), serializedATNSegment0, + serializedATNSegment0 + sizeof(serializedATNSegment0) / sizeof(serializedATNSegment0[0])); + + atn::ATNDeserializer deserializer; + staticData->atn = deserializer.deserialize(staticData->serializedATN); + + size_t count = staticData->atn->getNumberOfDecisions(); + staticData->decisionToDFA.reserve(count); + for (size_t i = 0; i < count; i++) { + staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i); + } + XPathLexer_staticData = staticData.release(); +} + +} XPathLexer::XPathLexer(CharStream *input) : Lexer(input) { - _interpreter = new atn::LexerATNSimulator(this, *_atn, *_decisionToDFA, _sharedContextCache); + XPathLexer::initialize(); + _interpreter = new atn::LexerATNSimulator(this, *XPathLexer_staticData->atn, XPathLexer_staticData->decisionToDFA, XPathLexer_staticData->sharedContextCache); } XPathLexer::~XPathLexer() { @@ -21,30 +136,29 @@ std::string XPathLexer::getGrammarFileName() const { } const std::vector& XPathLexer::getRuleNames() const { - return _ruleNames; + return XPathLexer_staticData->ruleNames; } const std::vector& XPathLexer::getChannelNames() const { - return _channelNames; + return XPathLexer_staticData->channelNames; } const std::vector& XPathLexer::getModeNames() const { - return _modeNames; + return XPathLexer_staticData->modeNames; } -dfa::Vocabulary& XPathLexer::getVocabulary() const { - return _vocabulary; +const dfa::Vocabulary& XPathLexer::getVocabulary() const { + return XPathLexer_staticData->vocabulary; } const std::vector& XPathLexer::getSerializedATN() const { - return _serializedATN; + return XPathLexer_staticData->serializedATN; } const atn::ATN& XPathLexer::getATN() const { - return *_atn; + return *XPathLexer_staticData->atn; } - void XPathLexer::action(RuleContext *context, size_t ruleIndex, size_t actionIndex) { switch (ruleIndex) { case 4: IDAction(antlrcpp::downCast(context), actionIndex); break; @@ -68,95 +182,6 @@ void XPathLexer::IDAction(antlr4::RuleContext *context, size_t actionIndex) { } } - - -// Static vars and initialization. -std::vector* XPathLexer::_decisionToDFA = nullptr; -atn::PredictionContextCache XPathLexer::_sharedContextCache; - -// We own the ATN which in turn owns the ATN states. -atn::ATN* XPathLexer::_atn = nullptr; -std::vector XPathLexer::_serializedATN; - -std::vector XPathLexer::_ruleNames = { - "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", "NameChar", "NameStartChar", - "STRING" -}; - -std::vector XPathLexer::_channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN" -}; - -std::vector XPathLexer::_modeNames = { - "DEFAULT_MODE" -}; - -std::vector XPathLexer::_literalNames = { - "", "", "", "'//'", "'/'", "'*'", "'!'" -}; - -std::vector XPathLexer::_symbolicNames = { - "", "TOKEN_REF", "RULE_REF", "ANYWHERE", "ROOT", "WILDCARD", "BANG", "ID", - "STRING" -}; - -dfa::Vocabulary XPathLexer::_vocabulary(_literalNames, _symbolicNames); - -XPathLexer::Initializer::Initializer() { - static const uint16_t serializedATNSegment0[] = { - 0x4, 0x0, 0x8, 0x32, 0x6, 0xffff, 0x2, 0x0, 0x7, 0x0, 0x2, 0x1, 0x7, - 0x1, 0x2, 0x2, 0x7, 0x2, 0x2, 0x3, 0x7, 0x3, 0x2, 0x4, 0x7, 0x4, - 0x2, 0x5, 0x7, 0x5, 0x2, 0x6, 0x7, 0x6, 0x2, 0x7, 0x7, 0x7, 0x1, - 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, - 0x1, 0x3, 0x1, 0x3, 0x1, 0x4, 0x1, 0x4, 0x5, 0x4, 0x1d, 0x8, 0x4, - 0xa, 0x4, 0xc, 0x4, 0x20, 0x9, 0x4, 0x1, 0x4, 0x1, 0x4, 0x1, 0x5, - 0x1, 0x5, 0x3, 0x5, 0x26, 0x8, 0x5, 0x1, 0x6, 0x1, 0x6, 0x1, 0x7, - 0x1, 0x7, 0x5, 0x7, 0x2c, 0x8, 0x7, 0xa, 0x7, 0xc, 0x7, 0x2f, 0x9, - 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x2d, 0x0, 0x8, 0x1, 0x3, 0x3, 0x4, - 0x5, 0x5, 0x7, 0x6, 0x9, 0x7, 0xb, 0x0, 0xd, 0x0, 0xf, 0x8, 0x1, - 0x0, 0x2, 0x5, 0x0, 0x30, 0x39, 0x5f, 0x5f, 0xb7, 0xb7, 0x300, 0x36f, - 0x203f, 0x2040, 0xd, 0x0, 0x41, 0x5a, 0x61, 0x7a, 0xc0, 0xd6, 0xd8, - 0xf6, 0xf8, 0x2ff, 0x370, 0x37d, 0x37f, 0x1fff, 0x200c, 0x200d, 0x2070, - 0x218f, 0x2c00, 0x2fef, 0x3001, 0xd7ff, 0xf900, 0xfdcf, 0xfdf0, 0xffff, - 0x0, 0x32, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1, 0x0, 0x0, - 0x0, 0x0, 0x5, 0x1, 0x0, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, - 0x0, 0x9, 0x1, 0x0, 0x0, 0x0, 0x0, 0xf, 0x1, 0x0, 0x0, 0x0, 0x1, - 0x11, 0x1, 0x0, 0x0, 0x0, 0x3, 0x14, 0x1, 0x0, 0x0, 0x0, 0x5, 0x16, - 0x1, 0x0, 0x0, 0x0, 0x7, 0x18, 0x1, 0x0, 0x0, 0x0, 0x9, 0x1a, 0x1, - 0x0, 0x0, 0x0, 0xb, 0x25, 0x1, 0x0, 0x0, 0x0, 0xd, 0x27, 0x1, 0x0, - 0x0, 0x0, 0xf, 0x29, 0x1, 0x0, 0x0, 0x0, 0x11, 0x12, 0x5, 0x2f, 0x0, - 0x0, 0x12, 0x13, 0x5, 0x2f, 0x0, 0x0, 0x13, 0x2, 0x1, 0x0, 0x0, 0x0, - 0x14, 0x15, 0x5, 0x2f, 0x0, 0x0, 0x15, 0x4, 0x1, 0x0, 0x0, 0x0, 0x16, - 0x17, 0x5, 0x2a, 0x0, 0x0, 0x17, 0x6, 0x1, 0x0, 0x0, 0x0, 0x18, 0x19, - 0x5, 0x21, 0x0, 0x0, 0x19, 0x8, 0x1, 0x0, 0x0, 0x0, 0x1a, 0x1e, 0x3, - 0xd, 0x6, 0x0, 0x1b, 0x1d, 0x3, 0xb, 0x5, 0x0, 0x1c, 0x1b, 0x1, 0x0, - 0x0, 0x0, 0x1d, 0x20, 0x1, 0x0, 0x0, 0x0, 0x1e, 0x1c, 0x1, 0x0, 0x0, - 0x0, 0x1e, 0x1f, 0x1, 0x0, 0x0, 0x0, 0x1f, 0x21, 0x1, 0x0, 0x0, 0x0, - 0x20, 0x1e, 0x1, 0x0, 0x0, 0x0, 0x21, 0x22, 0x6, 0x4, 0x0, 0x0, 0x22, - 0xa, 0x1, 0x0, 0x0, 0x0, 0x23, 0x26, 0x3, 0xd, 0x6, 0x0, 0x24, 0x26, - 0x7, 0x0, 0x0, 0x0, 0x25, 0x23, 0x1, 0x0, 0x0, 0x0, 0x25, 0x24, 0x1, - 0x0, 0x0, 0x0, 0x26, 0xc, 0x1, 0x0, 0x0, 0x0, 0x27, 0x28, 0x7, 0x1, - 0x0, 0x0, 0x28, 0xe, 0x1, 0x0, 0x0, 0x0, 0x29, 0x2d, 0x5, 0x27, 0x0, - 0x0, 0x2a, 0x2c, 0x9, 0x0, 0x0, 0x0, 0x2b, 0x2a, 0x1, 0x0, 0x0, 0x0, - 0x2c, 0x2f, 0x1, 0x0, 0x0, 0x0, 0x2d, 0x2e, 0x1, 0x0, 0x0, 0x0, 0x2d, - 0x2b, 0x1, 0x0, 0x0, 0x0, 0x2e, 0x30, 0x1, 0x0, 0x0, 0x0, 0x2f, 0x2d, - 0x1, 0x0, 0x0, 0x0, 0x30, 0x31, 0x5, 0x27, 0x0, 0x0, 0x31, 0x10, - 0x1, 0x0, 0x0, 0x0, 0x4, 0x0, 0x1e, 0x25, 0x2d, 0x1, 0x1, 0x4, 0x0, - }; - - _serializedATN.insert(_serializedATN.end(), serializedATNSegment0, - serializedATNSegment0 + sizeof(serializedATNSegment0) / sizeof(serializedATNSegment0[0])); - - - atn::ATNDeserializer deserializer; - _atn = deserializer.deserialize(_serializedATN).release(); - - size_t count = _atn->getNumberOfDecisions(); - _decisionToDFA = new std::vector(); - _decisionToDFA->reserve(count); - for (size_t i = 0; i < count; i++) { - _decisionToDFA->emplace_back(_atn->getDecisionState(i), i); - } +void XPathLexer::initialize() { + std::call_once(XPathLexer_onceFlag, XPathLexer_initialize); } - -XPathLexer::Initializer XPathLexer::_init; diff --git a/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.h b/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.h index 0c794b1b40a..e35f15584d2 100644 --- a/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.h +++ b/runtime/Cpp/runtime/src/tree/xpath/XPathLexer.h @@ -7,8 +7,6 @@ #include "antlr4-runtime.h" - - class XPathLexer : public antlr4::Lexer { public: enum { @@ -17,41 +15,33 @@ class XPathLexer : public antlr4::Lexer { }; explicit XPathLexer(antlr4::CharStream *input); - ~XPathLexer(); + + ~XPathLexer() override; virtual std::string getGrammarFileName() const override; + virtual const std::vector& getRuleNames() const override; virtual const std::vector& getChannelNames() const override; + virtual const std::vector& getModeNames() const override; - virtual antlr4::dfa::Vocabulary& getVocabulary() const override; + + virtual const antlr4::dfa::Vocabulary& getVocabulary() const override; virtual const std::vector& getSerializedATN() const override; + virtual const antlr4::atn::ATN& getATN() const override; virtual void action(antlr4::RuleContext *context, size_t ruleIndex, size_t actionIndex) override; -private: - static std::vector *_decisionToDFA; - static antlr4::atn::PredictionContextCache _sharedContextCache; - static std::vector _ruleNames; - static std::vector _channelNames; - static std::vector _modeNames; - - static std::vector _literalNames; - static std::vector _symbolicNames; - static antlr4::dfa::Vocabulary _vocabulary; - static antlr4::atn::ATN *_atn; - static std::vector _serializedATN; - + // By default the static state used to implement the lexer is lazily initialized during the first + // call to the constructor. You can call this function if you wish to initialize the static state + // ahead of time. + static void initialize(); +private: // Individual action functions triggered by action() above. void IDAction(antlr4::RuleContext *context, size_t actionIndex); // Individual semantic predicate functions triggered by sempred() above. - - struct Initializer { - Initializer(); - }; - static Initializer _init; }; diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Cpp/Cpp.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Cpp/Cpp.stg index 3958d565329..305074f184d 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Cpp/Cpp.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Cpp/Cpp.stg @@ -64,38 +64,38 @@ public: explicit (antlr4::CharStream *input); - ~(); + + ~() override; - virtual std::string getGrammarFileName() const override; - virtual const std::vector\& getRuleNames() const override; - virtual const std::vector\& getChannelNames() const override; - virtual const std::vector\& getModeNames() const override; - virtual antlr4::dfa::Vocabulary& getVocabulary() const override; + std::string getGrammarFileName() const override; + + const std::vector\& getRuleNames() const override; + + const std::vector\& getChannelNames() const override; + + const std::vector\& getModeNames() const override; + + const antlr4::dfa::Vocabulary& getVocabulary() const override; virtual const std::vector\& getSerializedATN() const override; virtual const antlr4::atn::ATN& getATN() const override; - virtual void action(antlr4::RuleContext *context, size_t ruleIndex, size_t actionIndex) override; + void action(antlr4::RuleContext *context, size_t ruleIndex, size_t actionIndex) override; + - virtual bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override; + bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override; -private: - static std::vector\ *_decisionToDFA; - static antlr4::atn::PredictionContextCache _sharedContextCache; - static std::vector\ _ruleNames; - static std::vector\ _channelNames; - static std::vector\ _modeNames; - - static std::vector\ _literalNames; - static std::vector\ _symbolicNames; - static antlr4::dfa::Vocabulary _vocabulary; - + // By default the static state used to implement the lexer is lazily initialized during the first + // call to the constructor. You can call this function if you wish to initialize the static state + // ahead of time. + static void initialize(); +private: // Individual action functions triggered by action() above. @@ -104,16 +104,73 @@ private: // Individual semantic predicate functions triggered by sempred() above. - struct Initializer { - Initializer(); - }; - static Initializer _init; + }; >> Lexer(lexer, atn, actionFuncs, sempredFuncs, superClass = {Lexer}) ::= << + +namespace { + +struct _StaticData final { + _StaticData(std::vector\ ruleNames, + std::vector\ channelNames, + std::vector\ modeNames, + std::vector\ literalNames, + std::vector\ symbolicNames) + : ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)), + modeNames(std::move(modeNames)), literalNames(std::move(literalNames)), + symbolicNames(std::move(symbolicNames)), + vocabulary(this->literalNames, this->symbolicNames) {} + + _StaticData(const _StaticData&) = delete; + _StaticData(_StaticData&&) = delete; + _StaticData& operator=(const _StaticData&) = delete; + _StaticData& operator=(_StaticData&&) = delete; + + std::vector\ decisionToDFA; + antlr4::atn::PredictionContextCache sharedContextCache; + const std::vector\ ruleNames; + const std::vector\ channelNames; + const std::vector\ modeNames; + const std::vector\ literalNames; + const std::vector\ symbolicNames; + const antlr4::dfa::Vocabulary vocabulary; + std::vector\ serializedATN; + std::unique_ptr\ atn; +}; + +std::once_flag _onceFlag; +_StaticData *_staticData = nullptr; + +void _initialize() { + assert(_staticData == nullptr); + auto staticData = std::make_unique\<_StaticData>( + std::vector\{ + "}; separator = ", ", wrap, anchor> + }, + std::vector\{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", "}; separator = ", ", wrap, anchor> + }, + std::vector\{ + "}; separator = ", ", wrap, anchor> + }, + std::vector\{ + }; null = "\"\"", separator = ", ", wrap, anchor> + }, + std::vector\{ + }; null = "\"\"", separator = ", ", wrap, anchor> + } + ); + + _staticData = staticData.release(); +} + +} + ::(CharStream *input) : (input) { - _interpreter = new atn::LexerATNSimulator(this, *_atn, *_decisionToDFA, _sharedContextCache); + ::initialize(); + _interpreter = new atn::LexerATNSimulator(this, *_staticData->atn, _staticData->decisionToDFA, _staticData->sharedContextCache); } ::~() { @@ -125,27 +182,27 @@ std::string ::getGrammarFileName() const { } const std::vector\& ::getRuleNames() const { - return _ruleNames; + return _staticData->ruleNames; } const std::vector\& ::getChannelNames() const { - return _channelNames; + return _staticData->channelNames; } const std::vector\& ::getModeNames() const { - return _modeNames; + return _staticData->modeNames; } -dfa::Vocabulary& ::getVocabulary() const { - return _vocabulary; +const dfa::Vocabulary& ::getVocabulary() const { + return _staticData->vocabulary; } const std::vector\& ::getSerializedATN() const { - return _serializedATN; + return _staticData->serializedATN; } const atn::ATN& ::getATN() const { - return *_atn; + return *_staticData->atn; } @@ -177,41 +234,9 @@ bool ::sempred(RuleContext *context, size_t ruleIndex, size_t predic -// Static vars and initialization. -std::vector\* ::_decisionToDFA = nullptr; -atn::PredictionContextCache ::_sharedContextCache; - -// We own the ATN which in turn owns the ATN states. -atn::ATN* ::_atn = nullptr; -std::vector\ ::_serializedATN; - -std::vector\ ::_ruleNames = { - "}; separator = ", ", wrap, anchor> -}; - -std::vector\ ::_channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN", "}; separator = ", ", wrap, anchor> -}; - -std::vector\ ::_modeNames = { - "}; separator = ", ", wrap, anchor> -}; - -std::vector\ ::_literalNames = { - }; null = "\"\"", separator = ", ", wrap, anchor> -}; - -std::vector\ ::_symbolicNames = { - }; null = "\"\"", separator = ", ", wrap, anchor> -}; - -dfa::Vocabulary ::_vocabulary(_literalNames, _symbolicNames); - -::Initializer::Initializer() { - +void ::initialize() { + std::call_once(_onceFlag, _initialize); } - -::Initializer ::_init; >> RuleActionFunctionHeader(r, actions) ::= << @@ -269,12 +294,18 @@ public: explicit (antlr4::TokenStream *input); - ~(); - virtual std::string getGrammarFileName() const override; - virtual const antlr4::atn::ATN& getATN() const override { return *_atn; }; - virtual const std::vector\& getRuleNames() const override; - virtual antlr4::dfa::Vocabulary& getVocabulary() const override; + ~() override; + + std::string getGrammarFileName() const override; + + const antlr4::atn::ATN& getATN() const override; + + const std::vector\& getRuleNames() const override; + + const antlr4::dfa::Vocabulary& getVocabulary() const override; + + const std::vector\& getSerializedATN() const override; @@ -283,50 +314,99 @@ public: - virtual bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override; + bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override; + -private: - static std::vector\ *_decisionToDFA; - static antlr4::atn::PredictionContextCache _sharedContextCache; - static std::vector\ _ruleNames; - - static std::vector\ _literalNames; - static std::vector\ _symbolicNames; - static antlr4::dfa::Vocabulary _vocabulary; - + // By default the static state used to implement the parser is lazily initialized during the first + // call to the constructor. You can call this function if you wish to initialize the static state + // ahead of time. + static void initialize(); +private: - - struct Initializer { - Initializer(); - }; - static Initializer _init; }; >> Parser(parser, funcs, atn, sempredFuncs, superClass = {Parser}) ::= << + +namespace { + +struct _StaticData final { + _StaticData(std::vector\ ruleNames, + std::vector\ literalNames, + std::vector\ symbolicNames) + : ruleNames(std::move(ruleNames)), literalNames(std::move(literalNames)), + symbolicNames(std::move(symbolicNames)), + vocabulary(this->literalNames, this->symbolicNames) {} + + _StaticData(const _StaticData&) = delete; + _StaticData(_StaticData&&) = delete; + _StaticData& operator=(const _StaticData&) = delete; + _StaticData& operator=(_StaticData&&) = delete; + + std::vector\ decisionToDFA; + antlr4::atn::PredictionContextCache sharedContextCache; + const std::vector\ ruleNames; + const std::vector\ literalNames; + const std::vector\ symbolicNames; + const antlr4::dfa::Vocabulary vocabulary; + std::vector\ serializedATN; + std::unique_ptr\ atn; +}; + +std::once_flag _onceFlag; +_StaticData *_staticData = nullptr; + +void _initialize() { + assert(_staticData == nullptr); + auto staticData = std::make_unique\<_StaticData>( + std::vector\{ + "}; separator = ", ", wrap, anchor> + }, + std::vector\{ + }; null = "\"\"", separator = ", ", wrap, anchor> + }, + std::vector\{ + }; null = "\"\"", separator = ", ", wrap, anchor> + } + ); + + _staticData = staticData.release(); +} + +} + using namespace antlr4; ::(TokenStream *input) : (input) { - _interpreter = new atn::ParserATNSimulator(this, *_atn, *_decisionToDFA, _sharedContextCache); + ::initialize(); + _interpreter = new atn::ParserATNSimulator(this, *_staticData->atn, _staticData->decisionToDFA, _staticData->sharedContextCache); } ::~() { delete _interpreter; } +const atn::ATN& ::getATN() const { + return *_staticData->atn; +} + std::string ::getGrammarFileName() const { return ""; } const std::vector\& ::getRuleNames() const { - return _ruleNames; + return _staticData->ruleNames; +} + +const dfa::Vocabulary& ::getVocabulary() const { + return _staticData->vocabulary; } -dfa::Vocabulary& ::getVocabulary() const { - return _vocabulary; +const std::vector\& ::getSerializedATN() const { + return _staticData->serializedATN; } @@ -347,57 +427,29 @@ bool ::sempred(RuleContext *context, size_t ruleIndex, size_t predi -// Static vars and initialization. -std::vector\* ::_decisionToDFA = nullptr; -atn::PredictionContextCache ::_sharedContextCache; - -// We own the ATN which in turn owns the ATN states. -atn::ATN* ::_atn = nullptr; -std::vector\ ::_serializedATN; - -std::vector\ ::_ruleNames = { - "}; separator = ", ", wrap, anchor> -}; - -std::vector\ ::_literalNames = { - }; null = "\"\"", separator = ", ", wrap, anchor> -}; - -std::vector\ ::_symbolicNames = { - }; null = "\"\"", separator = ", ", wrap, anchor> -}; - -dfa::Vocabulary ::_vocabulary(_literalNames, _symbolicNames); - -::Initializer::Initializer() { - +void ::initialize() { + std::call_once(_onceFlag, _initialize); } - -::Initializer ::_init; >> SerializedATNHeader(model) ::= << -static antlr4::atn::ATN *_atn; -static std::vector\ _serializedATN; >> -// Constructs the serialized ATN and writes init code for static member vars. SerializedATN(model) ::= << static const uint16_t serializedATNSegment[] = { }; separator=",", wrap> }; - -_serializedATN.insert(_serializedATN.end(), serializedATNSegment, +staticData->serializedATN.reserve(sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0])); +staticData->serializedATN.insert(staticData->serializedATN.end(), serializedATNSegment, serializedATNSegment + sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0])); atn::ATNDeserializer deserializer; -_atn = deserializer.deserialize(_serializedATN).release(); +staticData->atn = deserializer.deserialize(staticData->serializedATN); -size_t count = _atn->getNumberOfDecisions(); -_decisionToDFA = new std::vector\(); -_decisionToDFA->reserve(count); +const size_t count = staticData->atn->getNumberOfDecisions(); +staticData->decisionToDFA.reserve(count); for (size_t i = 0; i \< count; i++) { - _decisionToDFA->emplace_back(_atn->getDecisionState(i), i); + staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i); } >>