Evaluate C define expressions using postfix evaluation, and rename 'asm' to 'parseutil'

This commit is contained in:
Marcus Huderle
2018-03-03 17:09:05 -08:00
parent d87d5e6f00
commit af4dc34eba
7 changed files with 287 additions and 142 deletions

View File

@@ -1,4 +1,4 @@
#include "asm.h"
#include "parseutil.h"
#include "project.h"
#include "tile.h"
#include "tileset.h"
@@ -71,7 +71,7 @@ void Project::loadMapConnections(Map *map) {
QString path = root + QString("/data/maps/%1/connections.inc").arg(map->name);
QString text = readTextFile(path);
if (!text.isNull()) {
QList<QStringList> *commands = parse(text);
QList<QStringList> *commands = parseAsm(text);
QStringList *list = getLabelValues(commands, map->connections_label);
//// Avoid using this value. It ought to be generated instead.
@@ -150,13 +150,13 @@ void Project::readMapHeader(Map* map) {
}
QString label = map->name;
Asm *parser = new Asm;
ParseUtil *parser = new ParseUtil;
QString header_text = readTextFile(root + "/data/maps/" + label + "/header.inc");
if (header_text.isNull()) {
return;
}
QStringList *header = getLabelValues(parser->parse(header_text), label);
QStringList *header = getLabelValues(parser->parseAsm(header_text), label);
map->attributes_label = header->value(0);
map->events_label = header->value(1);
map->scripts_label = header->value(2);
@@ -212,7 +212,7 @@ void Project::saveMapHeader(Map *map) {
void Project::readMapAttributesTable() {
int curMapIndex = 1;
QString attributesText = readTextFile(getMapAttributesTableFilepath());
QList<QStringList>* values = parse(attributesText);
QList<QStringList>* values = parseAsm(attributesText);
bool inAttributePointers = false;
for (int i = 0; i < values->length(); i++) {
QStringList params = values->value(i);
@@ -265,13 +265,13 @@ void Project::readMapAttributes(Map* map) {
return;
}
Asm *parser = new Asm;
ParseUtil *parser = new ParseUtil;
QString assets_text = readTextFile(getMapAssetsFilepath());
if (assets_text.isNull()) {
return;
}
QStringList *attributes = getLabelValues(parser->parse(assets_text), map->attributes_label);
QStringList *attributes = getLabelValues(parser->parseAsm(assets_text), map->attributes_label);
map->width = attributes->value(0);
map->height = attributes->value(1);
map->border_label = attributes->value(2);
@@ -283,13 +283,13 @@ void Project::readMapAttributes(Map* map) {
void Project::readAllMapAttributes() {
mapAttributes.clear();
Asm *parser = new Asm;
ParseUtil *parser = new ParseUtil;
QString assets_text = readTextFile(getMapAssetsFilepath());
if (assets_text.isNull()) {
return;
}
QList<QStringList> *commands = parser->parse(assets_text);
QList<QStringList> *commands = parser->parseAsm(assets_text);
// Assume the _assets.inc file is grouped consistently in the order of:
// 1. <map_name>_MapBorder
@@ -539,10 +539,10 @@ void Project::getTilesets(Map* map) {
}
Tileset* Project::loadTileset(QString label) {
Asm *parser = new Asm;
ParseUtil *parser = new ParseUtil;
QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
QStringList *values = getLabelValues(parser->parse(headers_text), label);
QStringList *values = getLabelValues(parser->parseAsm(headers_text), label);
Tileset *tileset = new Tileset;
tileset->name = label;
tileset->is_compressed = values->value(0);
@@ -562,7 +562,7 @@ Tileset* Project::loadTileset(QString label) {
QString Project::getBlockdataPath(Map* map) {
QString text = readTextFile(getMapAssetsFilepath());
QStringList *values = getLabelValues(parse(text), map->blockdata_label);
QStringList *values = getLabelValues(parseAsm(text), map->blockdata_label);
QString path;
if (!values->isEmpty()) {
path = root + "/" + values->value(0).section('"', 1, 1);
@@ -574,7 +574,7 @@ QString Project::getBlockdataPath(Map* map) {
QString Project::getMapBorderPath(Map *map) {
QString text = readTextFile(getMapAssetsFilepath());
QStringList *values = getLabelValues(parse(text), map->border_label);
QStringList *values = getLabelValues(parseAsm(text), map->border_label);
QString path;
if (!values->isEmpty()) {
path = root + "/" + values->value(0).section('"', 1, 1);
@@ -705,7 +705,7 @@ void Project::saveAllDataStructures() {
}
void Project::loadTilesetAssets(Tileset* tileset) {
Asm* parser = new Asm;
ParseUtil* parser = new ParseUtil;
QString category = (tileset->is_secondary == "TRUE") ? "secondary" : "primary";
if (tileset->name.isNull()) {
return;
@@ -713,7 +713,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
QString dir_path = root + "/data/tilesets/" + category + "/" + tileset->name.replace("gTileset_", "").toLower();
QString graphics_text = readTextFile(root + "/data/tilesets/graphics.inc");
QList<QStringList> *graphics = parser->parse(graphics_text);
QList<QStringList> *graphics = parser->parseAsm(graphics_text);
QStringList *tiles_values = getLabelValues(graphics, tileset->tiles_label);
QStringList *palettes_values = getLabelValues(graphics, tileset->palettes_label);
@@ -743,7 +743,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
QString metatiles_path;
QString metatile_attrs_path;
QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
QList<QStringList> *metatiles_macros = parser->parse(metatiles_text);
QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
if (!metatiles_values->isEmpty()) {
metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
@@ -918,8 +918,8 @@ void Project::readMapGroups() {
if (text.isNull()) {
return;
}
Asm *parser = new Asm;
QList<QStringList> *commands = parser->parse(text);
ParseUtil *parser = new ParseUtil;
QList<QStringList> *commands = parser->parseAsm(text);
bool in_group_pointers = false;
QStringList *groups = new QStringList;
@@ -1015,9 +1015,9 @@ QString Project::getNewMapName() {
return newMapName;
}
QList<QStringList>* Project::parse(QString text) {
Asm *parser = new Asm;
return parser->parse(text);
QList<QStringList>* Project::parseAsm(QString text) {
ParseUtil *parser = new ParseUtil;
return parser->parseAsm(text);
}
QStringList Project::getLocations() {
@@ -1074,7 +1074,7 @@ void Project::readItemNames() {
void Project::readFlagNames() {
QString filepath = root + "/include/constants/flags.h";
QStringList prefixes = (QStringList() << "FLAG_");
readCDefinesSorted(filepath, prefixes, flagNames, "SYSTEM_FLAGS", 0x800);
readCDefinesSorted(filepath, prefixes, flagNames);
}
void Project::readVarNames() {
@@ -1084,13 +1084,9 @@ void Project::readVarNames() {
}
void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
return readCDefinesSorted(filepath, prefixes, definesToSet, "", 0);
}
void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet, QString hardcodedDefine, int hardcodedDefineValue) {
QString text = readTextFile(filepath);
if (!text.isNull()) {
QMap<QString, int> defines = readCDefines(text, prefixes, hardcodedDefine, hardcodedDefineValue);
QMap<QString, int> defines = readCDefines(text, prefixes);
// The defines should to be sorted by their underlying value, not alphabetically.
// Reverse the map and read out the resulting keys in order.
@@ -1318,13 +1314,13 @@ void Project::readMapEvents(Map *map) {
return;
}
QStringList *labels = getLabelValues(parse(text), map->events_label);
QStringList *labels = getLabelValues(parseAsm(text), map->events_label);
map->object_events_label = labels->value(0);
map->warps_label = labels->value(1);
map->coord_events_label = labels->value(2);
map->bg_events_label = labels->value(3);
QList<QStringList> *object_events = getLabelMacros(parse(text), map->object_events_label);
QList<QStringList> *object_events = getLabelMacros(parseAsm(text), map->object_events_label);
map->events["object"].clear();
for (QStringList command : *object_events) {
if (command.value(0) == "object_event") {
@@ -1368,7 +1364,7 @@ void Project::readMapEvents(Map *map) {
}
}
QList<QStringList> *warps = getLabelMacros(parse(text), map->warps_label);
QList<QStringList> *warps = getLabelMacros(parseAsm(text), map->warps_label);
map->events["warp"].clear();
for (QStringList command : *warps) {
if (command.value(0) == "warp_def") {
@@ -1392,7 +1388,7 @@ void Project::readMapEvents(Map *map) {
}
}
QList<QStringList> *coords = getLabelMacros(parse(text), map->coord_events_label);
QList<QStringList> *coords = getLabelMacros(parseAsm(text), map->coord_events_label);
map->events["trap"].clear();
map->events["trap_weather"].clear();
for (QStringList command : *coords) {
@@ -1430,7 +1426,7 @@ void Project::readMapEvents(Map *map) {
}
}
QList<QStringList> *bgs = getLabelMacros(parse(text), map->bg_events_label);
QList<QStringList> *bgs = getLabelMacros(parseAsm(text), map->bg_events_label);
map->events["sign"].clear();
map->events["event_hidden_item"].clear();
map->events["event_secret_base"].clear();
@@ -1535,41 +1531,23 @@ QString Project::readCIncbin(QString text, QString label) {
}
QMap<QString, int> Project::readCDefines(QString text, QStringList prefixes) {
return readCDefines(text, prefixes, "", 0);
}
QMap<QString, int> Project::readCDefines(QString text, QStringList prefixes, QString hardcodedDefine, int hardcodedDefineValue) {
QMap<QString, int> defines;
QString combinedPrefixes = "(" + prefixes.join('|') + ")";
QString regex;
if (hardcodedDefine.isEmpty()) {
regex = QString("#define\\s+(?<defineName>(%1)\\w+)\\s+(?<defineValue>\\w+)").arg(combinedPrefixes);
} else {
regex = QString("#define\\s+(?<defineName>(%1)\\w+)\\s+\\(*(?<hardcodedDefineName>\\\s*%2\\s+\\+\\s+)*(?<defineValue>\\w+\)\\)*").arg(combinedPrefixes, hardcodedDefine);
}
QRegularExpression re(regex);
ParseUtil parser;
QMap<QString, int> allDefines;
QMap<QString, int> filteredDefines;
QRegularExpression re("#define\\s+(?<defineName>\\w+)[^\\S\\n]+(?<defineValue>.+)");
QRegularExpressionMatchIterator iter = re.globalMatch(text);
while (iter.hasNext()) {
QRegularExpressionMatch match = iter.next();
QString name = match.captured("defineName");
QString hardcodedDefineName = match.captured("hardcodedDefineName");
QString value = match.captured("defineValue");
bool valid;
int parsedValue = value.startsWith("0x") ? value.toInt(&valid, 16) : value.toInt(&valid, 10);
if (valid) {
int actualValue = parsedValue;
if (!hardcodedDefine.isEmpty() && !hardcodedDefineName.isEmpty()) {
actualValue += hardcodedDefineValue;
QString expression = match.captured("defineValue");
expression.replace(QRegularExpression("//.*"), "");
int value = parser.evaluateDefine(expression, &allDefines);
allDefines.insert(name, value);
for (QString prefix : prefixes) {
if (name.startsWith(prefix)) {
filteredDefines.insert(name, value);
}
defines.insert(name, actualValue);
} else if (defines.contains(value)) {
defines.insert(name, defines.value(value));
} else {
qDebug() << QString("Failed to parse define '%1' value '%2' as base 10 or hexadecimal value").arg(name, value);
}
}
return defines;
return filteredDefines;
}