From fdd12cde25d8f6c0b76b4401c4752479cbd30de6 Mon Sep 17 00:00:00 2001 From: BigBahss Date: Tue, 16 Feb 2021 07:15:47 -0500 Subject: [PATCH] Refactor ParseUtil to stop using pointers and output-parameters --- include/core/parseutil.h | 41 ++++++++--------- src/core/parseutil.cpp | 99 ++++++++++++++++++---------------------- src/project.cpp | 41 +++++++---------- 3 files changed, 81 insertions(+), 100 deletions(-) diff --git a/include/core/parseutil.h b/include/core/parseutil.h index 399f43fb..7c9b225e 100644 --- a/include/core/parseutil.h +++ b/include/core/parseutil.h @@ -39,31 +39,30 @@ public: class ParseUtil { public: - ParseUtil(); - void set_root(QString); - static QString readTextFile(QString); + ParseUtil() { }; + void set_root(const QString &dir); + static QString readTextFile(const QString &path); static int textFileLineCount(const QString &path); - void strip_comment(QString*); QList parseAsm(const QString &filename); - int evaluateDefine(QString, QMap*); - QStringList readCArray(QString text, QString label); - QMap readNamedIndexCArray(QString text, QString label); - QString readCIncbin(QString text, QString label); - QMap readCDefines(QString filename, QStringList prefixes, QMap = QMap()); - void readCDefinesSorted(QString, QStringList, QStringList*, QMap = QMap()); - QList getLabelMacros(const QList &, const QString &); - QStringList getLabelValues(const QList &, const QString &); - bool tryParseJsonFile(QJsonDocument *out, QString filepath); - bool ensureFieldsExist(QJsonObject obj, QList fields); + int evaluateDefine(const QString&, const QMap&); + QStringList readCArray(const QString &text, const QString &label); + QMap readNamedIndexCArray(const QString &text, const QString &label); + QString readCIncbin(const QString &text, const QString &label); + QMap readCDefines(const QString &filename, const QStringList &prefixes, QMap = { }); + QStringList readCDefinesSorted(const QString&, const QStringList&, const QMap& = { }); + QList getLabelMacros(const QList&, const QString&); + QStringList getLabelValues(const QList&, const QString&); + bool tryParseJsonFile(QJsonDocument *out, const QString &filepath); + bool ensureFieldsExist(const QJsonObject &obj, const QList &fields); // Returns the 1-indexed line number for the definition of scriptLabel in the scripts file at filePath. // Returns 0 if a definition for scriptLabel cannot be found. static int getScriptLineNumber(const QString &filePath, const QString &scriptLabel); static int getRawScriptLineNumber(QString text, const QString &scriptLabel); static int getPoryScriptLineNumber(QString text, const QString &scriptLabel); - static QString &removeStringLiterals(QString &text); - static QString &removeLineComments(QString &text, const QString &commentSymbol); - static QString &removeLineComments(QString &text, const QStringList &commentSymbols); + static QString removeStringLiterals(QString text); + static QString removeLineComments(QString text, const QString &commentSymbol); + static QString removeLineComments(QString text, const QStringList &commentSymbols); static QStringList splitShellCommand(QStringView command); @@ -71,10 +70,10 @@ private: QString root; QString text; QString file; - QList tokenizeExpression(QString expression, QMap* knownIdentifiers); - QList generatePostfix(QList tokens); - int evaluatePostfix(QList postfix); - void error(QString message, QString expression); + QList tokenizeExpression(QString expression, const QMap &knownIdentifiers); + QList generatePostfix(const QList &tokens); + int evaluatePostfix(const QList &postfix); + void error(const QString &message, const QString &expression); }; #endif // PARSEUTIL_H diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp index cd053458..30ebe19c 100644 --- a/src/core/parseutil.cpp +++ b/src/core/parseutil.cpp @@ -6,15 +6,12 @@ #include #include -ParseUtil::ParseUtil() -{ -} -void ParseUtil::set_root(QString dir) { +void ParseUtil::set_root(const QString &dir) { this->root = dir; } -void ParseUtil::error(QString message, QString expression) { +void ParseUtil::error(const QString &message, const QString &expression) { QStringList lines = text.split(QRegularExpression("[\r\n]")); int lineNum = 0, colNum = 0; for (QString line : lines) { @@ -25,21 +22,7 @@ void ParseUtil::error(QString message, QString expression) { logError(QString("%1:%2:%3: %4").arg(file).arg(lineNum).arg(colNum).arg(message)); } -void ParseUtil::strip_comment(QString *line) { - bool in_string = false; - for (int i = 0; i < line->length(); i++) { - if (line->at(i) == '"') { - in_string = !in_string; - } else if (line->at(i) == '@') { - if (!in_string) { - line->truncate(i); - break; - } - } - } -} - -QString ParseUtil::readTextFile(QString path) { +QString ParseUtil::readTextFile(const QString &path) { QFile file(path); if (!file.open(QIODevice::ReadOnly)) { logError(QString("Could not open '%1': ").arg(path) + file.errorString()); @@ -63,21 +46,23 @@ QList ParseUtil::parseAsm(const QString &filename) { QList parsed; text = readTextFile(root + '/' + filename); - const QStringList lines = text.split('\n'); - for (QString line : lines) { - strip_comment(&line); - if (line.trimmed().isEmpty()) { - } else if (line.contains(':')) { + const QStringList lines = removeLineComments(text, "@").split('\n'); + for (const auto &line : lines) { + const QString trimmedLine = line.trimmed(); + if (trimmedLine.isEmpty()) { + continue; + } + + if (line.contains(':')) { const QString label = line.left(line.indexOf(':')); const QStringList list{ ".label", label }; // .label is not a real keyword. It's used only to make the output more regular. parsed.append(list); // There should not be anything else on the line. // gas will raise a syntax error if there is. } else { - line = line.trimmed(); - int index = line.indexOf(QRegExp("\\s+")); - const QString macro = line.left(index); - QStringList params(line.right(line.length() - index).trimmed().split(QRegExp("\\s*,\\s*"))); + int index = trimmedLine.indexOf(QRegExp("\\s+")); + const QString macro = trimmedLine.left(index); + QStringList params(trimmedLine.right(trimmedLine.length() - index).trimmed().split(QRegExp("\\s*,\\s*"))); params.prepend(macro); parsed.append(params); } @@ -85,13 +70,13 @@ QList ParseUtil::parseAsm(const QString &filename) { return parsed; } -int ParseUtil::evaluateDefine(QString define, QMap* knownDefines) { +int ParseUtil::evaluateDefine(const QString &define, const QMap &knownDefines) { QList tokens = tokenizeExpression(define, knownDefines); QList postfixExpression = generatePostfix(tokens); return evaluatePostfix(postfixExpression); } -QList ParseUtil::tokenizeExpression(QString expression, QMap* knownIdentifiers) { +QList ParseUtil::tokenizeExpression(QString expression, const QMap &knownIdentifiers) { QList tokens; QStringList tokenTypes = (QStringList() << "hex" << "decimal" << "identifier" << "operator" << "leftparen" << "rightparen"); @@ -108,8 +93,8 @@ QList ParseUtil::tokenizeExpression(QString expression, QMapcontains(token)) { - QString actualToken = QString("%1").arg(knownIdentifiers->value(token)); + if (knownIdentifiers.contains(token)) { + QString actualToken = QString("%1").arg(knownIdentifiers.value(token)); expression = expression.replace(0, token.length(), actualToken); token = actualToken; tokenType = "decimal"; @@ -152,7 +137,7 @@ QMap Token::precedenceMap = QMap( // Shunting-yard algorithm for generating postfix notation. // https://en.wikipedia.org/wiki/Shunting-yard_algorithm -QList ParseUtil::generatePostfix(QList tokens) { +QList ParseUtil::generatePostfix(const QList &tokens) { QList output; QStack operatorStack; for (Token token : tokens) { @@ -194,7 +179,7 @@ QList ParseUtil::generatePostfix(QList tokens) { // Evaluate postfix expression. // https://en.wikipedia.org/wiki/Reverse_Polish_notation#Postfix_evaluation_algorithm -int ParseUtil::evaluatePostfix(QList postfix) { +int ParseUtil::evaluatePostfix(const QList &postfix) { QStack stack; for (Token token : postfix) { if (token.type == TokenClass::Operator && stack.size() > 1) { @@ -228,7 +213,7 @@ int ParseUtil::evaluatePostfix(QList postfix) { return stack.size() ? stack.pop().value.toInt(nullptr, 0) : 0; } -QString ParseUtil::readCIncbin(QString filename, QString label) { +QString ParseUtil::readCIncbin(const QString &filename, const QString &label) { QString path; if (label.isNull()) { @@ -251,7 +236,10 @@ QString ParseUtil::readCIncbin(QString filename, QString label) { return path; } -QMap ParseUtil::readCDefines(QString filename, QStringList prefixes, QMap allDefines) { +QMap ParseUtil::readCDefines(const QString &filename, + const QStringList &prefixes, + QMap allDefines) +{ QMap filteredDefines; file = filename; @@ -280,7 +268,7 @@ QMap ParseUtil::readCDefines(QString filename, QStringList prefixe QString name = match.captured("defineName"); QString expression = match.captured("defineValue"); if (expression == " ") continue; - int value = evaluateDefine(expression, &allDefines); + int value = evaluateDefine(expression, allDefines); allDefines.insert(name, value); for (QString prefix : prefixes) { if (name.startsWith(prefix) || QRegularExpression(prefix).match(name).hasMatch()) { @@ -291,7 +279,10 @@ QMap ParseUtil::readCDefines(QString filename, QStringList prefixe return filteredDefines; } -void ParseUtil::readCDefinesSorted(QString filename, QStringList prefixes, QStringList* definesToSet, QMap knownDefines) { +QStringList ParseUtil::readCDefinesSorted(const QString &filename, + const QStringList &prefixes, + const QMap &knownDefines) +{ QMap defines = readCDefines(filename, prefixes, knownDefines); // The defines should to be sorted by their underlying value, not alphabetically. @@ -300,10 +291,10 @@ void ParseUtil::readCDefinesSorted(QString filename, QStringList prefixes, QStri for (QString defineName : defines.keys()) { definesInverse.insert(defines[defineName], defineName); } - *definesToSet = definesInverse.values(); + return definesInverse.values(); } -QStringList ParseUtil::readCArray(QString filename, QString label) { +QStringList ParseUtil::readCArray(const QString &filename, const QString &label) { QStringList list; if (label.isNull()) { @@ -329,7 +320,7 @@ QStringList ParseUtil::readCArray(QString filename, QString label) { return list; } -QMap ParseUtil::readNamedIndexCArray(QString filename, QString label) { +QMap ParseUtil::readNamedIndexCArray(const QString &filename, const QString &label) { text = readTextFile(root + "/" + filename); QMap map; @@ -388,16 +379,16 @@ QStringList ParseUtil::getLabelValues(const QList &list, const QStr return values; } -bool ParseUtil::tryParseJsonFile(QJsonDocument *out, QString filepath) { +bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath) { QFile file(filepath); if (!file.open(QIODevice::ReadOnly)) { logError(QString("Error: Could not open %1 for reading").arg(filepath)); return false; } - QByteArray data = file.readAll(); + const QByteArray data = file.readAll(); QJsonParseError parseError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError); + const QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError); file.close(); if (parseError.error != QJsonParseError::NoError) { logError(QString("Error: Failed to parse json file %1: %2").arg(filepath).arg(parseError.errorString())); @@ -408,7 +399,7 @@ bool ParseUtil::tryParseJsonFile(QJsonDocument *out, QString filepath) { return true; } -bool ParseUtil::ensureFieldsExist(QJsonObject obj, QList fields) { +bool ParseUtil::ensureFieldsExist(const QJsonObject &obj, const QList &fields) { for (QString field : fields) { if (!obj.contains(field)) { logError(QString("JSON object is missing field '%1'.").arg(field)); @@ -431,8 +422,8 @@ int ParseUtil::getScriptLineNumber(const QString &filePath, const QString &scrip } int ParseUtil::getRawScriptLineNumber(QString text, const QString &scriptLabel) { - removeStringLiterals(text); - removeLineComments(text, "@"); + text = removeStringLiterals(text); + text = removeLineComments(text, "@"); static const QRegularExpression re_incScriptLabel("\\b(?