First commit
This commit is contained in:
228
runtime-linux/antlr4-runtime/atn/ATNConfigSet.cpp
Executable file
228
runtime-linux/antlr4-runtime/atn/ATNConfigSet.cpp
Executable file
@@ -0,0 +1,228 @@
|
||||
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
||||
* Use of this file is governed by the BSD 3-clause license that
|
||||
* can be found in the LICENSE.txt file in the project root.
|
||||
*/
|
||||
|
||||
#include "atn/PredictionContext.h"
|
||||
#include "atn/ATNConfig.h"
|
||||
#include "atn/ATNSimulator.h"
|
||||
#include "Exceptions.h"
|
||||
#include "atn/SemanticContext.h"
|
||||
#include "support/Arrays.h"
|
||||
|
||||
#include "atn/ATNConfigSet.h"
|
||||
|
||||
using namespace antlr4::atn;
|
||||
using namespace antlrcpp;
|
||||
|
||||
ATNConfigSet::ATNConfigSet(bool fullCtx) : fullCtx(fullCtx) {
|
||||
InitializeInstanceFields();
|
||||
}
|
||||
|
||||
ATNConfigSet::ATNConfigSet(const Ref<ATNConfigSet> &old) : ATNConfigSet(old->fullCtx) {
|
||||
addAll(old);
|
||||
uniqueAlt = old->uniqueAlt;
|
||||
conflictingAlts = old->conflictingAlts;
|
||||
hasSemanticContext = old->hasSemanticContext;
|
||||
dipsIntoOuterContext = old->dipsIntoOuterContext;
|
||||
}
|
||||
|
||||
ATNConfigSet::~ATNConfigSet() {
|
||||
}
|
||||
|
||||
bool ATNConfigSet::add(const Ref<ATNConfig> &config) {
|
||||
return add(config, nullptr);
|
||||
}
|
||||
|
||||
bool ATNConfigSet::add(const Ref<ATNConfig> &config, PredictionContextMergeCache *mergeCache) {
|
||||
if (_readonly) {
|
||||
throw IllegalStateException("This set is readonly");
|
||||
}
|
||||
if (config->semanticContext != SemanticContext::NONE) {
|
||||
hasSemanticContext = true;
|
||||
}
|
||||
if (config->getOuterContextDepth() > 0) {
|
||||
dipsIntoOuterContext = true;
|
||||
}
|
||||
|
||||
size_t hash = getHash(config.get());
|
||||
ATNConfig *existing = _configLookup[hash];
|
||||
if (existing == nullptr) {
|
||||
_configLookup[hash] = config.get();
|
||||
_cachedHashCode = 0;
|
||||
configs.push_back(config); // track order here
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// a previous (s,i,pi,_), merge with it and save result
|
||||
bool rootIsWildcard = !fullCtx;
|
||||
Ref<PredictionContext> merged = PredictionContext::merge(existing->context, config->context, rootIsWildcard, mergeCache);
|
||||
// no need to check for existing.context, config.context in cache
|
||||
// since only way to create new graphs is "call rule" and here. We
|
||||
// cache at both places.
|
||||
existing->reachesIntoOuterContext = std::max(existing->reachesIntoOuterContext, config->reachesIntoOuterContext);
|
||||
|
||||
// make sure to preserve the precedence filter suppression during the merge
|
||||
if (config->isPrecedenceFilterSuppressed()) {
|
||||
existing->setPrecedenceFilterSuppressed(true);
|
||||
}
|
||||
|
||||
existing->context = merged; // replace context; no need to alt mapping
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ATNConfigSet::addAll(const Ref<ATNConfigSet> &other) {
|
||||
for (auto &c : other->configs) {
|
||||
add(c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<ATNState*> ATNConfigSet::getStates() {
|
||||
std::vector<ATNState*> states;
|
||||
for (auto c : configs) {
|
||||
states.push_back(c->state);
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the complete set of represented alternatives for the configuration
|
||||
* set.
|
||||
*
|
||||
* @return the set of represented alternatives in this configuration set
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
|
||||
BitSet ATNConfigSet::getAlts() {
|
||||
BitSet alts;
|
||||
for (ATNConfig config : configs) {
|
||||
alts.set(config.alt);
|
||||
}
|
||||
return alts;
|
||||
}
|
||||
|
||||
std::vector<Ref<SemanticContext>> ATNConfigSet::getPredicates() {
|
||||
std::vector<Ref<SemanticContext>> preds;
|
||||
for (auto c : configs) {
|
||||
if (c->semanticContext != SemanticContext::NONE) {
|
||||
preds.push_back(c->semanticContext);
|
||||
}
|
||||
}
|
||||
return preds;
|
||||
}
|
||||
|
||||
Ref<ATNConfig> ATNConfigSet::get(size_t i) const {
|
||||
return configs[i];
|
||||
}
|
||||
|
||||
void ATNConfigSet::optimizeConfigs(ATNSimulator *interpreter) {
|
||||
if (_readonly) {
|
||||
throw IllegalStateException("This set is readonly");
|
||||
}
|
||||
if (_configLookup.empty())
|
||||
return;
|
||||
|
||||
for (auto &config : configs) {
|
||||
config->context = interpreter->getCachedContext(config->context);
|
||||
}
|
||||
}
|
||||
|
||||
bool ATNConfigSet::operator == (const ATNConfigSet &other) {
|
||||
if (&other == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (configs.size() != other.configs.size())
|
||||
return false;
|
||||
|
||||
if (fullCtx != other.fullCtx || uniqueAlt != other.uniqueAlt ||
|
||||
conflictingAlts != other.conflictingAlts || hasSemanticContext != other.hasSemanticContext ||
|
||||
dipsIntoOuterContext != other.dipsIntoOuterContext) // includes stack context
|
||||
return false;
|
||||
|
||||
return Arrays::equals(configs, other.configs);
|
||||
}
|
||||
|
||||
size_t ATNConfigSet::hashCode() {
|
||||
if (!isReadonly() || _cachedHashCode == 0) {
|
||||
_cachedHashCode = 1;
|
||||
for (auto &i : configs) {
|
||||
_cachedHashCode = 31 * _cachedHashCode + i->hashCode(); // Same as Java's list hashCode impl.
|
||||
}
|
||||
}
|
||||
|
||||
return _cachedHashCode;
|
||||
}
|
||||
|
||||
size_t ATNConfigSet::size() {
|
||||
return configs.size();
|
||||
}
|
||||
|
||||
bool ATNConfigSet::isEmpty() {
|
||||
return configs.empty();
|
||||
}
|
||||
|
||||
void ATNConfigSet::clear() {
|
||||
if (_readonly) {
|
||||
throw IllegalStateException("This set is readonly");
|
||||
}
|
||||
configs.clear();
|
||||
_cachedHashCode = 0;
|
||||
_configLookup.clear();
|
||||
}
|
||||
|
||||
bool ATNConfigSet::isReadonly() {
|
||||
return _readonly;
|
||||
}
|
||||
|
||||
void ATNConfigSet::setReadonly(bool readonly) {
|
||||
_readonly = readonly;
|
||||
_configLookup.clear();
|
||||
}
|
||||
|
||||
std::string ATNConfigSet::toString() {
|
||||
std::stringstream ss;
|
||||
ss << "[";
|
||||
for (size_t i = 0; i < configs.size(); i++) {
|
||||
ss << configs[i]->toString();
|
||||
}
|
||||
ss << "]";
|
||||
|
||||
if (hasSemanticContext) {
|
||||
ss << ",hasSemanticContext = " << hasSemanticContext;
|
||||
}
|
||||
if (uniqueAlt != ATN::INVALID_ALT_NUMBER) {
|
||||
ss << ",uniqueAlt = " << uniqueAlt;
|
||||
}
|
||||
|
||||
if (conflictingAlts.size() > 0) {
|
||||
ss << ",conflictingAlts = ";
|
||||
ss << conflictingAlts.toString();
|
||||
}
|
||||
|
||||
if (dipsIntoOuterContext) {
|
||||
ss << ", dipsIntoOuterContext";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
size_t ATNConfigSet::getHash(ATNConfig *c) {
|
||||
size_t hashCode = 7;
|
||||
hashCode = 31 * hashCode + c->state->stateNumber;
|
||||
hashCode = 31 * hashCode + c->alt;
|
||||
hashCode = 31 * hashCode + c->semanticContext->hashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
void ATNConfigSet::InitializeInstanceFields() {
|
||||
uniqueAlt = 0;
|
||||
hasSemanticContext = false;
|
||||
dipsIntoOuterContext = false;
|
||||
|
||||
_readonly = false;
|
||||
_cachedHashCode = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user