From 1992e1d42b282c10fc2285c98da296eef80c34aa Mon Sep 17 00:00:00 2001 From: Username404-59 Date: Tue, 24 Aug 2021 17:23:31 +0200 Subject: [PATCH] Add transpilation of strings to lua-compatible ones, and fix a comment --- src/headers/parsing/ParseComponents.hpp | 3 +- src/headers/parsing/Parser.hpp | 64 +++++++++---------- .../transpiler/implementations/Lua.hpp | 28 +++++++- src/main.cpp | 2 +- 4 files changed, 60 insertions(+), 37 deletions(-) diff --git a/src/headers/parsing/ParseComponents.hpp b/src/headers/parsing/ParseComponents.hpp index b76bbc1..604d9e3 100644 --- a/src/headers/parsing/ParseComponents.hpp +++ b/src/headers/parsing/ParseComponents.hpp @@ -20,7 +20,6 @@ struct ParseComponent { }; namespace StandardComponents { - struct [[deprecated]] Expression: ParseComponent {}; struct NamedIdentifier: public ParseComponent { const string name; explicit NamedIdentifier(string_view nameText): name(nameText) {} @@ -41,7 +40,7 @@ namespace StandardComponents { }; namespace types { struct String: ParseComponent { - const char* content; + const string content; explicit String(const char* string): content(string) {} }; } diff --git a/src/headers/parsing/Parser.hpp b/src/headers/parsing/Parser.hpp index 9278f26..129d4bc 100644 --- a/src/headers/parsing/Parser.hpp +++ b/src/headers/parsing/Parser.hpp @@ -15,46 +15,44 @@ namespace Parser { ParseTree parseTree; using namespace StandardComponents; using enum tok::type; - if (lexed.size() > 1) { - unsigned int i = 0; - const auto nextAre = [&i, &lexed](convertible_to auto nextValues,...) { - va_list argumentsList; - va_start(argumentsList, nextValues); - for (decltype(nextValues) j = 1; j <= nextValues; ++j) { - if (!cmp_greater(lexed.size() - i, nextValues) || lexed[i + j].toktype != va_arg(argumentsList, decltype(nextValues))) { - va_end(argumentsList); - return false; - } + unsigned int i = 0; + const auto nextAre = [&i, &lexed](convertible_to auto nextValues,...) { + va_list argumentsList; + va_start(argumentsList, nextValues); + for (decltype(nextValues) j = 1; j <= nextValues; ++j) { + if (!cmp_greater(lexed.size() - i, nextValues) || lexed[i + j].toktype != va_arg(argumentsList, decltype(nextValues))) { + va_end(argumentsList); + return false; } - va_end(argumentsList); - return true; - }; - for (;i < lexed.size() - 1; ++i) { - const auto& current = lexed[i], next = lexed[i + 1]; + } + va_end(argumentsList); + return true; + }; + for (;i < lexed.size(); ++i) { + const tok& current = lexed[i], next = (i != lexed.size() - 1) ? lexed[i + 1] : tok(UNEXPECTED, string(), current.line); - switch (current.toktype) { - case STRING: parseTree << types::String(current.toktext.data()); break; - case IDENTIFIER: { - if (current.toktext == "class") { - if (next.toktype == IDENTIFIER) { - parseTree << Class(next.toktext); ++i; - } else throw ParsingException('"' + next.toktext + "\" is not a valid class identifier"); - } else { - if ((lexed.size() - i) > 2) { - bool isFinalDefine = nextAre(2, TAG, DEFINE); - if (isFinalDefine || next.toktype == DEFINE) { - parseTree << Define(isFinalDefine, current.toktext); - i += isFinalDefine ? 2 : 1; - } else { - parseTree << Reference(current.toktext); - } + switch (current.toktype) { + case STRING: parseTree << types::String(current.toktext.data()); break; + case IDENTIFIER: { + if (current.toktext == "class") { + if (next.toktype == IDENTIFIER) { + parseTree << Class(next.toktext); ++i; + } else throw ParsingException('"' + next.toktext + "\" is not a valid class identifier"); + } else { + if ((lexed.size() - i) > 2) { + bool isFinalDefine = nextAre(2, TAG, DEFINE); + if (isFinalDefine || next.toktype == DEFINE) { + parseTree << Define(isFinalDefine, current.toktext); + i += isFinalDefine ? 2 : 1; + } else { + parseTree << Reference(current.toktext); } } } - default: break; } + default: break; } - } else throw ParsingException("At least 2 tokens must be provided"); + } return parseTree; } } diff --git a/src/headers/transpiler/implementations/Lua.hpp b/src/headers/transpiler/implementations/Lua.hpp index 6d02c8a..dba5e4b 100644 --- a/src/headers/transpiler/implementations/Lua.hpp +++ b/src/headers/transpiler/implementations/Lua.hpp @@ -5,9 +5,35 @@ struct LuaTarget: Target { void on(const StandardComponents::Define &parseComponent) override { if (parseComponent.final) output << "local "; output << parseComponent.name; - if (parseComponent.final) output << " "; // TODO Find an alternative to for lua >5.4 + if (parseComponent.final) output << " "; // TODO Find an alternative to for lua <5.4 output << " = "; } + void on(const StandardComponents::types::String &parseComponent) override { + const string_view view (parseComponent.content); + vector interpolationVector; + const string interpolationString = "${"; + unsigned long occurence_position = view.find(interpolationString); + while (occurence_position != string_view::npos) { + interpolationVector.push_back(occurence_position); + occurence_position = view.find(interpolationString, occurence_position + interpolationString.size()); + } + const bool multiline = view.find('\n') != string_view::npos; + const char* openCharacters = multiline ? "[[" : "\""; + decltype(openCharacters) closeCharacters = multiline ? "]]" : "\""; + if (not interpolationVector.empty()) { + unsigned long closingBrace = 0; + for (unsigned long i = 0; cmp_less(i, interpolationVector.size()); ++i) { + const auto& occurence = interpolationVector[i]; + if (i > 0) output << ".."; + output << openCharacters << view.substr((i > 0) ? closingBrace + 1 : 0, occurence - (closingBrace + 1)) << closeCharacters; + closingBrace = view.find_first_of('}', occurence); + if (closingBrace == string_view::npos) { + throw Yerbacon::Exception("Closing brace missing in a string"); + } + output << ".." << view.substr(occurence + interpolationString.size(), (closingBrace - occurence) - interpolationString.size()); + } + } else output << openCharacters << view << closeCharacters << '\n'; + } }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fccc427..d7c63fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char* argv[]) { else if (currentArg.ends_with(".ybcon")) files.push_back(currentArg); } const auto compile = [&target](string_view name) { - const string transpiledString = transpile(parseString(getFileContent(name.data())), target); + string transpiledString = transpile(parseString(getFileContent(name.data())), target); name.remove_suffix(6); string outputFile; (outputFile = name).append(target);