diff --git a/WsNovelParser/main.cpp b/WsNovelParser/main.cpp index e4b6ff4..7f1da76 100644 --- a/WsNovelParser/main.cpp +++ b/WsNovelParser/main.cpp @@ -69,15 +69,19 @@ int main(int argc, char* argv[]) { if (files.size()) { try { auto parser = std::make_shared(); - auto docs = parser->parse(files); + auto result_list = parser->parse(files); - auto errors_list = parser->parserContext()->errors(); - if (errors_list.size()) { - for (auto& err : errors_list) { - qDebug().noquote() << err; - } - exit(0); + QList> docs; + bool exit_mark = false; + for (auto fork : result_list) { + docs << fork.mbrs_list; + if(fork.error_messages.size()) + qDebug().noquote() << fork.error_messages; } + + if (exit_mark) + exit(0); + access_ptr = parser->validsApply(docs); } catch (lib_syntax::SyntaxException* e) { diff --git a/WsNovelParser/novelparser.cpp b/WsNovelParser/novelparser.cpp index a54987d..24ad33a 100644 --- a/WsNovelParser/novelparser.cpp +++ b/WsNovelParser/novelparser.cpp @@ -8,6 +8,7 @@ using namespace example_novel; using namespace lib_parse; +using namespace lib_syntax; NovelParser::NovelParser() { @@ -29,29 +30,29 @@ QString NovelParser::version() const return "1.0.0"; } -std::shared_ptr NovelParser::parserContext() const +std::shared_ptr NovelParser::parserContext() const { return context; } -QList> NovelParser::parse(const QFileInfoList source_list) const { +QList NovelParser::parse(const QFileInfoList source_list) const { const_cast(this)->context = std::make_shared(u8"小说"); auto word_reader = std::make_shared(); + QList parse_result; auto time_stamp = QTime::currentTime(); for (auto& file : source_list) { - context->setCurrentFile(file.canonicalFilePath()); auto words = word_reader->wordsFrom(file.canonicalFilePath()); - lib_syntax::IBasicRule::ErrDeals modify = lib_syntax::IBasicRule::ErrDeals::None; - this->syntax_defines->parse(context, words, modify); + ParseFork start; + start.next = words; + parse_result << this->syntax_defines->parse(start); } - QList> forst_root = context->getDocInsts(); auto current_stamp = QTime::currentTime(); qDebug().noquote() << QString(u8"%词法解析+语法解析消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp)); - return forst_root; + return parse_result; } std::shared_ptr NovelParser::validsApply(QList> forst_root) const { diff --git a/WsNovelParser/novelparser.h b/WsNovelParser/novelparser.h index 2bd365e..c538db6 100644 --- a/WsNovelParser/novelparser.h +++ b/WsNovelParser/novelparser.h @@ -22,7 +22,7 @@ public: QList> fragmentsSorted() const; virtual QString version() const; - std::shared_ptr parserContext() const; - QList> parse(const QFileInfoList souurce_list) const; + std::shared_ptr parserContext() const; + QList parse(const QFileInfoList souurce_list) const; std::shared_ptr validsApply(QList> docs_list) const; }; \ No newline at end of file diff --git a/libSyntax/ast_basic.cpp b/libSyntax/ast_basic.cpp index c5431d2..e8eff08 100644 --- a/libSyntax/ast_basic.cpp +++ b/libSyntax/ast_basic.cpp @@ -33,78 +33,3 @@ void ExpressionElement::addChild(std::shared_ptr inst) { QList> ExpressionElement::tokens() const { return this->tokens_bind; } - -ExpressionContext::ExpressionContext() {} - -void ExpressionContext::setCurrentFile(const QString& path) { this->current_file_path = path; } - -QString ExpressionContext::currentFile() const { return this->current_file_path; } - -std::shared_ptr ExpressionContext::currentExprInst() const -{ - if (expression_stack.size()) - return expression_stack.last(); - - return nullptr; -} - -void ExpressionContext::pushExprInst(std::shared_ptr current_inst) -{ - if (!expression_stack.size() || expression_stack.last() != current_inst) - expression_stack.append(current_inst); -} - -std::shared_ptr ExpressionContext::popExprInst() -{ - auto lastx = expression_stack.takeLast(); - return lastx; -} - -std::shared_ptr ExpressionContext::currentExprRule() const { - if (rule_stack.size()) - return rule_stack.last(); - return nullptr; -} - -void ExpressionContext::pushExprRule(std::shared_ptr inst) { - if (!rule_stack.size() || rule_stack.last() != inst) - rule_stack.append(inst); -} - -std::shared_ptr ExpressionContext::popExprRule() -{ - return rule_stack.takeLast(); -} - -void ExpressionContext::appendParseError(const QString& file_path, int start, const QString& e) { - this->errors_storage.append(std::make_tuple(file_path, start, e)); -} - -QStringList ExpressionContext::errors() const { - QStringList values; - for (auto& tp : this->errors_storage) - values.append(QString(u8"文件:%1\n\t%2").arg(std::get<0>(tp)).arg(std::get<2>(tp))); - - return values; -} - -void ExpressionContext::clearErrors(const QString &file_path, int start) { - for (int idx = 0; idx < this->errors_storage.size(); ++idx) { - auto &tp = errors_storage[idx]; - if(std::get<0>(tp) == file_path && std::get<1>(tp) >= start) - errors_storage.removeAt(idx--); - } -} - -QList> ExpressionContext::currentExprRuleStack() const { - return rule_stack; -} - - -void ExpressionContext::appendDocInst(std::shared_ptr inst) { - this->document_store.append(inst); -} - -QList> ExpressionContext::getDocInsts() const { - return this->document_store; -} \ No newline at end of file diff --git a/libSyntax/ast_basic.h b/libSyntax/ast_basic.h index ae90544..09f9ba0 100644 --- a/libSyntax/ast_basic.h +++ b/libSyntax/ast_basic.h @@ -77,35 +77,4 @@ namespace ast_basic { void addChild(std::shared_ptr inst) override; }; - class LIBSYNTAX_EXPORT ExpressionContext : public lib_syntax::IContext, public std::enable_shared_from_this { - private: - QList> rule_stack; - QList> expression_stack; - QList> document_store; - QString current_file_path; - QList> errors_storage; - - public: - ExpressionContext(); - - // 通过 IContext 继承 - virtual void setCurrentFile(const QString& path); - virtual QString currentFile() const; - - std::shared_ptr currentExprInst() const override; - void pushExprInst(std::shared_ptr current_inst) override; - std::shared_ptr popExprInst() override; - - std::shared_ptr currentExprRule() const override; - void pushExprRule(std::shared_ptr inst) override; - std::shared_ptr popExprRule() override; - virtual QList> currentExprRuleStack() const; - - virtual void appendDocInst(std::shared_ptr inst) override; - virtual QList> getDocInsts() const override; - - void appendParseError(const QString& file_path, int start, const QString& error_msg) override; - QStringList errors() const override; - void clearErrors(const QString& file_path, int start) override; - }; } \ No newline at end of file diff --git a/libSyntax/ast_gen.h b/libSyntax/ast_gen.h index 2dc6246..8174068 100644 --- a/libSyntax/ast_gen.h +++ b/libSyntax/ast_gen.h @@ -102,7 +102,7 @@ namespace ast_gen /** * @brief 根元素定义 */ - class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement, public ast_basic::ExpressionContext { + class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement { private: QString names_store; QHash> node_cache; diff --git a/libSyntax/ast_novel.h b/libSyntax/ast_novel.h index c425c84..05b5bfb 100644 --- a/libSyntax/ast_novel.h +++ b/libSyntax/ast_novel.h @@ -168,7 +168,7 @@ namespace example_novel } namespace lib_syntax { - template<> class ElementRule : public ExprRule { + template<> class ElementRule : public lib_syntax::ExprRule { public: ElementRule(const QString& rule_name, int expr_mark) :ExprRule(rule_name, expr_mark) {} @@ -179,64 +179,43 @@ namespace lib_syntax { std::make_shared(this->shared_from_this())); } - virtual std::shared_ptr makeCopy() const { + virtual std::shared_ptr makeCopy() const { return std::make_shared>(name(), typeMark()); } - virtual std::tuple> - parse(std::shared_ptr rt_inst, std::shared_ptr head, IBasicRule::ErrDeals &fx_type) const override { - std::shared_ptr elm_ast = this->newEmptyInstance(); + virtual QList parse(const ParseFork& context) const override { auto text_present = this->token_present(); - rt_inst->pushExprRule(this->shared_from_this()); - rt_inst->pushExprInst(elm_ast); + ParseFork estart; + estart.next = context.next; + auto result_fork = this->child_store->parse(estart); + for (auto rst : result_fork) { + switch (rst.occurs) { + case ErrDeals::None: { + auto tokens_decl = result_fork.first().tokens_list; - IBasicRule::ErrDeals fixed = IBasicRule::ErrDeals::None; - auto rstg = child_store->parse(rt_inst, head, fixed); - auto tokens_decl = elm_ast->tokens(); + while (tokens_decl.size()) { + auto text_paragraph = this->newEmptyInstance(); + int row_n = tokens_decl.first()->row(); - switch (std::get<0>(rstg)) { - case IBasicRule::MatchResult::Fail: - case IBasicRule::MatchResult::Part: - rt_inst->popExprInst(); - rt_inst->popExprRule(); - break; - case IBasicRule::MatchResult::Success: { - if (!std::dynamic_pointer_cast(elm_ast)) { - auto start_pos = head->position(); - rt_inst->clearErrors(rt_inst->currentFile(), start_pos); - } - - rt_inst->popExprInst(); - rt_inst->popExprRule(); - while (tokens_decl.size()) { - auto text_paragraph = this->newEmptyInstance(); - int row_n = tokens_decl.first()->row(); - - for (int idx = 0; idx < tokens_decl.size(); ++idx) { - auto target_token = tokens_decl.at(idx); - if (target_token->row() == row_n) { - text_paragraph->addToken(target_token); - tokens_decl.removeAt(idx--); + for (int idx = 0; idx < tokens_decl.size(); ++idx) { + auto target_token = tokens_decl.at(idx); + if (target_token->row() == row_n) { + text_paragraph->addToken(target_token); + tokens_decl.removeAt(idx--); + } } + rst.mbrs_list << text_paragraph; } - if (rt_inst->currentExprInst()) { - rt_inst->currentExprInst()->addChild(text_paragraph); - } - else { - rt_inst->appendDocInst(text_paragraph); - } + return QList{ rst }; + }break; + default: + break; } - - }break; - default: - break; } - return rstg; + return result_fork; } - - }; } diff --git a/libSyntax/libsyntax.cpp b/libSyntax/libsyntax.cpp index cac13c0..6d97856 100644 --- a/libSyntax/libsyntax.cpp +++ b/libSyntax/libsyntax.cpp @@ -11,75 +11,74 @@ TokenMatch::TokenMatch(shared_ptr define) : define_peer(defi QList> TokenMatch::children() const { return QList>(); } -ParseResult TokenMatch::parse(shared_ptr rt_inst, shared_ptr head, ErrDeals& fx_type) const +QList TokenMatch::parse(const ParseFork& context) const { + auto head = context.next; if (!head) { - rt_inst->appendParseError(rt_inst->currentFile(), -1, QString(u8"Syntax[0x0000]token流(%1)提前终止").arg(rt_inst->currentFile())); - return ParseResult(); + ParseFork result(context); + result.error_messages << u8"输入流提前终止"; + result.next = nullptr; + result.occurs = ErrDeals::TerminalAOT; + return QList{result}; } - ParseResult result_ret; + QList result_list; auto match_result = define_peer->analysis(head); if (get<0>(match_result)) { - rt_inst->currentExprInst()->addToken(get<0>(match_result)); + ParseFork success_fork(context); + success_fork.tokens_list << get<0>(match_result); - decltype(result_ret.result_repair) v_result; if (get<1>(match_result)) { - v_result = make_tuple(MatchResult::Success, make_shared(get<1>(match_result), head->nextWord())); + success_fork.next = make_shared(get<1>(match_result), head->nextWord()); } else { - v_result = make_tuple(MatchResult::Success, head->nextWord()); + success_fork.next = head->nextWord(); } - - if (fx_type == ErrDeals::None) - result_ret.result_straight = v_result; - else - result_ret.result_repair = v_result; } else { - switch (fx_type) { - case lib_syntax::ErrDeals::Replace: - fx_type = ErrDeals::None; - result_ret.result_repair = make_tuple(MatchResult::Success, head->nextWord()); - rt_inst->appendParseError(rt_inst->currentFile(), head->position(), QString(u8"指定Token“%1”匹配错误,应为“%2”。") - .arg(head->content()).arg(this->define_peer->reviseWords()).arg(head->row()).arg(head->column())); - break; + if (context.occurs != ErrDeals::None) { + ParseFork fail_fork(context); + fail_fork.error_messages << QString(u8"Syntax[0x0001]解析终止,Token匹配失败('%1')。") + .arg(head->content()).arg(head->row()).arg(head->column()); + fail_fork.next = nullptr; + fail_fork.occurs = ErrDeals::Abort; - case lib_syntax::ErrDeals::Absence: - fx_type = ErrDeals::None; - result_ret.result_repair = make_tuple(MatchResult::Success, head); - rt_inst->appendParseError(rt_inst->currentFile(), head->position(), QString(u8"指定位置缺失Token,应为“%1”。") - .arg(this->define_peer->reviseWords()).arg(head->row()).arg(head->column())); - break; + return result_list << fail_fork; + } + // 缺一个 + ParseFork absence_fork(context); + result_list << absence_fork; + absence_fork.error_messages << QString(u8"Syntax[0x0002]缺失Token('%1')。") + .arg(this->token_present()).arg(head->row()).arg(head->column()); + absence_fork.next = head; + absence_fork.occurs = ErrDeals::Absence; - case lib_syntax::ErrDeals::Surplus: - fx_type = ErrDeals::None; - { - auto temp_head = head->nextWord(); - auto match_result = define_peer->analysis(temp_head); - if (get<0>(match_result)) { - rt_inst->appendParseError(rt_inst->currentFile(), head->position(), QString(u8"发现冗余Token,内容为“%1”。") - .arg(head->content()).arg(head->row()).arg(head->column())); + // 错一个 + ParseFork replace_fork(context); + result_list << replace_fork; + replace_fork.error_messages << QString(u8"Syntax[0x0003]纠正Token('%1',应该为'%4')。") + .arg(head->content()).arg(head->row()).arg(head->column()).arg(this->token_present()); + replace_fork.next = head->nextWord(); + replace_fork.occurs = ErrDeals::Replace; - rt_inst->currentExprInst()->addToken(get<0>(match_result)); - if (get<1>(match_result)) - result_ret.result_repair = make_tuple(MatchResult::Success, make_shared(get<1>(match_result), temp_head->nextWord())); - else - result_ret.result_repair = make_tuple(MatchResult::Success, temp_head->nextWord()); - } - else { - result_ret.result_repair = make_tuple(MatchResult::Part, head); - } - } - break; + // 多一个 + auto temp_head = head->nextWord(); + auto match_result = define_peer->analysis(temp_head); + if (get<0>(match_result)) { + ParseFork surplus_fork(context); + result_list << surplus_fork; + surplus_fork.error_messages << QString(u8"Syntax[0x0004]发现冗余Token('%1')。") + .arg(head->content()).arg(head->row()).arg(head->column()); + surplus_fork.occurs = ErrDeals::Surplus; + surplus_fork.tokens_list << get<0>(match_result); - default: - result_ret.result_straight = make_tuple(MatchResult::Part, head); - break; + if (get<1>(match_result)) + surplus_fork.next = make_shared(get<1>(match_result), temp_head->nextWord()); + else + surplus_fork.next = temp_head->nextWord(); } } - - return result_ret; + return result_list; } QString TokenMatch::token_present() const { @@ -90,78 +89,97 @@ Rept::Rept(shared_ptr rule, int min, int max) : rule_peer(rule QList> Rept::children() const { return QList>() << rule_peer; } -ParseResult Rept::parse(shared_ptr rt_inst, shared_ptr head, ErrDeals& fx_type) const { - ParseResult fnl_result; +QList tidy_results(QList temp_results) { + QList ret_forks; + std::copy_if(temp_results.begin(), temp_results.end(), std::back_inserter(ret_forks), + [](ParseFork elm)->bool { + return elm.occurs == ErrDeals::None; + }); - auto temp_head = head; - auto initial_fxtype = ErrDeals::None; + // 成功匹配 + if (ret_forks.size()) + return ret_forks; -retry_entry: - switch (initial_fxtype) { - case lib_syntax::ErrDeals::Surplus: - case lib_syntax::ErrDeals::Absence: - case lib_syntax::ErrDeals::Replace: + std::copy_if(temp_results.begin(), temp_results.end(), std::back_inserter(ret_forks), + [](ParseFork elm)->bool { + return elm.occurs == ErrDeals::Absence || elm.occurs == ErrDeals::Surplus || elm.occurs == ErrDeals::Replace; + }); + // 修正匹配 + if (ret_forks.size()) + return ret_forks; - break; - case lib_syntax::ErrDeals::None: - // min-match - for (auto idx = 0; idx < min_match; ++idx) { - auto result_genx = rule_peer->parse(rt_inst, temp_head, initial_fxtype); + // 失败匹配 + return temp_results; +} - switch (std::get<0>(result_genx.result_straight)) { - case MatchResult::Part: - if(fx_type == ErrDeals::None) - return result_genx; +QList Rept::parse(const ParseFork& context) const { + std::function(const ParseFork&, int)> min_match_calc = + [&](const ParseFork& context, int times_remains)->QList { + QList retvs; - initial_fxtype = fx_type; - temp_head = head; - goto retry_entry; + if (!times_remains) + return retvs << context; + auto result_forks = rule_peer->parse(context); + for (auto it : result_forks) { + switch (it.occurs) { + case ErrDeals::Abort: + case ErrDeals::TerminalAOT: + retvs << it; + break; default: - temp_head = std::get<1>(result_genx.result_straight); + retvs << min_match_calc(it, times_remains - 1); break; } } - // max-match - for (auto idx = min_match; idx < max_match; ++idx) { - if (!temp_head) + return retvs; + }; + + std::function(const ParseFork&, int)> max_match_calc = + [&](const ParseFork& context, int times_remains) -> QList { + QList retvs; + + if (!times_remains) + return retvs << context; + + auto result_forks = rule_peer->parse(context); + for (auto rst : result_forks) { + switch (rst.occurs) { + case ErrDeals::Abort: + case ErrDeals::TerminalAOT: + retvs << context; break; - auto result_genx = rule_peer->parse(rt_inst, temp_head, initial_fxtype); - auto v_result = result_genx.result_straight; - if (std::get<0>(v_result) == MatchResult::None) { - v_result = result_genx.result_repair; - } - - switch (get<0>(v_result)) { - case MatchResult::Part: - if (straight_flags) - fnl_result.result_straight = v_result; - else - fnl_result.result_repair = v_result; - return fnl_result; - + case ErrDeals::Surplus: + case ErrDeals::Absence: + case ErrDeals::Replace: + if (context.occurs == ErrDeals::None) + retvs << context; default: - temp_head = get<1>(v_result); + retvs << max_match_calc(rst, times_remains - 1); break; } } - break; - default: - break; - } + return retvs;; + }; + + auto temp_results = min_match_calc(context, min_match); + auto rst_itor = std::find_if(temp_results.begin(), temp_results.end(), [](ParseFork e) -> bool { + return QList{ ErrDeals::None, ErrDeals::Surplus, ErrDeals::Absence, ErrDeals::Replace }.contains(e.occurs); + }); - if(straight_flags) - fnl_result.result_straight = make_tuple(MatchResult::Success, temp_head); - else - fnl_result.result_repair = make_tuple(MatchResult::Success, temp_head); + if(rst_itor == temp_results.end()) + return temp_results; - fx_type = initial_fxtype; - return fnl_result; + decltype(temp_results) result_x2; + for(auto xit : temp_results) + result_x2 << max_match_calc(xit, max_match - min_match); + + return tidy_results(result_x2); } QString Rept::token_present() const @@ -173,40 +191,35 @@ Seqs::Seqs(const QList> mbrs) : mbrs_store(mbrs) {} QList> Seqs::children() const { return mbrs_store; } -ParseResult Seqs::parse(shared_ptr rt_inst, shared_ptr head, ErrDeals& fx_type) const { - ParseResult result_final; +QList Seqs::parse(const ParseFork& context) const { + function(const ParseFork &, QList>::const_iterator)> match_seqs = + [&](const ParseFork& context, QList>::const_iterator rule_it) -> QList { + QList retvs; - auto temp_head = head; - bool straight_mark = fx_type == ErrDeals::None; - for (auto& r : mbrs_store) { - auto rule_present = r->token_present(); - auto rst_gene = r->parse(rt_inst, temp_head, fx_type); + auto cendx = mbrs_store.cend(); + if(rule_it == mbrs_store.cend()) + return retvs << context; - auto v_result = rst_gene.result_straight; - if (std::get<0>(v_result) == MatchResult::None) - v_result = rst_gene.result_repair; + auto rule_present = (*rule_it)->token_present(); + auto result_forks = (*rule_it)->parse(context); + for (auto fork : result_forks) { + switch (fork.occurs) { + case ErrDeals::Abort: + case ErrDeals::TerminalAOT: + retvs << fork; + break; - switch (get<0>(v_result)) { - case MatchResult::Part: - if (straight_mark) - result_final.result_straight = v_result; - else - result_final.result_repair = v_result; - return result_final; - - case MatchResult::Success: - temp_head = get<1>(v_result); - break; - default: - break; + default: + retvs << match_seqs(fork, rule_it + 1); + break; + } } - } - if (straight_mark) - result_final.result_straight = make_tuple(MatchResult::Success, temp_head); - else - result_final.result_repair = make_tuple(MatchResult::Success, temp_head); - return result_final; + return retvs; + }; + + auto temp_results = match_seqs(context, mbrs_store.cbegin()); + return tidy_results(temp_results); } QString Seqs::token_present() const @@ -217,93 +230,30 @@ QString Seqs::token_present() const return content; } -//tuple, shared_ptr> + Any::Any(const QList> mbrs) : mbrs_store(mbrs) {} QList> Any::children() const { return mbrs_store; } -ParseResult Any::parse(shared_ptr rt_inst, shared_ptr head, ErrDeals& fx_type) const { +QList Any::parse(const ParseFork& context) const { auto rule_present = this->token_present(); + QList temp_results; - std::tuple, uint64_t> temp_result = std::make_tuple(nullptr, 0); - bool straight_mark = fx_type == + for (auto& fork : mbrs_store) { + auto result_forks = fork->parse(context); + for (auto rst_fork : result_forks) { + switch (rst_fork.occurs) { + case ErrDeals::None: + return QList{ rst_fork }; - switch (fx_type) { - case ErrDeals::None: { - ParseResult result_final; - for (auto& fork : mbrs_store) { - auto xgen = fork->parse(rt_inst, head, fx_type); - - auto v_result = xgen.result_straight; - if (std::get<0>(v_result) == MatchResult::None) - v_result = xgen.result_repair; - - switch (get<0>(v_result)) { - // 遇到成功的直接返回解析结果 - case MatchResult::Success: - return gen; - - case MatchResult::Part: { - auto span = get<1>(gen.result_straight)->position() - head->position(); - if (span >= get<1>(temp_result)) - temp_result = make_tuple(fork, span); - } - default: - break; - } + default: + temp_results << rst_fork; + break; } - - for (auto& itfx : QList{ ErrDeals::Surplus, ErrDeals::Absence, ErrDeals::Replace }) { - auto fix_current = itfx; - auto repair_result = this->parse(rt_inst, head, fix_current); - - auto v_result = repair_result.result_straight; - if (std::get<0>(v_result) == MatchResult::None) - v_result = repair_result.result_repair; - - switch (std::get<0>(v_result)) { - case MatchResult::Success: - - - default: - break; - } - } - - }break; - - default: { - ParseResult inst; - - for (auto& fork : mbrs_store) { - auto fx_init = fx_type; - - auto gen = fork->parse(rt_inst, head, fx_init); - auto v_result = gen.result_straight; - if (std::get<0>(v_result) == MatchResult::None) - v_result = gen.result_repair; - - switch (std::get<0>(v_result)) { - case MatchResult::Success: - inst.result_repair = v_result; - fx_type = fx_init; - return inst; - - default: { - auto span = std::get<1>(v_result)->position() - head->position(); - if (span >= std::get<1>(temp_result)) - temp_result = std::make_tuple(fork, span); - }break; - } - } - - }break; } + } - // 分析最匹配的分支 - rt_inst->clearErrors(rt_inst->currentFile(), head->position()); - auto temp = get<0>(temp_result)->parse(rt_inst, head, fx_type); - return make_tuple(MatchResult::Part, get<1>(temp)); + return tidy_results(temp_results); } QString Any::token_present() const @@ -339,45 +289,67 @@ QList> ExprRule::children() const { } #include -tuple> -ExprRule::parse(shared_ptr rt_inst, shared_ptr head, ErrDeals& fx_type) const { +QList ExprRule::parse(const ParseFork& context) const { auto text_present = this->token_present(); - shared_ptr elm_ast = this->newEmptyInstance(); - rt_inst->pushExprRule(this->shared_from_this()); - rt_inst->pushExprInst(elm_ast); + ParseFork elm_start; + elm_start.next = context.next; - auto ret_tuple = child_store->parse(rt_inst, head, fx_type); - switch (get<0>(ret_tuple)) { - case MatchResult::Success: - if (!dynamic_pointer_cast(elm_ast) && fx_type == ErrDeals::None) { - rt_inst->clearErrors(rt_inst->currentFile(), head->position()); + QList temp_returns; + auto result_forks = child_store->parse(elm_start); + for (auto fork : result_forks) { + switch (fork.occurs) { + case ErrDeals::None: { + ParseFork value(context); + shared_ptr elm_ast = this->newEmptyInstance(); + for (auto& token : fork.tokens_list) + elm_ast->addToken(token); + for (auto& child : fork.mbrs_list) + elm_ast->addChild(child); + + value.mbrs_list << elm_ast; + value.next = fork.next; + + return QList{ value }; } - rt_inst->popExprInst(); - rt_inst->popExprRule(); + case ErrDeals::Surplus: + case ErrDeals::Absence: + case ErrDeals::Replace: { + ParseFork value(context); + value.error_messages << fork.error_messages; + shared_ptr elm_ast = this->newEmptyInstance(); + for (auto& token : fork.tokens_list) + elm_ast->addToken(token); + for (auto& child : fork.mbrs_list) + elm_ast->addChild(child); - if (rt_inst->currentExprInst()) { - rt_inst->currentExprInst()->addChild(elm_ast); + value.mbrs_list << elm_ast; + value.next = fork.next; + + temp_returns << value; + } break; + + default: + break; } - else { - rt_inst->appendDocInst(elm_ast); - } - break; - - case MatchResult::Part: - case MatchResult::Fail: - rt_inst->popExprInst(); - rt_inst->popExprRule(); - break; - - default: - break; } - return ret_tuple; + // 修正后的完整匹配结果 + if (temp_returns.size()) + return temp_returns; + + return result_forks; } QString ExprRule::token_present() const { return child_store->token_present(); } + +ParseFork::ParseFork() : occurs(ErrDeals::None) {} + +ParseFork::ParseFork(const ParseFork& other) + : occurs(other.occurs), + error_messages(other.error_messages), + mbrs_list(other.mbrs_list), + tokens_list(other.tokens_list) {} diff --git a/libSyntax/libsyntax.h b/libSyntax/libsyntax.h index 9c17f7c..9d8c408 100644 --- a/libSyntax/libsyntax.h +++ b/libSyntax/libsyntax.h @@ -28,63 +28,30 @@ namespace lib_syntax { }; // 基础语法解析接口 =================================================================================================== - /** - * @brief 解析上下文接口 - */ - class IContext { - public: - virtual ~IContext() = default; - - virtual void setCurrentFile(const QString& path) = 0; - virtual QString currentFile() const = 0; - - virtual void appendParseError(const QString& file_path, int start, const QString& error_msg) = 0; - virtual QStringList errors() const = 0; - virtual void clearErrors(const QString& file_path, int start) = 0; - - virtual void appendDocInst(std::shared_ptr inst) = 0; - virtual QList> getDocInsts() const = 0; - - /** - * \brief 当前表达式元素. - * - * \return 返回当前表达式 - */ - virtual std::shared_ptr currentExprInst() const = 0; - virtual void pushExprInst(std::shared_ptr current_inst) = 0; - virtual std::shared_ptr popExprInst() = 0; - - virtual std::shared_ptr currentExprRule() const = 0; - virtual void pushExprRule(std::shared_ptr inst) = 0; - virtual std::shared_ptr popExprRule() = 0; - virtual QList> currentExprRuleStack() const = 0; - }; - - /** - * @brief 匹配结果 - */ - enum class MatchResult { - None, // 不适用 - Success, // 符合匹配条件 - Part, // 部分匹配 - }; - /** * @brief 修正类型 */ enum class ErrDeals { - None, // 不修复 - Surplus, // 多一个词 - Absence, // 少一个词 - Replace, // 错一个词 + None, // 无错误 + Surplus, // 多一个词 + Absence, // 少一个词 + Replace, // 错一个词 + Abort, // 中断解析过程 + TerminalAOT, // 输入提前终止 }; /** - * 匹配结果,返回直接匹配结果和修复匹配结果. - */ - struct ParseResult { - std::tuple> result_straight = std::make_tuple(MatchResult::None, nullptr); - std::tuple> result_repair = std::make_tuple(MatchResult::None, nullptr); + * @brief 解析分支 + */ + struct LIBSYNTAX_EXPORT ParseFork { + ErrDeals occurs = ErrDeals::None; // 解析过程中的错误 + QList error_messages; // 累计错误信息 + QList> mbrs_list; // 成员存储 + QList> tokens_list; // token列表 + std::shared_ptr next = nullptr; // 下一个解析词 + + ParseFork(); + ParseFork(const ParseFork& other); }; /** @@ -102,12 +69,10 @@ namespace lib_syntax { /** * @brief 解析 - * @param rt_inst 解析上下文 - * @param head 列表头 - * @param fx_type 修正措施 - * @return 返回结果<匹配完成新列表头,匹配长度> + * @param context 累计上下文 + * @return 返回结果<解析分支> */ - virtual ParseResult parse(std::shared_ptr rt_inst, std::shared_ptr head, ErrDeals& fx_type) const = 0; + virtual QList parse(const ParseFork& context) const = 0; /** * 返回匹配语法规则的词法序列表达 @@ -131,7 +96,7 @@ namespace lib_syntax { // IBasicRule interface public: virtual QList> children() const override; - virtual ParseResult parse(std::shared_ptr rt_inst, std::shared_ptr head, ErrDeals& fx_type) const override; + virtual QList parse(const ParseFork& context) const override; virtual QString token_present() const override; }; @@ -142,15 +107,13 @@ namespace lib_syntax { private: QList> mbrs_store; - std::tuple, std::shared_ptr> rule_select(std::shared_ptr head) const; - public: Any(const QList> mbrs); // IBasicRule interface public: virtual QList> children() const override; - virtual ParseResult parse(std::shared_ptr rt_inst, std::shared_ptr head, ErrDeals& fx_type) const override; + virtual QList parse(const ParseFork& context) const override; virtual QString token_present() const override; }; @@ -167,7 +130,7 @@ namespace lib_syntax { // IBasicRule interface public: virtual QList> children() const override; - virtual ParseResult parse(std::shared_ptr rt_inst, std::shared_ptr head, ErrDeals& fx_type) const override; + virtual QList parse(const ParseFork& context) const override; virtual QString token_present() const override; }; @@ -185,7 +148,7 @@ namespace lib_syntax { // IBasicRule interface public: virtual QList> children() const override; - virtual ParseResult parse(std::shared_ptr rt_inst, std::shared_ptr head, ErrDeals& fx_type) const override; + virtual QList parse(const ParseFork& context) const override; virtual QString token_present() const override; }; @@ -193,7 +156,7 @@ namespace lib_syntax { /** * @brief 对应语法表达式解析规则 */ - class LIBSYNTAX_EXPORT ExprRule : public lib_syntax::IBasicRule, public std::enable_shared_from_this { + class LIBSYNTAX_EXPORT ExprRule : public IBasicRule, public std::enable_shared_from_this { public: typedef QList> TokenSeqs; ExprRule(const QString& rule_name, int expr_mark); @@ -207,12 +170,12 @@ namespace lib_syntax { // IBasicRule interface public: - virtual QList> children() const override; - virtual ParseResult parse(std::shared_ptr rt_inst, std::shared_ptr head, ErrDeals& fx_type) const override; + virtual QList> children() const override; + virtual QList parse(const ParseFork& context) const override; virtual QString token_present() const override; protected: - std::shared_ptr child_store; + std::shared_ptr child_store; private: QString name_store; diff --git a/libSyntax/syntax_novel.cpp b/libSyntax/syntax_novel.cpp index 9d23167..f8dd49f 100644 --- a/libSyntax/syntax_novel.cpp +++ b/libSyntax/syntax_novel.cpp @@ -119,7 +119,7 @@ void NovalSyntax::node_register(std::shared_ptr ro if (!child->isAnonymous()) { auto check_result = ast_gen::GlobalElement::UniquePtr->appendToCache(child); if (check_result) - throw new lib_syntax::SyntaxException(QString(u8"SyntaxError[0x0004]系统中包含同类型重名命名节点:%1(%3,%4)") + throw new SyntaxException(QString(u8"SyntaxError[0x0004]系统中包含同类型重名命名节点:%1(%3,%4)") .arg(child->signature()).arg(child->typeMark()).arg(child->path()).arg(check_result->path())); }