diff --git a/src/qtapp/mdemList.cpp b/src/qtapp/mdemList.cpp index 4ce7414..c6c788e 100644 --- a/src/qtapp/mdemList.cpp +++ b/src/qtapp/mdemList.cpp @@ -546,7 +546,6 @@ Mdem* makeMdem() { // Aizmuguras saturs. for (size_t i = 0; i < 20; ++i) { - // @Improve: back label pooling QLabel *elBackText = new QLabel(); mdem->hBack.addWidget(elBackText); mdem->backLabels.push_back(elBackText); diff --git a/src/transpiler/parser.cpp b/src/transpiler/parser.cpp index d5fe3be..fb1f9bd 100644 --- a/src/transpiler/parser.cpp +++ b/src/transpiler/parser.cpp @@ -75,7 +75,7 @@ void initTransitions() { * Pārbauda, vai tekstvienību saraksts atbilst valodas * definētām pieļaujamām pārejām. * */ -Result ValidateGrammar(const std::vector& tokens) { +Result validateGrammar(const std::vector& tokens) { if (!transitions) { initTransitions(); } @@ -125,6 +125,9 @@ Result parseQuestions(const std::vector& tokens) { // kļūdas informāciju. auto makeResult = [&questions, &time](std::string error, Token token) -> Result { + if (debug) { + std::cout << "SECTION END: PARSER:\n"; + } return { { questions, time }, error, @@ -137,7 +140,7 @@ Result parseQuestions(const std::vector& tokens) { if (tokens.size() == 0) { return makeResult("", Token()); } - auto result = ValidateGrammar(tokens); + auto result = validateGrammar(tokens); if (result.error.length() > 0) { return makeResult( result.error, @@ -145,8 +148,6 @@ Result parseQuestions(const std::vector& tokens) { ); } - size_t i = 0; - if (debug) { std::cout << "SECTION: PARSER:\n"; } @@ -157,6 +158,7 @@ Result parseQuestions(const std::vector& tokens) { return i < tokens.size() && tokens[i].tokenType != TokenType::EndOfFile; }; + size_t i = 0; // Sākuma datumu un laiku mēģina nolasīt, ja tāds ir norādīts. if (isInBounds(i) && tokens[i].tokenType == TokenType::TextFragment) { @@ -191,288 +193,289 @@ Result parseQuestions(const std::vector& tokens) { // Pamata parsēšana. while (i < tokens.size()) { - if (tokens[i].tokenType == TokenType::ElementDashStart) { - std::string questionText; - std::vector questionElements; - double cooldown; - bool isOrderQuestion = false; - bool isGroupQuestion = false; - bool isPlusQuestion = false; - bool hasGroupEncountered = false; - Token questionStartToken; + switch (tokens[i].tokenType) { + case TokenType::ElementDashStart: { + std::string questionText; + std::vector questionElements; + double cooldown; + bool isOrderQuestion = false; + bool isGroupQuestion = false; + bool isPlusQuestion = false; + bool hasGroupEncountered = false; + Token questionStartToken; - // Šajā momentā ir sagaidāms jautājuma sākums - tam nevar būt secības modifikators. - if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { - return makeResult( - "Nevar izmantot secības modifikatoru ('^') jautājuma sākumā", - tokens[i + 1]); - } - - // Piefiksē sākumu, lai varētu sniegt labāku kļūdas - // atrašanās vietu kļūdas gadījumā. - questionStartToken = tokens[i]; - - // Apstrādā pārtraukumu, ja tāds ir. - bool hasCooldown; - if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::CooldownStart) { - try { - auto cooldownContent = tokens[i + 2].content; - // Pārbauda, vai dotais pārtraukums ir viens skaitlis, kas ir: - // - pozitīvs; - // - viens no: vesels skaitlis vai ar punktu atdalīts skaitlis - // ar norādīto vai bez norādītās veselās daļas. - static const std::regex decimalNumExp( - "^\\d*(\\.\\d+)?$", - std::regex_constants::ECMAScript | std::regex_constants::icase - ); - if (!std::regex_match(cooldownContent, decimalNumExp)) { - throw std::invalid_argument("Nekorekts pārtraukuma formāts"); - } - cooldown = std::stod(cooldownContent); - } catch (std::exception e) { - return makeResult( - "Nekorekts pārtraukums. Pārtraukums ir viens pozitīvs " - "decimāls skaitlis ar punktu vai bez punkta", - tokens[i + 1] - ); - } - questionText = tokens[i + 4].content; - hasCooldown = true; - } else { - cooldown = 0; - questionText = tokens[i + 1].content; - hasCooldown = false; - } - - int questionStartOffset = hasCooldown ? 5 : 2; - // Pārbauda, vai jautājums ir nobeigts ar korektu simbolu. - if (isInBounds(questionStartOffset) && - tokens[i + questionStartOffset].tokenType != TokenType::QuestionEnd) { - return makeResult( - "Jautājumu var iesākt tikai ar \">\"", - tokens[i + questionStartOffset] - ); - } - i += hasCooldown ? 6 : 3; - - // Jautājumu elementu parsēšana. - while (isInBounds(i)) { - - // Pārbauda, vai nav sastapts cits jautājuma sākums, un noslēdz, ja tas tā ir. - if (isInBounds(i + 3) && tokens[i].tokenType == TokenType::ElementDashStart) { - - // Jautājumam var būt un var nebūt pārtraukums - nosaka vai tas būtu. - size_t offset; - if (tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { - offset = tokens[i + 2].tokenType == TokenType::CooldownStart ? 6 : 3; - } else { - offset = tokens[i + 1].tokenType == TokenType::CooldownStart ? 5 : 2; - } - if (isInBounds(i + offset) && tokens[i + offset].tokenType == TokenType::QuestionEnd) { - break; - } - - if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) { - return makeResult( - "Jautājuma elementam nevar būt pārtraukums", - tokens[i] - ); - } + // Šajā momentā ir sagaidāms jautājuma sākums - tam nevar būt secības modifikators. + if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { + return makeResult( + "Nevar izmantot secības modifikatoru ('^') jautājuma sākumā", + tokens[i + 1]); } - - // Jautājuma elementa noteikšana un ar to saistītās kļūdas. - bool isDash; - bool isGroup = false; - bool isOrder = false; - // Elementa sākums. - if (tokens[i].tokenType == TokenType::ElementDashStart) { - isDash = true; - } else { - isDash = false; - isPlusQuestion = true; - if (isGroupQuestion) { - return makeResult( - "Jautājumos ar grupām nevar būt secības elementu ('+' and ':')", - tokens[i] - ); - } - if (isOrderQuestion) { - return makeResult( - "Secības jautājumos nevar būt izvēles elementu ('-^' and '+')", - tokens[i] - ); - } - } + // Piefiksē sākumu, lai varētu sniegt labāku kļūdas + // atrašanās vietu kļūdas gadījumā. + questionStartToken = tokens[i]; - // Elementa secības modifikators. - if (isInBounds(i+1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { - isOrder = true; - isOrderQuestion = true; - if (!isDash) { - return makeResult( - "Secības jautājumus var izmantot tikai ar svītrām ('-')", - tokens[i] - ); - } - if (isGroupQuestion) { - return makeResult( - "Jautājumos ar grupām nevar būt secības elementu ('-^' and ':')", - tokens[i] - ); - } - if (isPlusQuestion) { - return makeResult( - "Izvēles jautājumos nevar būt secības elementu ('+' and '-^')", - tokens[i] - ); - } - if (isInBounds(i + 3) && tokens[i + 3].tokenType == TokenType::MatchGroupEnd) { - return makeResult( - "Secības jautājumā nevar būt grupas ('-^' and ':')", - tokens[i] - ); - } - } + // Apstrādā pārtraukumu, ja tāds ir. + bool hasCooldown; + if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::CooldownStart) { + try { + auto cooldownContent = tokens[i + 2].content; + // Pārbauda, vai dotais pārtraukums ir viens skaitlis, kas ir: + // - pozitīvs; + // - viens no: vesels skaitlis vai ar punktu atdalīts skaitlis + // ar norādīto vai bez norādītās veselās daļas. + static const std::regex decimalNumExp( + "^\\d*(\\.\\d+)?$", + std::regex_constants::ECMAScript | std::regex_constants::icase + ); + if (!std::regex_match(cooldownContent, decimalNumExp)) { + throw std::invalid_argument("Nekorekts pārtraukuma formāts"); + } + cooldown = std::stod(cooldownContent); + } catch (std::exception e) { + return makeResult( + "Nekorekts pārtraukums. Pārtraukums ir viens pozitīvs " + "decimāls skaitlis ar punktu vai bez punkta", + tokens[i + 1] + ); + } + questionText = tokens[i + 4].content; + hasCooldown = true; + } else { + cooldown = 0; + questionText = tokens[i + 1].content; + hasCooldown = false; + } - // Elementa grupas modifikators. - if (isInBounds(i + 2) && tokens[i + 2].tokenType == TokenType::MatchGroupEnd) { - isGroup = true; - isGroupQuestion = true; - if (!isDash) { - return makeResult( - "Grupas jautājumus var definēt tikai ar svītru elementiem ('-')", - tokens[i] - ); - } - if (!hasGroupEncountered) { - if (questionElements.size() > 0) { - return makeResult( - "Elementi grupas jautājumā nevar eksistēt bez grupas", - tokens[i] - ); - } - } - hasGroupEncountered = true; - } + int questionStartOffset = hasCooldown ? 5 : 2; + // Pārbauda, vai jautājums ir nobeigts ar korektu simbolu. + if (isInBounds(questionStartOffset) && + tokens[i + questionStartOffset].tokenType != TokenType::QuestionEnd) { + return makeResult( + "Jautājumu var iesākt tikai ar \">\"", + tokens[i + questionStartOffset] + ); + } + i += hasCooldown ? 6 : 3; - // Izveido atbilstoša veida jautājuma elementu. - QuestionElement questionElement; - questionElement.isDash = isDash; - questionElement.isGroup = isGroup; - if (isOrder) { - questionElement.content = tokens[i + 2].content; - } else { - questionElement.content = tokens[i + 1].content; - } - questionElements.push_back(questionElement); + // Jautājumu elementu parsēšana. + while (isInBounds(i)) { - // Nākamā elementa atrašanās vieta ir atkarīga no elementu - // veida, kas ir sastapts. - size_t offset = 2; - if (isOrder) { - offset += 1; - } - if (isGroup) { - offset += 1; - } - i += offset; - } + // Pārbauda, vai nav sastapts cits jautājuma sākums, un noslēdz, ja tas tā ir. + if (isInBounds(i + 3) && tokens[i].tokenType == TokenType::ElementDashStart) { - // Izveido jautājuma objektu. - // Fix: else block - jautājums bez elementiem. - if (questionElements.size() > 0) { - if (isGroupQuestion) { - auto *question = new GroupQuestion(); - question->cooldown = cooldown; - question->questionText = cleanContent(questionText); + // Jautājumam var būt un var nebūt pārtraukums - nosaka vai tas būtu. + size_t offset; + if (tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { + offset = tokens[i + 2].tokenType == TokenType::CooldownStart ? 6 : 3; + } else { + offset = tokens[i + 1].tokenType == TokenType::CooldownStart ? 5 : 2; + } + if (isInBounds(i + offset) && tokens[i + offset].tokenType == TokenType::QuestionEnd) { + break; + } - // Izveido grupas; i - elementu iterators; k - grupu iterators. - int32_t k = -1; - for (size_t i = 0; i < questionElements.size(); ++i) { - auto questionElement = questionElements[i]; - if (questionElement.isGroup) { - ++k; - auto group = Group(); - group.name = cleanContent(questionElement.content); - question->groups.push_back(group); - } else { - if (k >= 0) { - question->groups[k].elements.push_back( - cleanContent( - questionElement.content - ) - ); - } - } - } - questions.push_back(question); - if (debug) { - std::cout << question->toString() << "\n"; - } - } else { - auto *question = new MultiElementQuestion(); - question->cooldown = cooldown; - question->questionText = cleanContent(questionText); + if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) { + return makeResult( + "Jautājuma elementam nevar būt pārtraukums", + tokens[i] + ); + } + } + + // Jautājuma elementa noteikšana un ar to saistītās kļūdas. + bool isDash; + bool isGroup = false; + bool isOrder = false; - // Izveido vairāku elementu jautājumu. - auto existingElements = std::set(); - for (const auto& elem : questionElements) { - Choice choice; - choice.answer = cleanContent(elem.content); - choice.isCorrect = !elem.isDash; + // Elementa sākums. + if (tokens[i].tokenType == TokenType::ElementDashStart) { + isDash = true; + } else { + isDash = false; + isPlusQuestion = true; + if (isGroupQuestion) { + return makeResult( + "Jautājumos ar grupām nevar būt secības elementu ('+' and ':')", + tokens[i] + ); + } + if (isOrderQuestion) { + return makeResult( + "Secības jautājumos nevar būt izvēles elementu ('-^' and '+')", + tokens[i] + ); + } + } - // Secības elementiem nedrīkst būt vienādi elementi. - if (isOrderQuestion) { - if (existingElements.contains(choice.answer)) { - return makeResult( - "Secības jautājumi atbildes nedrīkst atkārtoties", - questionStartToken - ); - } else { - question->choices.push_back(choice); - existingElements.insert(choice.answer); - } - } else { - question->choices.push_back(choice); - } - } - questions.push_back(question); + // Elementa secības modifikators. + if (isInBounds(i+1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) { + isOrder = true; + isOrderQuestion = true; + if (!isDash) { + return makeResult( + "Secības jautājumus var izmantot tikai ar svītrām ('-')", + tokens[i] + ); + } + if (isGroupQuestion) { + return makeResult( + "Jautājumos ar grupām nevar būt secības elementu ('-^' and ':')", + tokens[i] + ); + } + if (isPlusQuestion) { + return makeResult( + "Izvēles jautājumos nevar būt secības elementu ('+' and '-^')", + tokens[i] + ); + } + if (isInBounds(i + 3) && tokens[i + 3].tokenType == TokenType::MatchGroupEnd) { + return makeResult( + "Secības jautājumā nevar būt grupas ('-^' and ':')", + tokens[i] + ); + } + } - // Uzstāda vairāku elementu jautājuma specializēto veidu. - if (isPlusQuestion) { - question->type = MultiElementType::MultiChoice; - } else if (isOrderQuestion) { - question->type = MultiElementType::Order; - } else { - question->type = MultiElementType::Regular; - } - if (debug) { - std::cout << question->toString() << "\n"; - } - } - } else { - return makeResult( - "Jautājums nevar būt bez atbildes elementiem", - questionStartToken - ); - } - } else if (tokens[i].tokenType == TokenType::EndOfFile) { - if (debug) { - std::cout << "Fails beidzās: EndOfFile\n"; - } - break; - } else { - return makeResult( - "Negaidīta tekstvienība", - tokens[i] - ); + // Elementa grupas modifikators. + if (isInBounds(i + 2) && tokens[i + 2].tokenType == TokenType::MatchGroupEnd) { + isGroup = true; + isGroupQuestion = true; + if (!isDash) { + return makeResult( + "Grupas jautājumus var definēt tikai ar svītru elementiem ('-')", + tokens[i] + ); + } + if (!hasGroupEncountered) { + if (questionElements.size() > 0) { + return makeResult( + "Elementi grupas jautājumā nevar eksistēt bez grupas", + tokens[i] + ); + } + } + hasGroupEncountered = true; + } + + // Izveido atbilstoša veida jautājuma elementu. + QuestionElement questionElement; + questionElement.isDash = isDash; + questionElement.isGroup = isGroup; + if (isOrder) { + questionElement.content = tokens[i + 2].content; + } else { + questionElement.content = tokens[i + 1].content; + } + questionElements.push_back(questionElement); + + // Nākamā elementa atrašanās vieta ir atkarīga no elementu + // veida, kas ir sastapts. + size_t offset = 2; + if (isOrder) { + offset += 1; + } + if (isGroup) { + offset += 1; + } + i += offset; + } + + if (questionElements.size() > 0) { + + // Izveido jautājuma objektu. + if (isGroupQuestion) { + auto *question = new GroupQuestion(); + question->cooldown = cooldown; + question->questionText = cleanContent(questionText); + + // Izveido grupas; i - elementu iterators; k - grupu iterators. + int32_t k = -1; + for (size_t i = 0; i < questionElements.size(); ++i) { + auto questionElement = questionElements[i]; + if (questionElement.isGroup) { + ++k; + auto group = Group(); + group.name = cleanContent(questionElement.content); + question->groups.push_back(group); + } else { + if (k >= 0) { + question->groups[k].elements.push_back( + cleanContent( + questionElement.content + ) + ); + } + } + } + questions.push_back(question); + if (debug) { + std::cout << question->toString() << "\n"; + } + } else { + auto *question = new MultiElementQuestion(); + question->cooldown = cooldown; + question->questionText = cleanContent(questionText); + + // Izveido vairāku elementu jautājumu. + auto existingElements = std::set(); + for (const auto& elem : questionElements) { + Choice choice; + choice.answer = cleanContent(elem.content); + choice.isCorrect = !elem.isDash; + + // Secības elementiem nedrīkst būt vienādi elementi. + if (isOrderQuestion) { + if (existingElements.contains(choice.answer)) { + return makeResult( + "Secības jautājumi atbildes nedrīkst atkārtoties", + questionStartToken + ); + } else { + question->choices.push_back(choice); + existingElements.insert(choice.answer); + } + } else { + question->choices.push_back(choice); + } + } + questions.push_back(question); + + // Uzstāda vairāku elementu jautājuma specializēto veidu. + if (isPlusQuestion) { + question->type = MultiElementType::MultiChoice; + } else if (isOrderQuestion) { + question->type = MultiElementType::Order; + } else { + question->type = MultiElementType::Regular; + } + if (debug) { + std::cout << question->toString() << "\n"; + } + } + } else { + return makeResult( + "Jautājums nevar būt bez atbildes elementiem", + questionStartToken + ); + } + } break; + case TokenType::EndOfFile: { + return makeResult( + "", + Token() + ); + } break; + default: { + return makeResult( + "", + Token() + ); + } break; } } - if (debug) { - std::cout << "SECTION END: PARSER:\n"; - } return makeResult( "", Token()