Generalize C struct parsing

This commit is contained in:
GriffinR 2022-09-27 18:29:16 -04:00 committed by Marcus Huderle
parent 85a5f07695
commit ebdf22145d
3 changed files with 41 additions and 45 deletions

View file

@ -69,6 +69,7 @@ public:
static QString removeLineComments(QString text, const QStringList &commentSymbols);
static QStringList splitShellCommand(QStringView command);
static QMap<QString, QMap<QString, QString>> readCStructs(const QString &filePath, const QHash<int, QString> memberMap = { });
private:
QString root;

View file

@ -6,6 +6,9 @@
#include <QJsonObject>
#include <QStack>
#include "lib/fex/lexer.h"
#include "lib/fex/parser.h"
const QRegularExpression ParseUtil::re_incScriptLabel("\\b(?<label>[\\w_][\\w\\d_]*):{1,2}");
const QRegularExpression ParseUtil::re_globalIncScriptLabel("\\b(?<label>[\\w_][\\w\\d_]*)::");
const QRegularExpression ParseUtil::re_poryScriptLabel("\\b(script)(\\((global|local)\\))?\\s*\\b(?<label>[\\w_][\\w\\d_]*)");
@ -375,6 +378,31 @@ QMap<QString, QString> ParseUtil::readNamedIndexCArray(const QString &filename,
return map;
}
QMap<QString, QMap<QString, QString>> ParseUtil::readCStructs(const QString &filePath, const QHash<int, QString> memberMap) {
auto cParser = fex::Parser();
auto tokens = fex::Lexer().LexFile(filePath.toStdString());
auto structs = cParser.ParseTopLevelObjects(tokens);
QMap<QString, QMap<QString, QString>> structMaps;
for (auto it = structs.begin(); it != structs.end(); it++) {
QMap<QString, QString> values;
int i = 0;
for (const fex::ArrayValue &v : it->second.values()) {
if (v.type() == fex::ArrayValue::Type::kValuePair) {
QString key = QString::fromStdString(v.pair().first);
QString value = QString::fromStdString(v.pair().second->string_value());
values.insert(key, value);
} else {
// For backwards compatibility with structs that don't specify member names.
if (memberMap.contains(i))
values.insert(memberMap.value(i), QString::fromStdString(v.string_value()));
}
i++;
}
structMaps.insert(QString::fromStdString(it->first), values);
}
return structMaps;
}
QList<QStringList> ParseUtil::getLabelMacros(const QList<QStringList> &list, const QString &label) {
bool in_label = false;
QList<QStringList> new_list;

View file

@ -10,8 +10,6 @@
#include "map.h"
#include "orderedjson.h"
#include "lib/fex/lexer.h"
#include "lib/fex/parser.h"
#include <QDir>
#include <QJsonArray>
@ -2481,7 +2479,18 @@ bool Project::readEventGraphics() {
qDeleteAll(eventGraphicsMap);
eventGraphicsMap.clear();
QStringList gfxNames = gfxDefines.keys();
QMap<QString, QMap<QString, QString>> gfxInfos = readObjEventGfxInfo();
// The positions of each of the required members for the gfx info struct.
// For backwards compatibility if the struct doesn't use initializers.
const auto gfxInfoMemberMap = QHash<int, QString>{
{8, "inanimate"},
{11, "oam"},
{12, "subspriteTables"},
{14, "images"},
};
QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
QMap<QString, QMap<QString, QString>> gfxInfos = ParseUtil::readCStructs(filepath, gfxInfoMemberMap);
for (QString gfxName : gfxNames) {
EventGraphics * eventGraphics = new EventGraphics;
@ -2529,48 +2538,6 @@ bool Project::readEventGraphics() {
return true;
}
QMap<QString, QMap<QString, QString>> Project::readObjEventGfxInfo() {
// TODO: refactor this to be more general if we end up directly parsing C
// for more use cases in the future.
auto cParser = fex::Parser();
auto tokens = fex::Lexer().LexFile((root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info)).toStdString());
auto gfxInfoObjects = cParser.ParseTopLevelObjects(tokens);
QMap<QString, QMap<QString, QString>> gfxInfos;
for (auto it = gfxInfoObjects.begin(); it != gfxInfoObjects.end(); it++) {
QMap<QString, QString> values;
int i = 0;
for (const fex::ArrayValue &v : it->second.values()) {
if (v.type() == fex::ArrayValue::Type::kValuePair) {
QString key = QString::fromStdString(v.pair().first);
QString value = QString::fromStdString(v.pair().second->string_value());
values.insert(key, value);
} else {
// This is for backwards compatibility with the old-style version of
// object_event_graphics_info.h, in which the structs didn't use
// attribute names to specify each struct member.
switch (i) {
case 8:
values.insert("inanimate", QString::fromStdString(v.string_value()));
break;
case 11:
values.insert("oam", QString::fromStdString(v.string_value()));
break;
case 12:
values.insert("subspriteTables", QString::fromStdString(v.string_value()));
break;
case 14:
values.insert("images", QString::fromStdString(v.string_value()));
break;
}
}
i++;
}
gfxInfos.insert(QString::fromStdString(it->first), values);
}
return gfxInfos;
}
bool Project::readSpeciesIconPaths() {
speciesToIconPath.clear();
QString srcfilename = projectConfig.getFilePath(ProjectFilePath::path_pokemon_icon_table);