datetime as first token

This commit is contained in:
jorenchik
2024-10-06 10:18:22 +03:00
parent 22053041bd
commit 28c1841bdc
8 changed files with 91 additions and 60 deletions

View File

@@ -1,4 +1,4 @@
#include "result.h" #include "result.h"
#include "parser.h" #include "parser.h"
Result<std::vector<Question*>> Transpile(std::string fileContent, bool debug); Result<ParseInfo> Transpile(std::string fileContent, bool isDebug);

View File

@@ -15,7 +15,7 @@ enum class TokenType {
Cooldown, Cooldown,
CooldownStart, CooldownStart,
CooldownEnd, CooldownEnd,
SOF, StartOfFile,
EndOfFile EndOfFile
}; };

View File

@@ -45,4 +45,9 @@ struct GroupQuestion : public Question {
std::string ToString() const override; std::string ToString() const override;
}; };
Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens); struct ParseInfo {
std::vector<Question*> questions;
time_t lastTrainedAt;
};
Result<ParseInfo> ParseQuestions(const std::vector<Token>& tokens);

View File

@@ -344,13 +344,20 @@ void loadMdem() {
std::stringstream buffer; std::stringstream buffer;
buffer << file.rdbuf(); buffer << file.rdbuf();
content = buffer.str(); content = buffer.str();
auto parseRes = Transpile(content, true); auto res = Transpile(content, true);
for (auto question: questions) { for (auto question: questions) {
delete question; delete question;
} }
questions.clear(); questions.clear();
if (parseRes.error == "") { if (res.error == "") {
questions = parseRes.value; 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(); makePages();
SwitchPage(0); SwitchPage(0);
std::smatch matches; std::smatch matches;
@@ -359,7 +366,7 @@ void loadMdem() {
QString::fromStdString(std::format("mdem: {}", matches[2].str())) QString::fromStdString(std::format("mdem: {}", matches[2].str()))
); );
} else { } else {
std::cout << "Compilation error." << std::endl; std::cout << std::format("Compilation error: {}", res.error) << std::endl;
for (auto mdem: mdems) { for (auto mdem: mdems) {
if (mdem->wMdem->isVisible()) { if (mdem->wMdem->isVisible()) {
mdem->wMdem->hide(); mdem->wMdem->hide();

View File

@@ -12,7 +12,7 @@ bool debug;
std::chrono::high_resolution_clock::time_point start; std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::time_point end; std::chrono::high_resolution_clock::time_point end;
Result<std::vector<Question*>> Transpile(std::string fileContent, bool isDebug) { Result<ParseInfo> Transpile(std::string fileContent, bool isDebug) {
start = std::chrono::high_resolution_clock::now(); start = std::chrono::high_resolution_clock::now();
end = std::chrono::high_resolution_clock::now(); end = std::chrono::high_resolution_clock::now();
debug = isDebug; debug = isDebug;

View File

@@ -18,6 +18,7 @@ int32_t previousRow;
int32_t previousColumn; int32_t previousColumn;
bool textStarted = false; bool textStarted = false;
bool identifierStarted = false; bool identifierStarted = false;
bool sof;
void trimString(std::string &str, std::string trimChars) { void trimString(std::string &str, std::string trimChars) {
int padSize = 0; int padSize = 0;
@@ -261,6 +262,7 @@ std::string Token::ToString(const TokenType* ttype) {
case TokenType::Cooldown: return "cooldown"; case TokenType::Cooldown: return "cooldown";
case TokenType::CooldownStart: return "start of cooldown"; case TokenType::CooldownStart: return "start of cooldown";
case TokenType::CooldownEnd: return "end of cooldown"; case TokenType::CooldownEnd: return "end of cooldown";
case TokenType::StartOfFile: return "start of the file";
case TokenType::EndOfFile: return "end of file"; case TokenType::EndOfFile: return "end of file";
default: return "unrecognized token"; default: return "unrecognized token";
} }

View File

@@ -50,7 +50,7 @@ int main(int argc, char* argv[]) {
ShowTime("I/O time"); ShowTime("I/O time");
auto res = Transpile(fileContent, debug); auto res = Transpile(fileContent, debug);
auto questions = res.value; auto questions = res.value.questions;
if (res.error.length() > 0) { if (res.error.length() > 0) {
std::cout << std::format( std::cout << std::format(
"{} ({}:{})\n", "{} ({}:{})\n",

View File

@@ -1,4 +1,6 @@
#include <cstdio> #include <cstdio>
#include <ctime>
#include <iomanip>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -103,7 +105,8 @@ std::map<TokenType, std::vector<TokenType>> parserAutomata() {
automata[TokenType::CooldownEnd] = { automata[TokenType::CooldownEnd] = {
TokenType::TextFragment TokenType::TextFragment
}; };
automata[TokenType::SOF] = { automata[TokenType::StartOfFile] = {
TokenType::TextFragment,
TokenType::ElementDashStart, TokenType::ElementDashStart,
TokenType::EndOfFile TokenType::EndOfFile
}; };
@@ -138,21 +141,29 @@ Result<NoneType> ValidateGrammar(const std::vector<Token>& tokens) {
return {}; return {};
} }
Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens) { Result<ParseInfo> ParseQuestions(const std::vector<Token>& tokens) {
auto questions = std::vector<Question*>(); auto questions = std::vector<Question*>();
time_t time = 0;
auto makeResult = [&questions, &time](std::string error, Token token) -> Result<ParseInfo> {
return {
{ questions, time },
error,
token.row,
token.column
};
};
if (tokens.size() == 0) { if (tokens.size() == 0) {
return {questions, ""}; return makeResult("", Token());
} }
auto result = ValidateGrammar(tokens); auto result = ValidateGrammar(tokens);
if (result.error.length() > 0) { if (result.error.length() > 0) {
return { return makeResult(
questions,
result.error, result.error,
result.row, Token{.row=result.row, .column=result.column}
result.column );
};
} }
std::string section; std::string section;
@@ -161,39 +172,49 @@ Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens)
if (debug) { if (debug) {
std::cout << "SECTION: Parser output:\n"; 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()) { while (i < tokens.size()) {
if (tokens[i].tokenType == TokenType::ElementDashStart) { if (tokens[i].tokenType == TokenType::ElementDashStart) {
double cooldown;
std::string questionText; std::string questionText;
std::vector<QuestionElement> questionElements; std::vector<QuestionElement> questionElements;
double cooldown;
bool isOrderQuestion = false; bool isOrderQuestion = false;
bool isGroupQuestion = false; bool isGroupQuestion = false;
bool isPlusQuestion = 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. // Start element parsing & add to the offset.
if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) {
return { return makeResult(
questions,
"cannot have order modifier ('^') in the question definition", "cannot have order modifier ('^') in the question definition",
tokens[i + 1].row, tokens[i + 1]
tokens[i + 1].column );
};
} }
if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::CooldownStart) { if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::CooldownStart) {
try { try {
cooldown = std::stod(tokens[i + 2].content); cooldown = std::stod(tokens[i + 2].content);
} catch (std::exception e) { } catch (std::exception e) {
return { return makeResult(
questions,
"error parsing cooldown", "error parsing cooldown",
tokens[i + 1].row, tokens[i + 1]
tokens[i + 1].column );
};
} }
questionText = tokens[i + 4].content; questionText = tokens[i + 4].content;
i += 6; i += 6;
@@ -220,12 +241,10 @@ Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens)
} }
if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) { if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) {
// Cannot place the identifier on the ordinary element. // Cannot place the identifier on the ordinary element.
return { return makeResult(
questions,
"Invalid identifier placement", "Invalid identifier placement",
tokens[i].row, tokens[i]
tokens[i].column );
};
} }
} }
@@ -243,35 +262,32 @@ Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens)
isOrder = true; isOrder = true;
isOrderQuestion = true; isOrderQuestion = true;
if (!isDash) { if (!isDash) {
return { return makeResult(
questions,
"order questions can only be used with dashes ('-')", "order questions can only be used with dashes ('-')",
tokens[i].row, tokens[i]
tokens[i].column );
};
} }
if (isGroupQuestion) { if (isGroupQuestion) {
return { return makeResult(
questions,
"question with groups cannot be ordered ('-^' and ':')", "question with groups cannot be ordered ('-^' and ':')",
tokens[i].row, tokens[i]
tokens[i].column );
};
} }
if (isInBounds(i + 3) && tokens[i + 3].tokenType == TokenType::MatchGroupEnd) { if (isInBounds(i + 3) && tokens[i + 3].tokenType == TokenType::MatchGroupEnd) {
return { return makeResult(
questions,
"cannot have groups in order question('-^' and ':')", "cannot have groups in order question('-^' and ':')",
tokens[i].row, tokens[i]
tokens[i].column );
};
} }
} }
if (isInBounds(i + 2) && tokens[i + 2].tokenType == TokenType::MatchGroupEnd) { if (isInBounds(i + 2) && tokens[i + 2].tokenType == TokenType::MatchGroupEnd) {
isGroup = true; isGroup = true;
isGroupQuestion = true; isGroupQuestion = true;
if (!isDash) { 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<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens)
} }
break; break;
} else { } else {
return { return makeResult(
questions,
"Unexpected token encountered", "Unexpected token encountered",
tokens[i].row, tokens[i]
tokens[i].column );
};
} }
} }
if (debug) { if (debug) {
std::cout << "SECTION END: Parser output:\n"; std::cout << "SECTION END: Parser output:\n";
} }
return {questions, ""}; return makeResult(
"",
Token()
);
} }