Skip to content

Commit

Permalink
Merge pull request #3326 from jcking/cpp-guid-cache
Browse files Browse the repository at this point in the history
[C++] Cleanup ATNDeserializer interface
  • Loading branch information
parrt authored Nov 28, 2021
2 parents aeaa445 + 7fb7373 commit 1493859
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ public String execModule(String fileName) {
}

try {
List<String> command2 = new ArrayList<String>(Arrays.asList("clang++", "-std=c++11", "-I", includePath, "-L.", "-lantlr4-runtime", "-o", "a.out"));
List<String> command2 = new ArrayList<String>(Arrays.asList("clang++", "-std=c++11", "-I", includePath, "-L.", "-lantlr4-runtime", "-pthread", "-o", "a.out"));
command2.addAll(allCppFiles(getTempDirPath()));
if (runCommand(command2.toArray(new String[0]), getTempDirPath(), "building test binary", true) == null) {
return null;
Expand Down
4 changes: 2 additions & 2 deletions runtime/Cpp/runtime/src/atn/ATNConfigSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ std::vector<ATNState*> ATNConfigSet::getStates() {

BitSet ATNConfigSet::getAlts() {
BitSet alts;
for (const ATNConfig &config : configs) {
alts.set(config.alt);
for (const auto &config : configs) {
alts.set(config->alt);
}
return alts;
}
Expand Down
54 changes: 22 additions & 32 deletions runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,51 @@
*/

#include "atn/ATNDeserializationOptions.h"
#include "Exceptions.h"

#include <memory>
#include <mutex>

using namespace antlr4;
using namespace antlr4::atn;

const ATNDeserializationOptions ATNDeserializationOptions::defaultOptions;
namespace {

ATNDeserializationOptions::ATNDeserializationOptions() {
InitializeInstanceFields();
}
std::once_flag defaultATNDeserializationOptionsOnceFlag;
std::unique_ptr<ATNDeserializationOptions> defaultATNDeserializationOptions;

ATNDeserializationOptions::ATNDeserializationOptions(ATNDeserializationOptions *options) : ATNDeserializationOptions() {
this->verifyATN = options->verifyATN;
this->generateRuleBypassTransitions = options->generateRuleBypassTransitions;
void initializeDefaultATNDeserializationOptions() {
defaultATNDeserializationOptions.reset(new ATNDeserializationOptions());
}

ATNDeserializationOptions::~ATNDeserializationOptions() {
}

const ATNDeserializationOptions& ATNDeserializationOptions::getDefaultOptions() {
return defaultOptions;
}
ATNDeserializationOptions::ATNDeserializationOptions(ATNDeserializationOptions *options)
: _readOnly(false), _verifyATN(options->_verifyATN),
_generateRuleBypassTransitions(options->_generateRuleBypassTransitions) {}

bool ATNDeserializationOptions::isReadOnly() {
return readOnly;
const ATNDeserializationOptions& ATNDeserializationOptions::getDefaultOptions() {
std::call_once(defaultATNDeserializationOptionsOnceFlag,
initializeDefaultATNDeserializationOptions);
return *defaultATNDeserializationOptions;
}

void ATNDeserializationOptions::makeReadOnly() {
readOnly = true;
}

bool ATNDeserializationOptions::isVerifyATN() {
return verifyATN;
_readOnly = true;
}

void ATNDeserializationOptions::setVerifyATN(bool verify) {
throwIfReadOnly();
verifyATN = verify;
}

bool ATNDeserializationOptions::isGenerateRuleBypassTransitions() {
return generateRuleBypassTransitions;
_verifyATN = verify;
}

void ATNDeserializationOptions::setGenerateRuleBypassTransitions(bool generate) {
throwIfReadOnly();
generateRuleBypassTransitions = generate;
_generateRuleBypassTransitions = generate;
}

void ATNDeserializationOptions::throwIfReadOnly() {
void ATNDeserializationOptions::throwIfReadOnly() const {
if (isReadOnly()) {
throw "The object is read only.";
throw IllegalStateException("ATNDeserializationOptions is read only.");
}
}

void ATNDeserializationOptions::InitializeInstanceFields() {
readOnly = false;
verifyATN = true;
generateRuleBypassTransitions = false;
}
46 changes: 22 additions & 24 deletions runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,39 @@
namespace antlr4 {
namespace atn {

class ANTLR4CPP_PUBLIC ATNDeserializationOptions {
private:
static const ATNDeserializationOptions defaultOptions;
class ANTLR4CPP_PUBLIC ATNDeserializationOptions final {
public:
ATNDeserializationOptions()
: _readOnly(false), _verifyATN(true), _generateRuleBypassTransitions(false) {}

bool readOnly;
bool verifyATN;
bool generateRuleBypassTransitions;
// TODO: Is this useful? If so we should mark it as explicit, otherwise remove it.
ATNDeserializationOptions(ATNDeserializationOptions *options);

public:
ATNDeserializationOptions();
ATNDeserializationOptions(ATNDeserializationOptions *options);
ATNDeserializationOptions(ATNDeserializationOptions const&) = default;
virtual ~ATNDeserializationOptions();
ATNDeserializationOptions& operator=(ATNDeserializationOptions const&) = default;
ATNDeserializationOptions(const ATNDeserializationOptions&) = default;

static const ATNDeserializationOptions& getDefaultOptions();
ATNDeserializationOptions& operator=(const ATNDeserializationOptions&) = default;

bool isReadOnly();
static const ATNDeserializationOptions& getDefaultOptions();

void makeReadOnly();
bool isReadOnly() const { return _readOnly; }

bool isVerifyATN();
void makeReadOnly();

void setVerifyATN(bool verify);
bool isVerifyATN() const { return _verifyATN; }

bool isGenerateRuleBypassTransitions();
void setVerifyATN(bool verify);

void setGenerateRuleBypassTransitions(bool generate);
bool isGenerateRuleBypassTransitions() const { return _generateRuleBypassTransitions; }

protected:
virtual void throwIfReadOnly();
void setGenerateRuleBypassTransitions(bool generate);

private:
void InitializeInstanceFields();
};
private:
void throwIfReadOnly() const;

bool _readOnly;
bool _verifyATN;
bool _generateRuleBypassTransitions;
};

} // namespace atn
} // namespace antlr4
63 changes: 49 additions & 14 deletions runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,47 @@

#include "atn/ATNDeserializer.h"

#include <mutex>
#include <string>
#include <vector>

using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;

namespace {

struct WellKnownUuids final {
WellKnownUuids() = default;

WellKnownUuids(const WellKnownUuids&) = delete;

WellKnownUuids(WellKnownUuids&&) = delete;

antlrcpp::Guid addedPrecedenceTransitions;
antlrcpp::Guid addedLexerActions;
antlrcpp::Guid addedUnicodeSmp;
antlrcpp::Guid baseSerialized;
std::vector<antlrcpp::Guid> supported;
};

std::once_flag wellKnownUuidsOnceFlag;
std::unique_ptr<WellKnownUuids> wellKnownUuids;

void initializeWellKnownUuids() {
wellKnownUuids.reset(new WellKnownUuids());
wellKnownUuids->addedPrecedenceTransitions = antlrcpp::Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61");
wellKnownUuids->addedLexerActions = antlrcpp::Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E");
wellKnownUuids->addedUnicodeSmp = antlrcpp::Guid("59627784-3BE5-417A-B9EB-8131A7286089");
wellKnownUuids->baseSerialized = antlrcpp::Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3");
wellKnownUuids->supported.assign({
wellKnownUuids->baseSerialized, wellKnownUuids->addedPrecedenceTransitions,
wellKnownUuids->addedLexerActions, wellKnownUuids->addedUnicodeSmp});
wellKnownUuids->supported.shrink_to_fit();
}

uint32_t deserializeInt32(const std::vector<uint16_t>& data, size_t offset) {
return (uint32_t)data[offset] | ((uint32_t)data[offset + 1] << 16);
return static_cast<uint32_t>(data[offset]) | (static_cast<uint32_t>(data[offset + 1]) << 16);
}

ssize_t readUnicodeInt(const std::vector<uint16_t>& data, int& p) {
Expand Down Expand Up @@ -105,7 +136,7 @@ void deserializeSets(
ATNDeserializer::ATNDeserializer(): ATNDeserializer(ATNDeserializationOptions::getDefaultOptions()) {
}

ATNDeserializer::ATNDeserializer(const ATNDeserializationOptions& dso): deserializationOptions(dso) {
ATNDeserializer::ATNDeserializer(const ATNDeserializationOptions& dso): _deserializationOptions(dso) {
}

ATNDeserializer::~ATNDeserializer() {
Expand All @@ -116,28 +147,32 @@ ATNDeserializer::~ATNDeserializer() {
* reflected as change in the unique ID SERIALIZED_UUID.
*/
antlrcpp::Guid ATNDeserializer::ADDED_PRECEDENCE_TRANSITIONS() {
return antlrcpp::Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61");
std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids);
return wellKnownUuids->addedPrecedenceTransitions;
}

antlrcpp::Guid ATNDeserializer::ADDED_LEXER_ACTIONS() {
return antlrcpp::Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E");
std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids);
return wellKnownUuids->addedLexerActions;
}

antlrcpp::Guid ATNDeserializer::ADDED_UNICODE_SMP() {
return antlrcpp::Guid("59627784-3BE5-417A-B9EB-8131A7286089");
std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids);
return wellKnownUuids->addedUnicodeSmp;
}

antlrcpp::Guid ATNDeserializer::SERIALIZED_UUID() {
return ADDED_UNICODE_SMP();
}

antlrcpp::Guid ATNDeserializer::BASE_SERIALIZED_UUID() {
return antlrcpp::Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3");
std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids);
return wellKnownUuids->baseSerialized;
}

std::vector<antlrcpp::Guid>& ATNDeserializer::SUPPORTED_UUIDS() {
static std::vector<antlrcpp::Guid> singleton = { BASE_SERIALIZED_UUID(), ADDED_PRECEDENCE_TRANSITIONS(), ADDED_LEXER_ACTIONS(), ADDED_UNICODE_SMP() };
return singleton;
const std::vector<antlrcpp::Guid>& ATNDeserializer::SUPPORTED_UUIDS() {
std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids);
return wellKnownUuids->supported;
}

bool ATNDeserializer::isFeatureSupported(const antlrcpp::Guid &feature, const antlrcpp::Guid &actualUuid) {
Expand Down Expand Up @@ -433,11 +468,11 @@ ATN ATNDeserializer::deserialize(const std::vector<uint16_t>& input) {

markPrecedenceDecisions(atn);

if (deserializationOptions.isVerifyATN()) {
if (_deserializationOptions.isVerifyATN()) {
verifyATN(atn);
}

if (deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType::PARSER) {
if (_deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType::PARSER) {
atn.ruleToTokenType.resize(atn.ruleToStartState.size());
for (size_t i = 0; i < atn.ruleToStartState.size(); i++) {
atn.ruleToTokenType[i] = int(atn.maxTokenType + i + 1);
Expand Down Expand Up @@ -521,7 +556,7 @@ ATN ATNDeserializer::deserialize(const std::vector<uint16_t>& input) {
bypassStart->addTransition(new EpsilonTransition(matchState)); /* mem check: freed in ATNState d-tor */
}

if (deserializationOptions.isVerifyATN()) {
if (_deserializationOptions.isVerifyATN()) {
// reverify after modification
verifyATN(atn);
}
Expand All @@ -537,7 +572,7 @@ ATN ATNDeserializer::deserialize(const std::vector<uint16_t>& input) {
*
* @param atn The ATN.
*/
void ATNDeserializer::markPrecedenceDecisions(const ATN &atn) {
void ATNDeserializer::markPrecedenceDecisions(const ATN &atn) const {
for (ATNState *state : atn.states) {
if (!is<StarLoopEntryState *>(state)) {
continue;
Expand Down Expand Up @@ -723,7 +758,7 @@ ATNState* ATNDeserializer::stateFactory(size_t type, size_t ruleIndex) {
return s;
}

Ref<LexerAction> ATNDeserializer::lexerActionFactory(LexerActionType type, int data1, int data2) {
Ref<LexerAction> ATNDeserializer::lexerActionFactory(LexerActionType type, int data1, int data2) const {
switch (type) {
case LexerActionType::CHANNEL:
return std::make_shared<LexerChannelAction>(data1);
Expand Down
Loading

0 comments on commit 1493859

Please sign in to comment.