From 28c1841bdc2c624a69fc7a5e45d634cc637d8fc3 Mon Sep 17 00:00:00 2001 From: jorenchik Date: Sun, 6 Oct 2024 10:18:22 +0300 Subject: [PATCH] datetime as first token --- src/cpp/include/api.h | 2 +- src/cpp/include/lexer.h | 2 +- src/cpp/include/parser.h | 7 +- src/cpp/qtapp/main.cpp | 15 +++-- src/cpp/transpiler/api.cpp | 2 +- src/cpp/transpiler/lexer.cpp | 2 + src/cpp/transpiler/main.cpp | 2 +- src/cpp/transpiler/parser.cpp | 119 +++++++++++++++++++--------------- 8 files changed, 91 insertions(+), 60 deletions(-) diff --git a/src/cpp/include/api.h b/src/cpp/include/api.h index a14c13e..8823244 100644 --- a/src/cpp/include/api.h +++ b/src/cpp/include/api.h @@ -1,4 +1,4 @@ #include "result.h" #include "parser.h" -Result> Transpile(std::string fileContent, bool debug); +Result Transpile(std::string fileContent, bool isDebug); diff --git a/src/cpp/include/lexer.h b/src/cpp/include/lexer.h index 7f1ddc4..6dde84d 100644 --- a/src/cpp/include/lexer.h +++ b/src/cpp/include/lexer.h @@ -15,7 +15,7 @@ enum class TokenType { Cooldown, CooldownStart, CooldownEnd, - SOF, + StartOfFile, EndOfFile }; diff --git a/src/cpp/include/parser.h b/src/cpp/include/parser.h index 9437775..50bc7ad 100644 --- a/src/cpp/include/parser.h +++ b/src/cpp/include/parser.h @@ -45,4 +45,9 @@ struct GroupQuestion : public Question { std::string ToString() const override; }; -Result> ParseQuestions(const std::vector& tokens); +struct ParseInfo { + std::vector questions; + time_t lastTrainedAt; +}; + +Result ParseQuestions(const std::vector& tokens); diff --git a/src/cpp/qtapp/main.cpp b/src/cpp/qtapp/main.cpp index bfa8655..ed8e449 100644 --- a/src/cpp/qtapp/main.cpp +++ b/src/cpp/qtapp/main.cpp @@ -344,13 +344,20 @@ void loadMdem() { std::stringstream buffer; buffer << file.rdbuf(); content = buffer.str(); - auto parseRes = Transpile(content, true); + auto res = Transpile(content, true); for (auto question: questions) { delete question; } questions.clear(); - if (parseRes.error == "") { - questions = parseRes.value; + if (res.error == "") { + time_t trainedAt; + if (res.value.lastTrainedAt == 0) { + trainedAt = 0; + } else { + trainedAt = res.value.lastTrainedAt + 3600 * 2; + } + std::cout << std::format("Last trained at: {}", trainedAt) << std::endl; + questions = res.value.questions; makePages(); SwitchPage(0); std::smatch matches; @@ -359,7 +366,7 @@ void loadMdem() { QString::fromStdString(std::format("mdem: {}", matches[2].str())) ); } else { - std::cout << "Compilation error." << std::endl; + std::cout << std::format("Compilation error: {}", res.error) << std::endl; for (auto mdem: mdems) { if (mdem->wMdem->isVisible()) { mdem->wMdem->hide(); diff --git a/src/cpp/transpiler/api.cpp b/src/cpp/transpiler/api.cpp index 43f7d3f..9a86e5f 100644 --- a/src/cpp/transpiler/api.cpp +++ b/src/cpp/transpiler/api.cpp @@ -12,7 +12,7 @@ bool debug; std::chrono::high_resolution_clock::time_point start; std::chrono::high_resolution_clock::time_point end; -Result> Transpile(std::string fileContent, bool isDebug) { +Result Transpile(std::string fileContent, bool isDebug) { start = std::chrono::high_resolution_clock::now(); end = std::chrono::high_resolution_clock::now(); debug = isDebug; diff --git a/src/cpp/transpiler/lexer.cpp b/src/cpp/transpiler/lexer.cpp index b47477f..a916b6d 100644 --- a/src/cpp/transpiler/lexer.cpp +++ b/src/cpp/transpiler/lexer.cpp @@ -18,6 +18,7 @@ int32_t previousRow; int32_t previousColumn; bool textStarted = false; bool identifierStarted = false; +bool sof; void trimString(std::string &str, std::string trimChars) { int padSize = 0; @@ -261,6 +262,7 @@ std::string Token::ToString(const TokenType* ttype) { case TokenType::Cooldown: return "cooldown"; case TokenType::CooldownStart: return "start of cooldown"; case TokenType::CooldownEnd: return "end of cooldown"; + case TokenType::StartOfFile: return "start of the file"; case TokenType::EndOfFile: return "end of file"; default: return "unrecognized token"; } diff --git a/src/cpp/transpiler/main.cpp b/src/cpp/transpiler/main.cpp index 86ae4aa..efd1d4a 100644 --- a/src/cpp/transpiler/main.cpp +++ b/src/cpp/transpiler/main.cpp @@ -50,7 +50,7 @@ int main(int argc, char* argv[]) { ShowTime("I/O time"); auto res = Transpile(fileContent, debug); - auto questions = res.value; + auto questions = res.value.questions; if (res.error.length() > 0) { std::cout << std::format( "{} ({}:{})\n", diff --git a/src/cpp/transpiler/parser.cpp b/src/cpp/transpiler/parser.cpp index f472d3a..7cc5152 100644 --- a/src/cpp/transpiler/parser.cpp +++ b/src/cpp/transpiler/parser.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -103,7 +105,8 @@ std::map> parserAutomata() { automata[TokenType::CooldownEnd] = { TokenType::TextFragment }; - automata[TokenType::SOF] = { + automata[TokenType::StartOfFile] = { + TokenType::TextFragment, TokenType::ElementDashStart, TokenType::EndOfFile }; @@ -138,21 +141,29 @@ Result ValidateGrammar(const std::vector& tokens) { return {}; } -Result> ParseQuestions(const std::vector& tokens) { +Result ParseQuestions(const std::vector& tokens) { auto questions = std::vector(); + time_t time = 0; + + auto makeResult = [&questions, &time](std::string error, Token token) -> Result { + return { + { questions, time }, + error, + token.row, + token.column + }; + }; if (tokens.size() == 0) { - return {questions, ""}; + return makeResult("", Token()); } auto result = ValidateGrammar(tokens); if (result.error.length() > 0) { - return { - questions, + return makeResult( result.error, - result.row, - result.column - }; + Token{.row=result.row, .column=result.column} + ); } std::string section; @@ -161,39 +172,49 @@ Result> ParseQuestions(const std::vector& tokens) if (debug) { std::cout << "SECTION: Parser output:\n"; } + + auto isInBounds = [tokens](size_t i) { + return i < tokens.size() && tokens[i].tokenType != TokenType::EndOfFile; + }; + + if (isInBounds(i) && tokens[i].tokenType == TokenType::TextFragment) { + std::tm tm = {}; + try { + strptime(tokens[i].content.c_str(), "%d.%m.%Y %H:%M", &tm); + } catch (std::exception e) { + return makeResult( + std::format("cannot parse the time - {}", e.what()), + tokens[i] + ); + } + time = mktime(&tm); + i++; + } + while (i < tokens.size()) { if (tokens[i].tokenType == TokenType::ElementDashStart) { - - double cooldown; std::string questionText; std::vector questionElements; + double cooldown; bool isOrderQuestion = false; bool isGroupQuestion = false; bool isPlusQuestion = false; - auto isInBounds = [tokens](size_t i) { - return i < tokens.size() && tokens[i].tokenType != TokenType::EndOfFile; - }; - // Start element parsing & add to the offset. if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { - return { - questions, + return makeResult( "cannot have order modifier ('^') in the question definition", - tokens[i + 1].row, - tokens[i + 1].column - }; + tokens[i + 1] + ); } if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::CooldownStart) { try { cooldown = std::stod(tokens[i + 2].content); } catch (std::exception e) { - return { - questions, + return makeResult( "error parsing cooldown", - tokens[i + 1].row, - tokens[i + 1].column - }; + tokens[i + 1] + ); } questionText = tokens[i + 4].content; i += 6; @@ -220,12 +241,10 @@ Result> ParseQuestions(const std::vector& tokens) } if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) { // Cannot place the identifier on the ordinary element. - return { - questions, + return makeResult( "Invalid identifier placement", - tokens[i].row, - tokens[i].column - }; + tokens[i] + ); } } @@ -243,35 +262,32 @@ Result> ParseQuestions(const std::vector& tokens) isOrder = true; isOrderQuestion = true; if (!isDash) { - return { - questions, + return makeResult( "order questions can only be used with dashes ('-')", - tokens[i].row, - tokens[i].column - }; + tokens[i] + ); } if (isGroupQuestion) { - return { - questions, + return makeResult( "question with groups cannot be ordered ('-^' and ':')", - tokens[i].row, - tokens[i].column - }; + tokens[i] + ); } if (isInBounds(i + 3) && tokens[i + 3].tokenType == TokenType::MatchGroupEnd) { - return { - questions, + return makeResult( "cannot have groups in order question('-^' and ':')", - tokens[i].row, - tokens[i].column - }; + tokens[i] + ); } } if (isInBounds(i + 2) && tokens[i + 2].tokenType == TokenType::MatchGroupEnd) { isGroup = true; isGroupQuestion = true; if (!isDash) { - return {questions, "group questions can only be used with dashes ('-')"}; + return makeResult( + "group questions can only be used with dashes ('-')", + tokens[i] + ); } } @@ -354,17 +370,18 @@ Result> ParseQuestions(const std::vector& tokens) } break; } else { - return { - questions, + return makeResult( "Unexpected token encountered", - tokens[i].row, - tokens[i].column - }; + tokens[i] + ); } } if (debug) { std::cout << "SECTION END: Parser output:\n"; } - return {questions, ""}; + return makeResult( + "", + Token() + ); }