From fb85f272a15d2f2c3fe073eec8fea4e754510da3 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sat, 21 Nov 2020 14:39:01 +0100 Subject: [PATCH] Added pragmas to pattern language --- include/lang/preprocessor.hpp | 14 +++++-- source/lang/preprocessor.cpp | 79 ++++++++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/include/lang/preprocessor.hpp b/include/lang/preprocessor.hpp index 35640beba..98fee1631 100644 --- a/include/lang/preprocessor.hpp +++ b/include/lang/preprocessor.hpp @@ -4,9 +4,11 @@ #include "token.hpp" -#include -#include +#include #include +#include +#include +#include namespace hex::lang { @@ -14,10 +16,16 @@ namespace hex::lang { public: Preprocessor(); - std::pair preprocess(const std::string& code, bool applyDefines = true); + std::pair preprocess(const std::string& code, bool initialRun = true); + + void addPragmaHandler(std::string pragmaType, std::function function); + void addDefaultPragramHandlers(); private: + std::unordered_map> m_pragmaHandlers; + std::set> m_defines; + std::set> m_pragmas; }; } \ No newline at end of file diff --git a/source/lang/preprocessor.cpp b/source/lang/preprocessor.cpp index d54090b9a..4000328da 100644 --- a/source/lang/preprocessor.cpp +++ b/source/lang/preprocessor.cpp @@ -6,11 +6,13 @@ namespace hex::lang { } - std::pair Preprocessor::preprocess(const std::string& code, bool applyDefines) { + std::pair Preprocessor::preprocess(const std::string& code, bool initialRun) { u32 offset = 0; - if (applyDefines) + if (initialRun) { this->m_defines.clear(); + this->m_pragmas.clear(); + } std::string output; output.reserve(code.length()); @@ -76,45 +78,100 @@ namespace hex::lang { std::string defineName; while (!std::isblank(code[offset])) { defineName += code[offset]; - offset += 1; if (offset >= code.length() || code[offset] == '\n' || code[offset] == '\r') return { ResultPreprocessingError, "" }; + offset += 1; } while (std::isblank(code[offset])) offset += 1; std::string replaceValue; - do { + while (code[offset] != '\n' && code[offset] != '\r') { if (offset >= code.length()) return { ResultPreprocessingError, "" }; replaceValue += code[offset]; offset += 1; - } while (code[offset] != '\n' && code[offset] != '\r'); + } + + if (replaceValue.empty()) + return { ResultPreprocessingError, "" }; this->m_defines.emplace(defineName, replaceValue); - } + } else if (code.substr(offset, 6) == "pragma") { + offset += 6; + + while (std::isblank(code[offset])) + offset += 1; + + std::string pragmaKey; + while (!std::isblank(code[offset])) { + pragmaKey += code[offset]; + + if (offset >= code.length() || code[offset] == '\n' || code[offset] == '\r') + return { ResultPreprocessingError, "" }; + + offset += 1; + } + + while (std::isblank(code[offset])) + offset += 1; + + std::string pragmaValue; + while (code[offset] != '\n' && code[offset] != '\r') { + if (offset >= code.length()) + return { ResultPreprocessingError, "" }; + + pragmaValue += code[offset]; + offset += 1; + } + + if (pragmaValue.empty()) + return { ResultPreprocessingError, "" }; + + this->m_pragmas.emplace(pragmaKey, pragmaValue); + } else + return { ResultPreprocessingError, "" }; } output += code[offset]; offset += 1; } - if (applyDefines) { + if (initialRun) { + // Apply defines for (const auto &[define, value] : this->m_defines) { s32 index = 0; while((index = output.find(define, index)) != std::string::npos) { - if (index > 0) { - output.replace(index, define.length(), value); - index += value.length(); - } + output.replace(index, define.length(), value); + index += value.length(); } } + + // Handle pragmas + for (const auto &[type, value] : this->m_pragmas) { + if (this->m_pragmaHandlers.contains(type)) { + if (!this->m_pragmaHandlers[type](value)) + return { ResultPreprocessingError, { } }; + } else + return { ResultPreprocessingError, { } }; + } } return { ResultSuccess, output }; } + void Preprocessor::addPragmaHandler(std::string pragmaType, std::function function) { + if (!this->m_pragmaHandlers.contains(pragmaType)) + this->m_pragmaHandlers.emplace(pragmaType, function); + } + + void Preprocessor::addDefaultPragramHandlers() { + this->addPragmaHandler("MIME", [](std::string value) { + return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r'); + }); + } + } \ No newline at end of file