Stop unnecessary evaluation when parsing constant names
This commit is contained in:
parent
06ff213691
commit
c4adcc2963
7 changed files with 69 additions and 40 deletions
|
@ -44,7 +44,6 @@ The filepath that Porymap expects for each file can be overridden under the ``Pr
|
|||
include/constants/global.h, yes, no, ``constants_global``, reads ``OBJECT_EVENT_TEMPLATES_COUNT``
|
||||
include/constants/map_groups.h, no, yes, ``constants_map_groups``,
|
||||
include/constants/items.h, yes, no, ``constants_items``,
|
||||
include/constants/opponents.h, yes, no, ``constants_opponents``, reads max trainers constant
|
||||
include/constants/flags.h, yes, no, ``constants_flags``,
|
||||
include/constants/vars.h, yes, no, ``constants_vars``,
|
||||
include/constants/weather.h, yes, no, ``constants_weather``,
|
||||
|
|
|
@ -196,7 +196,6 @@ enum ProjectFilePath {
|
|||
constants_global,
|
||||
constants_map_groups,
|
||||
constants_items,
|
||||
constants_opponents,
|
||||
constants_flags,
|
||||
constants_vars,
|
||||
constants_weather,
|
||||
|
|
|
@ -56,7 +56,8 @@ public:
|
|||
QMap<QString, QString> readCIncbinMulti(const QString &filepath);
|
||||
QStringList readCIncbinArray(const QString &filename, const QString &label);
|
||||
QMap<QString, int> readCDefines(const QString &filename, const QStringList &prefixes, QMap<QString, int> = { });
|
||||
QStringList readCDefinesSorted(const QString&, const QStringList&, const QMap<QString, int>& = { });
|
||||
QStringList readCDefineNames(const QString&, const QStringList&);
|
||||
QStringList readCDefineNamesByValue(const QString&, const QStringList&, const QMap<QString, int>& = { });
|
||||
QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
|
||||
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
||||
QStringList getLabelValues(const QList<QStringList>&, const QString&);
|
||||
|
@ -89,6 +90,7 @@ private:
|
|||
QString file;
|
||||
QString curDefine;
|
||||
QHash<QString, QStringList> errorMap;
|
||||
QString readCDefinesFile(const QString &filename);
|
||||
QList<Token> tokenizeExpression(QString expression, const QMap<QString, int> &knownIdentifiers);
|
||||
QList<Token> generatePostfix(const QList<Token> &tokens);
|
||||
int evaluatePostfix(const QList<Token> &postfix);
|
||||
|
|
|
@ -42,7 +42,6 @@ const QMap<ProjectFilePath, std::pair<QString, QString>> ProjectConfig::defaultP
|
|||
{ProjectFilePath::constants_global, { "constants_global", "include/constants/global.h"}},
|
||||
{ProjectFilePath::constants_map_groups, { "constants_map_groups", "include/constants/map_groups.h"}},
|
||||
{ProjectFilePath::constants_items, { "constants_items", "include/constants/items.h"}},
|
||||
{ProjectFilePath::constants_opponents, { "constants_opponents", "include/constants/opponents.h"}},
|
||||
{ProjectFilePath::constants_flags, { "constants_flags", "include/constants/flags.h"}},
|
||||
{ProjectFilePath::constants_vars, { "constants_vars", "include/constants/vars.h"}},
|
||||
{ProjectFilePath::constants_weather, { "constants_weather", "include/constants/weather.h"}},
|
||||
|
|
|
@ -334,16 +334,12 @@ QStringList ParseUtil::readCIncbinArray(const QString &filename, const QString &
|
|||
return paths;
|
||||
}
|
||||
|
||||
QMap<QString, int> ParseUtil::readCDefines(const QString &filename,
|
||||
const QStringList &prefixes,
|
||||
QMap<QString, int> allDefines)
|
||||
QString ParseUtil::readCDefinesFile(const QString &filename)
|
||||
{
|
||||
QMap<QString, int> filteredDefines;
|
||||
|
||||
this->file = filename;
|
||||
|
||||
if (this->file.isEmpty()) {
|
||||
return filteredDefines;
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString filepath = this->root + "/" + this->file;
|
||||
|
@ -351,13 +347,27 @@ QMap<QString, int> ParseUtil::readCDefines(const QString &filename,
|
|||
|
||||
if (this->text.isNull()) {
|
||||
logError(QString("Failed to read C defines file: '%1'").arg(filepath));
|
||||
return filteredDefines;
|
||||
return QString();
|
||||
}
|
||||
|
||||
static const QRegularExpression re_extraChars("(//.*)|(\\/+\\*+[^*]*\\*+\\/+)");
|
||||
this->text.replace(re_extraChars, "");
|
||||
static const QRegularExpression re_extraSpaces("(\\\\\\s+)");
|
||||
this->text.replace(re_extraSpaces, "");
|
||||
return this->text;
|
||||
}
|
||||
|
||||
QMap<QString, int> ParseUtil::readCDefines(const QString &filename,
|
||||
const QStringList &prefixes,
|
||||
QMap<QString, int> allDefines)
|
||||
{
|
||||
QMap<QString, int> filteredDefines;
|
||||
|
||||
this->text = this->readCDefinesFile(filename);
|
||||
if (this->text.isEmpty()) {
|
||||
return filteredDefines;
|
||||
}
|
||||
|
||||
allDefines.insert("FALSE", 0);
|
||||
allDefines.insert("TRUE", 1);
|
||||
|
||||
|
@ -383,13 +393,37 @@ QMap<QString, int> ParseUtil::readCDefines(const QString &filename,
|
|||
return filteredDefines;
|
||||
}
|
||||
|
||||
QStringList ParseUtil::readCDefinesSorted(const QString &filename,
|
||||
const QStringList &prefixes,
|
||||
const QMap<QString, int> &knownDefines)
|
||||
// Similar to readCDefines, but for cases where we only need to show a list of define names.
|
||||
// We can skip evaluating each define (and by extension skip reporting any errors from this process).
|
||||
QStringList ParseUtil::readCDefineNames(const QString &filename, const QStringList &prefixes) {
|
||||
QStringList filteredDefines;
|
||||
|
||||
this->text = this->readCDefinesFile(filename);
|
||||
if (this->text.isEmpty()) {
|
||||
return filteredDefines;
|
||||
}
|
||||
|
||||
static const QRegularExpression re("#define\\s+(?<defineName>\\w+)[^\\S\\n]+");
|
||||
QRegularExpressionMatchIterator iter = re.globalMatch(this->text);
|
||||
while (iter.hasNext()) {
|
||||
QRegularExpressionMatch match = iter.next();
|
||||
QString name = match.captured("defineName");
|
||||
for (QString prefix : prefixes) {
|
||||
if (name.startsWith(prefix) || QRegularExpression(prefix).match(name).hasMatch()) {
|
||||
filteredDefines.append(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredDefines;
|
||||
}
|
||||
|
||||
QStringList ParseUtil::readCDefineNamesByValue(const QString &filename,
|
||||
const QStringList &prefixes,
|
||||
const QMap<QString, int> &knownDefines)
|
||||
{
|
||||
QMap<QString, int> defines = readCDefines(filename, prefixes, knownDefines);
|
||||
|
||||
// The defines should be sorted by their underlying value, not alphabetically.
|
||||
// The defines should be sorted by their underlying value, not alphabetically or in parse order.
|
||||
// Reverse the map and read out the resulting keys in order.
|
||||
QMultiMap<int, QString> definesInverse;
|
||||
for (QString defineName : defines.keys()) {
|
||||
|
|
|
@ -2069,7 +2069,7 @@ bool Project::readItemNames() {
|
|||
QStringList prefixes("\\bITEM_(?!(B_)?USE_)"); // Exclude ITEM_USE_ and ITEM_B_USE_ constants
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
itemNames = parser.readCDefinesSorted(filename, prefixes);
|
||||
itemNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (itemNames.isEmpty()) {
|
||||
logError(QString("Failed to read item constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2078,18 +2078,12 @@ bool Project::readItemNames() {
|
|||
}
|
||||
|
||||
bool Project::readFlagNames() {
|
||||
// First read MAX_TRAINERS_COUNT, used to skip over trainer flags
|
||||
// If this fails flags may simply be out of order, no need to check for success
|
||||
QString opponentsFilename = projectConfig.getFilePath(ProjectFilePath::constants_opponents);
|
||||
fileWatcher.addPath(root + "/" + opponentsFilename);
|
||||
QMap<QString, int> maxTrainers = parser.readCDefines(opponentsFilename, QStringList() << "\\bMAX_");
|
||||
// Parse flags
|
||||
QStringList prefixes("\\bFLAG_");
|
||||
QString flagsFilename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
|
||||
fileWatcher.addPath(root + "/" + flagsFilename);
|
||||
flagNames = parser.readCDefinesSorted(flagsFilename, prefixes, maxTrainers);
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
flagNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (flagNames.isEmpty()) {
|
||||
logError(QString("Failed to read flag constants from %1").arg(flagsFilename));
|
||||
logError(QString("Failed to read flag constants from %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -2099,7 +2093,7 @@ bool Project::readVarNames() {
|
|||
QStringList prefixes("\\bVAR_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
varNames = parser.readCDefinesSorted(filename, prefixes);
|
||||
varNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (varNames.isEmpty()) {
|
||||
logError(QString("Failed to read var constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2111,7 +2105,7 @@ bool Project::readMovementTypes() {
|
|||
QStringList prefixes("\\bMOVEMENT_TYPE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
movementTypes = parser.readCDefinesSorted(filename, prefixes);
|
||||
movementTypes = parser.readCDefineNames(filename, prefixes);
|
||||
if (movementTypes.isEmpty()) {
|
||||
logError(QString("Failed to read movement type constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2134,7 +2128,7 @@ bool Project::readMapTypes() {
|
|||
QStringList prefixes("\\bMAP_TYPE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
mapTypes = parser.readCDefinesSorted(filename, prefixes);
|
||||
mapTypes = parser.readCDefineNames(filename, prefixes);
|
||||
if (mapTypes.isEmpty()) {
|
||||
logError(QString("Failed to read map type constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2146,7 +2140,7 @@ bool Project::readMapBattleScenes() {
|
|||
QStringList prefixes("\\bMAP_BATTLE_SCENE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
mapBattleScenes = parser.readCDefinesSorted(filename, prefixes);
|
||||
mapBattleScenes = parser.readCDefineNames(filename, prefixes);
|
||||
if (mapBattleScenes.isEmpty()) {
|
||||
logError(QString("Failed to read map battle scene constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2158,7 +2152,7 @@ bool Project::readWeatherNames() {
|
|||
QStringList prefixes("\\bWEATHER_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
weatherNames = parser.readCDefinesSorted(filename, prefixes);
|
||||
weatherNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (weatherNames.isEmpty()) {
|
||||
logError(QString("Failed to read weather constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2173,7 +2167,7 @@ bool Project::readCoordEventWeatherNames() {
|
|||
QStringList prefixes("\\bCOORD_EVENT_WEATHER_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
coordEventWeatherNames = parser.readCDefinesSorted(filename, prefixes);
|
||||
coordEventWeatherNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (coordEventWeatherNames.isEmpty()) {
|
||||
logWarn(QString("Failed to read coord event weather constants from %1. Disabling Weather Trigger events.").arg(filename));
|
||||
projectConfig.setEventWeatherTriggerEnabled(false);
|
||||
|
@ -2188,7 +2182,7 @@ bool Project::readSecretBaseIds() {
|
|||
QStringList prefixes("\\bSECRET_BASE_[A-Za-z0-9_]*_[0-9]+");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
secretBaseIds = parser.readCDefinesSorted(filename, prefixes);
|
||||
secretBaseIds = parser.readCDefineNames(filename, prefixes);
|
||||
if (secretBaseIds.isEmpty()) {
|
||||
logWarn(QString("Failed to read secret base id constants from '%1'. Disabling Secret Base events.").arg(filename));
|
||||
projectConfig.setEventSecretBaseEnabled(false);
|
||||
|
@ -2200,7 +2194,7 @@ bool Project::readBgEventFacingDirections() {
|
|||
QStringList prefixes("\\bBG_EVENT_PLAYER_FACING_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
bgEventFacingDirections = parser.readCDefinesSorted(filename, prefixes);
|
||||
bgEventFacingDirections = parser.readCDefineNames(filename, prefixes);
|
||||
if (bgEventFacingDirections.isEmpty()) {
|
||||
logError(QString("Failed to read bg event facing direction constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2212,7 +2206,7 @@ bool Project::readTrainerTypes() {
|
|||
QStringList prefixes("\\bTRAINER_TYPE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
trainerTypes = parser.readCDefinesSorted(filename, prefixes);
|
||||
trainerTypes = parser.readCDefineNames(filename, prefixes);
|
||||
if (trainerTypes.isEmpty()) {
|
||||
logError(QString("Failed to read trainer type constants from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2243,13 +2237,14 @@ bool Project::readSongNames() {
|
|||
QStringList songDefinePrefixes{ "\\bSE_", "\\bMUS_" };
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> songDefines = parser.readCDefines(filename, songDefinePrefixes);
|
||||
this->songNames = songDefines.keys();
|
||||
this->songNames = parser.readCDefineNames(filename, songDefinePrefixes);
|
||||
this->defaultSong = this->songNames.value(0, "MUS_DUMMY");
|
||||
if (this->songNames.isEmpty()) {
|
||||
logError(QString("Failed to read song names from %1.").arg(filename));
|
||||
return false;
|
||||
}
|
||||
// Song names don't have a very useful order (esp. if we include SE_* values), so sort them alphabetically.
|
||||
this->songNames.sort();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2484,8 +2479,9 @@ bool Project::readSpeciesIconPaths() {
|
|||
static const QStringList prefixes("\\bSPECIES_");
|
||||
const QString constantsFilename = projectConfig.getFilePath(ProjectFilePath::constants_species);
|
||||
fileWatcher.addPath(root + "/" + constantsFilename);
|
||||
const QMap<QString, int> defines = parser.readCDefines(constantsFilename, prefixes); // TODO: Suppress errors
|
||||
const QStringList speciesNames = defines.isEmpty() ? monIconNames.keys() : defines.keys();
|
||||
QStringList speciesNames = parser.readCDefineNames(constantsFilename, prefixes);
|
||||
if (speciesNames.isEmpty())
|
||||
speciesNames = monIconNames.keys();
|
||||
|
||||
bool missingIcons = false;
|
||||
for (auto species : speciesNames) {
|
||||
|
|
|
@ -175,7 +175,7 @@ void NewMapPopup::setDefaultSettings(Project *project) {
|
|||
settings.secondaryTilesetLabel = project->getDefaultSecondaryTilesetLabel();
|
||||
settings.type = project->mapTypes.at(0);
|
||||
settings.location = project->mapSectionValueToName.values().at(0);
|
||||
settings.song = project->songNames.at(0);
|
||||
settings.song = project->defaultSong;
|
||||
settings.canFlyTo = false;
|
||||
settings.showLocationName = true;
|
||||
settings.allowRunning = false;
|
||||
|
|
Loading…
Reference in a new issue