From 2c3b904853e48e4bf7724e46b3e07c1048724205 Mon Sep 17 00:00:00 2001 From: jorenchik Date: Sat, 28 Sep 2024 17:21:14 +0300 Subject: [PATCH] partial implementation of all question types --- src/cpp/include/lexer.h | 2 + src/cpp/include/parser.h | 42 +++-- .../index/main.cpp.6DE93E662B25E657.idx | Bin 14846 -> 16250 bytes src/cpp/qtapp/main.cpp | 12 +- src/cpp/transpiler/lexer.cpp | 22 +++ src/cpp/transpiler/parser.cpp | 145 ++++++++++++------ tasks.md | 37 +++++ 7 files changed, 184 insertions(+), 76 deletions(-) create mode 100644 tasks.md diff --git a/src/cpp/include/lexer.h b/src/cpp/include/lexer.h index 10cebb1..94443bd 100644 --- a/src/cpp/include/lexer.h +++ b/src/cpp/include/lexer.h @@ -8,8 +8,10 @@ enum class TokenType { TextFragment, QuestionEnd, + MatchGroupEnd, ElementDashStart, ElementPlusStart, + ElementOrderModifier, Identifier, IdentifierStart, IdentifierEnd, diff --git a/src/cpp/include/parser.h b/src/cpp/include/parser.h index 610f5a6..d903182 100644 --- a/src/cpp/include/parser.h +++ b/src/cpp/include/parser.h @@ -6,32 +6,44 @@ #include "lexer.h" #include "result.h" + struct Question { virtual std::string ToString() const = 0; - virtual ~Question() = default; + virtual ~Question() = default; }; struct Choice { std::string Answer; - bool IsCorrect; + bool IsCorrect; }; -struct SingleAnswerQuestion : public Question { - std::string ID; - std::string QuestionText; - std::string Answer; - std::string Section; - - std::string ToString() const override; +enum MultiElementType { + Regular = 0, + MultiChoice, + Order }; -struct MultipleChoiceQuestion : public Question { - std::string ID; - std::string QuestionText; - std::vector Choices; - std::string Section; +struct MultiElementQuestion : public Question { + std::string ID; + std::string QuestionText; + std::vector Choices; + std::string Section; + MultiElementType type; - std::string ToString() const override; + std::string ToString() const override; +}; + +struct Group { + std::string name; + std::string elements; +}; + +struct GroupQuestion : public Question { + std::string ID; + std::string QuestionText; + std::vector Groups; + + std::string ToString() const override; }; Result> ParseQuestions(const std::vector& tokens); diff --git a/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx b/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx index f2fa27358b53ab07ab2b743173506628b6016a79..e73b53fc5f6c668cdb7390abadba54003113ea51 100644 GIT binary patch literal 16250 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 literal 14846 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 questions) { }; for (size_t i = 0; i < questions.size(); ++i) { - if (SingleAnswerQuestion* sa = dynamic_cast(questions[i])) { - mdems[i]->wFrontText->setText(QString::fromStdString(sa->QuestionText)); - auto answer = sa->Answer; - answer = transformAnswer(answer); - answer = std::format("- {}", answer); - mdems[i]->backLabels[0]->setText(QString::fromStdString(answer)); - if (mdems[i]->wBack->isVisible()) { - mdems[i]->wBack->hide(); - } - mdems[i]->labelCount = 1; - } else if (MultipleChoiceQuestion* mw = dynamic_cast(questions[i])) { + if (AnswerQuestion* mw = dynamic_cast(questions[i])) { mdems[i]->wFrontText->setText( QString::fromStdString(mw->QuestionText) ); diff --git a/src/cpp/transpiler/lexer.cpp b/src/cpp/transpiler/lexer.cpp index 81446fd..32049ff 100644 --- a/src/cpp/transpiler/lexer.cpp +++ b/src/cpp/transpiler/lexer.cpp @@ -199,6 +199,26 @@ Result> TokenizeMdem(const std::string& fileRunes) { previousColumn = column; textStarted = false; break; + case '^': + makeTokenWithTokenBuffer( + TokenType::ElementOrderModifier, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; + case ':': + makeTokenWithTokenBuffer( + TokenType::MatchGroupEnd, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; case '>': makeTokenWithTokenBuffer( TokenType::QuestionEnd, @@ -255,7 +275,9 @@ std::string Token::ToString(const TokenType* ttype) { switch (*ttype) { case TokenType::TextFragment: return "text fragment"; case TokenType::QuestionEnd: return "question end symbol"; + case TokenType::MatchGroupEnd: return "match group end"; case TokenType::ElementDashStart: return "dash element start"; + case TokenType::ElementOrderModifier: return "order element modifier"; case TokenType::ElementPlusStart: return "plus element start"; case TokenType::Identifier: return "identifier"; case TokenType::IdentifierStart: return "start of identifier"; diff --git a/src/cpp/transpiler/parser.cpp b/src/cpp/transpiler/parser.cpp index ce6f46e..fdbbf91 100644 --- a/src/cpp/transpiler/parser.cpp +++ b/src/cpp/transpiler/parser.cpp @@ -14,20 +14,11 @@ struct QuestionElement { bool isDash; + bool isGroup; std::string content; }; -std::string SingleAnswerQuestion::ToString() const { - return std::format( - ":{} section:{} id:{} answer:{}", - QuestionText, - Section, - ID, - Answer - ); -} - -std::string MultipleChoiceQuestion::ToString() const { +std::string MultiElementQuestion::ToString() const { std::stringstream choiceOut; for (const auto& choice : Choices) { char opener; @@ -61,18 +52,26 @@ std::map> parserAutomata() { TokenType::QuestionEnd, TokenType::ElementDashStart, TokenType::ElementPlusStart, + TokenType::MatchGroupEnd, TokenType::SectionIdentifierStart, TokenType::SectionStart, TokenType::EndOfFile, TokenType::SectionEnd }; + automata[TokenType::MatchGroupEnd] = { + TokenType::ElementDashStart + }; automata[TokenType::QuestionEnd] = { TokenType::ElementDashStart, TokenType::ElementPlusStart }; automata[TokenType::ElementDashStart] = { TokenType::IdentifierStart, - TokenType::TextFragment + TokenType::TextFragment, + TokenType::ElementOrderModifier + }; + automata[TokenType::ElementOrderModifier] = { + TokenType::TextFragment }; automata[TokenType::ElementPlusStart] = { TokenType::TextFragment @@ -165,7 +164,10 @@ Result> ParseQuestions(const std::vector& tokens) std::string id, questionText; std::vector questionElements; - // Parsing for a single question or multiple choice question + bool isOrderQuestion = false; + bool isGroupQuestion = false; + + // Start element parsing & add to the offset. if (tokens[i + 1].tokenType == TokenType::IdentifierStart) { id = tokens[i + 2].content; questionText = tokens[i + 4].content; @@ -176,17 +178,30 @@ Result> ParseQuestions(const std::vector& tokens) i += 3; } - while (true) { - if (i + 3 < tokens.size() && tokens[i + 3].tokenType != TokenType::EndOfFile) { - size_t offset = tokens[i + 1].tokenType == TokenType::IdentifierStart ? 5 : 2; - if (tokens[i].tokenType == TokenType::SectionIdentifierStart || - tokens[i].tokenType == TokenType::SectionEnd) { - break; - } - if (i + offset < tokens.size() && tokens[i + offset].tokenType == TokenType::QuestionEnd) { + auto isInBounds = [tokens](size_t i) { + return i < tokens.size() && tokens[i].tokenType != TokenType::EndOfFile; + }; + + // Parse elements of a question. + while (isInBounds(i)) { + + // Handle other constructs. + if (tokens[i].tokenType == TokenType::SectionIdentifierStart) { + break; + } + if (tokens[i].tokenType == TokenType::SectionEnd) { + break; + } + + // Check question end. + if (tokens[i].tokenType == TokenType::ElementDashStart && isInBounds(i + 3)) { + // Distance to the possible question end. + size_t offset = tokens[i + 1].tokenType == TokenType::IdentifierStart ? 5 : 2; + if (isInBounds(i + offset) && tokens[i + offset].tokenType == TokenType::QuestionEnd) { break; } if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) { + // Cannot place the identifier on the ordinary element. return { questions, "Invalid identifier placement", @@ -195,42 +210,72 @@ Result> ParseQuestions(const std::vector& tokens) }; } } - if (i + 2 >= tokens.size()) { - break; - } + + // Determine element type. + bool isDash; + bool isGroup = false; + if (isInBounds(i+1) && tokens[i].tokenType == TokenType::ElementOrderModifier) { + isOrderQuestion = true; + if (!isDash) { + // TODO: err + } + } + if (tokens[i].tokenType == TokenType::ElementDashStart) { + isDash = true; + if (isOrderQuestion) { + // TODO: err + } + } else { + isDash = false; + } + if (isInBounds(i+2) && tokens[i].tokenType == TokenType::MatchGroupEnd) { + isGroup = true; + isGroupQuestion = true; + if (!isDash) { + // TODO: err + } + if (isOrderQuestion) { + // TODO: err + } + } - // Create question elements QuestionElement questionElement; - questionElement.isDash = (tokens[i].tokenType == TokenType::ElementDashStart); + questionElement.isDash = isDash; + questionElement.isGroup = isGroup; questionElement.content = tokens[i + 1].content; questionElements.push_back(questionElement); - i += 2; + + size_t offset = 2; + if (isOrderQuestion) { + offset += 1; + } + if (isGroup) { + offset += 1; + } + + i += offset; } if (questionElements.size() > 1) { - auto* mcq = new MultipleChoiceQuestion(); - mcq->ID = id; - mcq->QuestionText = questionText; - for (const auto& elem : questionElements) { - Choice choice; - choice.Answer = elem.content; - choice.IsCorrect = !elem.isDash; - mcq->Choices.push_back(choice); - } - mcq->Section = section; - questions.push_back(mcq); - if (debug) { - std::cout << mcq->ToString() << "\n"; - } - } else if (questionElements.size() == 1) { - auto* saq = new SingleAnswerQuestion(); - saq->ID = id; - saq->QuestionText = questionText; - saq->Answer = questionElements[0].content; - saq->Section = section; - questions.push_back(saq); - if (debug) { - std::cout << saq->ToString() << "\n"; + if (isGroupQuestion) { + GroupQuestion *question = new GroupQuestion(); + // TODO + + } if (isOrderQuestion) { + auto *question = new MultiElementQuestion(); + question->ID = id; + question->QuestionText = questionText; + for (const auto& elem : questionElements) { + Choice choice; + choice.Answer = elem.content; + choice.IsCorrect = !elem.isDash; + question->Choices.push_back(choice); + } + question->Section = section; + questions.push_back(question); + if (debug) { + std::cout << question->ToString() << "\n"; + } } } } else if (tokens[i].tokenType == TokenType::SectionIdentifierStart) { diff --git a/tasks.md b/tasks.md new file mode 100644 index 0000000..9caf4d6 --- /dev/null +++ b/tasks.md @@ -0,0 +1,37 @@ +## 1-N Answer question + +- kfoewf > + - fiewfiwe + +- kfoewf > + - fiewfiwe + - fewpfowe + - fweofopew + - ofpewpofkew + +## Order question + +- ewjpfwe > + ^- ewijfew + ^- ewijfew + ^- ewijfew + ^- ewijfew + ^- ewijfew + +## Match question + +- iowjefew > + - fiwfo: + - fewfew + - ifoewf + - ejpfe: + - _ + - fewfw: + - fewjpfe + - fioewf + +- [ ] Augment the lexer for Order and match question; +- [ ] Parse the questions accordingly; +- [ ] Escape character; + +