添加改进措施

This commit is contained in:
codeboss 2024-07-25 10:29:31 +08:00
parent 26eab5a092
commit 0df0e77df5
10 changed files with 282 additions and 469 deletions

View File

@ -69,15 +69,19 @@ int main(int argc, char* argv[]) {
if (files.size()) { if (files.size()) {
try { try {
auto parser = std::make_shared<NovelParser>(); auto parser = std::make_shared<NovelParser>();
auto docs = parser->parse(files); auto result_list = parser->parse(files);
auto errors_list = parser->parserContext()->errors(); QList<std::shared_ptr<const ast_basic::IExprInst>> docs;
if (errors_list.size()) { bool exit_mark = false;
for (auto& err : errors_list) { for (auto fork : result_list) {
qDebug().noquote() << err; docs << fork.mbrs_list;
} if(fork.error_messages.size())
exit(0); qDebug().noquote() << fork.error_messages;
} }
if (exit_mark)
exit(0);
access_ptr = parser->validsApply(docs); access_ptr = parser->validsApply(docs);
} }
catch (lib_syntax::SyntaxException* e) { catch (lib_syntax::SyntaxException* e) {

View File

@ -8,6 +8,7 @@
using namespace example_novel; using namespace example_novel;
using namespace lib_parse; using namespace lib_parse;
using namespace lib_syntax;
NovelParser::NovelParser() NovelParser::NovelParser()
{ {
@ -29,29 +30,29 @@ QString NovelParser::version() const
return "1.0.0"; return "1.0.0";
} }
std::shared_ptr<lib_syntax::IContext> NovelParser::parserContext() const std::shared_ptr<ast_gen::GlobalElement> NovelParser::parserContext() const
{ {
return context; return context;
} }
QList<std::shared_ptr<const ast_basic::IExprInst>> NovelParser::parse(const QFileInfoList source_list) const { QList<ParseFork> NovelParser::parse(const QFileInfoList source_list) const {
const_cast<NovelParser*>(this)->context = std::make_shared<ast_gen::GlobalElement>(u8"小说"); const_cast<NovelParser*>(this)->context = std::make_shared<ast_gen::GlobalElement>(u8"小说");
auto word_reader = std::make_shared<lib_token::WordReader>(); auto word_reader = std::make_shared<lib_token::WordReader>();
QList<ParseFork> parse_result;
auto time_stamp = QTime::currentTime(); auto time_stamp = QTime::currentTime();
for (auto& file : source_list) { for (auto& file : source_list) {
context->setCurrentFile(file.canonicalFilePath());
auto words = word_reader->wordsFrom(file.canonicalFilePath()); auto words = word_reader->wordsFrom(file.canonicalFilePath());
lib_syntax::IBasicRule::ErrDeals modify = lib_syntax::IBasicRule::ErrDeals::None; ParseFork start;
this->syntax_defines->parse(context, words, modify); start.next = words;
parse_result << this->syntax_defines->parse(start);
} }
QList<std::shared_ptr<const ast_basic::IExprInst>> forst_root = context->getDocInsts();
auto current_stamp = QTime::currentTime(); auto current_stamp = QTime::currentTime();
qDebug().noquote() << QString(u8"%词法解析+语法解析消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp)); qDebug().noquote() << QString(u8"%词法解析+语法解析消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp));
return forst_root; return parse_result;
} }
std::shared_ptr<const ast_gen::ElementAccess> NovelParser::validsApply(QList<std::shared_ptr<const ast_basic::IExprInst>> forst_root) const { std::shared_ptr<const ast_gen::ElementAccess> NovelParser::validsApply(QList<std::shared_ptr<const ast_basic::IExprInst>> forst_root) const {

View File

@ -22,7 +22,7 @@ public:
QList<std::shared_ptr<const example_novel::FragmentGraphHelper>> fragmentsSorted() const; QList<std::shared_ptr<const example_novel::FragmentGraphHelper>> fragmentsSorted() const;
virtual QString version() const; virtual QString version() const;
std::shared_ptr<lib_syntax::IContext> parserContext() const; std::shared_ptr<ast_gen::GlobalElement> parserContext() const;
QList<std::shared_ptr<const ast_basic::IExprInst>> parse(const QFileInfoList souurce_list) const; QList<lib_syntax::ParseFork> parse(const QFileInfoList souurce_list) const;
std::shared_ptr<const ast_gen::ElementAccess> validsApply(QList<std::shared_ptr<const ast_basic::IExprInst>> docs_list) const; std::shared_ptr<const ast_gen::ElementAccess> validsApply(QList<std::shared_ptr<const ast_basic::IExprInst>> docs_list) const;
}; };

View File

@ -33,78 +33,3 @@ void ExpressionElement::addChild(std::shared_ptr<const IExprInst> inst) {
QList<std::shared_ptr<const IToken>> ExpressionElement::tokens() const { QList<std::shared_ptr<const IToken>> ExpressionElement::tokens() const {
return this->tokens_bind; 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<IExprInst> ExpressionContext::currentExprInst() const
{
if (expression_stack.size())
return expression_stack.last();
return nullptr;
}
void ExpressionContext::pushExprInst(std::shared_ptr<IExprInst> current_inst)
{
if (!expression_stack.size() || expression_stack.last() != current_inst)
expression_stack.append(current_inst);
}
std::shared_ptr<IExprInst> ExpressionContext::popExprInst()
{
auto lastx = expression_stack.takeLast();
return lastx;
}
std::shared_ptr<const IBasicRule> ExpressionContext::currentExprRule() const {
if (rule_stack.size())
return rule_stack.last();
return nullptr;
}
void ExpressionContext::pushExprRule(std::shared_ptr<const IBasicRule> inst) {
if (!rule_stack.size() || rule_stack.last() != inst)
rule_stack.append(inst);
}
std::shared_ptr<const IBasicRule> 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<std::shared_ptr<const IBasicRule>> ExpressionContext::currentExprRuleStack() const {
return rule_stack;
}
void ExpressionContext::appendDocInst(std::shared_ptr<ast_basic::IExprInst> inst) {
this->document_store.append(inst);
}
QList<std::shared_ptr<const ast_basic::IExprInst>> ExpressionContext::getDocInsts() const {
return this->document_store;
}

View File

@ -77,35 +77,4 @@ namespace ast_basic {
void addChild(std::shared_ptr<const IExprInst> inst) override; void addChild(std::shared_ptr<const IExprInst> inst) override;
}; };
class LIBSYNTAX_EXPORT ExpressionContext : public lib_syntax::IContext, public std::enable_shared_from_this<ExpressionContext> {
private:
QList<std::shared_ptr<const lib_syntax::IBasicRule>> rule_stack;
QList<std::shared_ptr<IExprInst>> expression_stack;
QList<std::shared_ptr<const ast_basic::IExprInst>> document_store;
QString current_file_path;
QList<std::tuple<QString, int, QString>> errors_storage;
public:
ExpressionContext();
// ͨ¹ý IContext ¼Ì³Ð
virtual void setCurrentFile(const QString& path);
virtual QString currentFile() const;
std::shared_ptr<ast_basic::IExprInst> currentExprInst() const override;
void pushExprInst(std::shared_ptr<ast_basic::IExprInst> current_inst) override;
std::shared_ptr<ast_basic::IExprInst> popExprInst() override;
std::shared_ptr<const lib_syntax::IBasicRule> currentExprRule() const override;
void pushExprRule(std::shared_ptr<const lib_syntax::IBasicRule> inst) override;
std::shared_ptr<const lib_syntax::IBasicRule> popExprRule() override;
virtual QList<std::shared_ptr<const lib_syntax::IBasicRule>> currentExprRuleStack() const;
virtual void appendDocInst(std::shared_ptr<ast_basic::IExprInst> inst) override;
virtual QList<std::shared_ptr<const ast_basic::IExprInst>> 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;
};
} }

View File

@ -102,7 +102,7 @@ namespace ast_gen
/** /**
* @brief ¸ùÔªËØ¨Òå * @brief ¸ùÔªËØ¨Òå
*/ */
class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement, public ast_basic::ExpressionContext { class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement {
private: private:
QString names_store; QString names_store;
QHash<QString, std::shared_ptr<const SyntaxElement>> node_cache; QHash<QString, std::shared_ptr<const SyntaxElement>> node_cache;

View File

@ -168,7 +168,7 @@ namespace example_novel
} }
namespace lib_syntax { namespace lib_syntax {
template<> class ElementRule<example_novel::TextSection> : public ExprRule { template<> class ElementRule<example_novel::TextSection> : public lib_syntax::ExprRule {
public: public:
ElementRule<example_novel::TextSection>(const QString& rule_name, int expr_mark) ElementRule<example_novel::TextSection>(const QString& rule_name, int expr_mark)
:ExprRule(rule_name, expr_mark) {} :ExprRule(rule_name, expr_mark) {}
@ -179,64 +179,43 @@ namespace lib_syntax {
std::make_shared<example_novel::TextSection>(this->shared_from_this())); std::make_shared<example_novel::TextSection>(this->shared_from_this()));
} }
virtual std::shared_ptr<ExprRule> makeCopy() const { virtual std::shared_ptr<lib_syntax::ExprRule> makeCopy() const {
return std::make_shared<ElementRule<example_novel::TextSection>>(name(), typeMark()); return std::make_shared<ElementRule<example_novel::TextSection>>(name(), typeMark());
} }
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>> virtual QList<ParseFork> parse(const ParseFork& context) const override {
parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, IBasicRule::ErrDeals &fx_type) const override {
std::shared_ptr<ast_basic::IExprInst> elm_ast = this->newEmptyInstance();
auto text_present = this->token_present(); auto text_present = this->token_present();
rt_inst->pushExprRule(this->shared_from_this()); ParseFork estart;
rt_inst->pushExprInst(elm_ast); 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; while (tokens_decl.size()) {
auto rstg = child_store->parse(rt_inst, head, fixed); auto text_paragraph = this->newEmptyInstance();
auto tokens_decl = elm_ast->tokens(); int row_n = tokens_decl.first()->row();
switch (std::get<0>(rstg)) { for (int idx = 0; idx < tokens_decl.size(); ++idx) {
case IBasicRule::MatchResult::Fail: auto target_token = tokens_decl.at(idx);
case IBasicRule::MatchResult::Part: if (target_token->row() == row_n) {
rt_inst->popExprInst(); text_paragraph->addToken(target_token);
rt_inst->popExprRule(); tokens_decl.removeAt(idx--);
break; }
case IBasicRule::MatchResult::Success: {
if (!std::dynamic_pointer_cast<example_novel::Document>(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--);
} }
rst.mbrs_list << text_paragraph;
} }
if (rt_inst->currentExprInst()) { return QList<ParseFork>{ rst };
rt_inst->currentExprInst()->addChild(text_paragraph); }break;
} default:
else { break;
rt_inst->appendDocInst(text_paragraph);
}
} }
}break;
default:
break;
} }
return rstg; return result_fork;
} }
}; };
} }

View File

@ -11,75 +11,74 @@ TokenMatch::TokenMatch(shared_ptr<const ITokenDefine> define) : define_peer(defi
QList<shared_ptr<const IBasicRule>> TokenMatch::children() const { return QList<shared_ptr<const IBasicRule>>(); } QList<shared_ptr<const IBasicRule>> TokenMatch::children() const { return QList<shared_ptr<const IBasicRule>>(); }
ParseResult TokenMatch::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const QList<ParseFork> TokenMatch::parse(const ParseFork& context) const
{ {
auto head = context.next;
if (!head) { if (!head) {
rt_inst->appendParseError(rt_inst->currentFile(), -1, QString(u8"Syntax[0x0000]token流%1提前终止").arg(rt_inst->currentFile())); ParseFork result(context);
return ParseResult(); result.error_messages << u8"输入流提前终止";
result.next = nullptr;
result.occurs = ErrDeals::TerminalAOT;
return QList<ParseFork>{result};
} }
ParseResult result_ret; QList<ParseFork> result_list;
auto match_result = define_peer->analysis(head); auto match_result = define_peer->analysis(head);
if (get<0>(match_result)) { 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)) { if (get<1>(match_result)) {
v_result = make_tuple(MatchResult::Success, make_shared<WordImpl>(get<1>(match_result), head->nextWord())); success_fork.next = make_shared<WordImpl>(get<1>(match_result), head->nextWord());
} }
else { 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 { else {
switch (fx_type) { if (context.occurs != ErrDeals::None) {
case lib_syntax::ErrDeals::Replace: ParseFork fail_fork(context);
fx_type = ErrDeals::None; fail_fork.error_messages << QString(u8"Syntax[0x0001]解析终止Token匹配失败'%1'<row:%2,col:%3>)。")
result_ret.result_repair = make_tuple(MatchResult::Success, head->nextWord()); .arg(head->content()).arg(head->row()).arg(head->column());
rt_inst->appendParseError(rt_inst->currentFile(), head->position(), QString(u8"指定Token<row:%3,col:%4>“%1”匹配错误应为“%2”。") fail_fork.next = nullptr;
.arg(head->content()).arg(this->define_peer->reviseWords()).arg(head->row()).arg(head->column())); fail_fork.occurs = ErrDeals::Abort;
break;
case lib_syntax::ErrDeals::Absence: return result_list << fail_fork;
fx_type = ErrDeals::None; }
result_ret.result_repair = make_tuple(MatchResult::Success, head); // 缺一个
rt_inst->appendParseError(rt_inst->currentFile(), head->position(), QString(u8"指定位置缺失Token<row:%2,col:%3>,应为“%1”。") ParseFork absence_fork(context);
.arg(this->define_peer->reviseWords()).arg(head->row()).arg(head->column())); result_list << absence_fork;
break; absence_fork.error_messages << QString(u8"Syntax[0x0002]缺失Token'%1'<row:%2,col:%3>)。")
.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; ParseFork replace_fork(context);
{ result_list << replace_fork;
auto temp_head = head->nextWord(); replace_fork.error_messages << QString(u8"Syntax[0x0003]纠正Token'%1'<row:%2,col:%3>,应该为'%4')。")
auto match_result = define_peer->analysis(temp_head); .arg(head->content()).arg(head->row()).arg(head->column()).arg(this->token_present());
if (get<0>(match_result)) { replace_fork.next = head->nextWord();
rt_inst->appendParseError(rt_inst->currentFile(), head->position(), QString(u8"发现冗余Token<row:%2,col:%3>,内容为“%1”。") replace_fork.occurs = ErrDeals::Replace;
.arg(head->content()).arg(head->row()).arg(head->column()));
rt_inst->currentExprInst()->addToken(get<0>(match_result)); // 多一个
if (get<1>(match_result)) auto temp_head = head->nextWord();
result_ret.result_repair = make_tuple(MatchResult::Success, make_shared<WordImpl>(get<1>(match_result), temp_head->nextWord())); auto match_result = define_peer->analysis(temp_head);
else if (get<0>(match_result)) {
result_ret.result_repair = make_tuple(MatchResult::Success, temp_head->nextWord()); ParseFork surplus_fork(context);
} result_list << surplus_fork;
else { surplus_fork.error_messages << QString(u8"Syntax[0x0004]发现冗余Token'%1'<row:%2,col:%3>)。")
result_ret.result_repair = make_tuple(MatchResult::Part, head); .arg(head->content()).arg(head->row()).arg(head->column());
} surplus_fork.occurs = ErrDeals::Surplus;
} surplus_fork.tokens_list << get<0>(match_result);
break;
default: if (get<1>(match_result))
result_ret.result_straight = make_tuple(MatchResult::Part, head); surplus_fork.next = make_shared<WordImpl>(get<1>(match_result), temp_head->nextWord());
break; else
surplus_fork.next = temp_head->nextWord();
} }
} }
return result_list;
return result_ret;
} }
QString TokenMatch::token_present() const { QString TokenMatch::token_present() const {
@ -90,78 +89,97 @@ Rept::Rept(shared_ptr<const IBasicRule> rule, int min, int max) : rule_peer(rule
QList<shared_ptr<const IBasicRule>> Rept::children() const { return QList<shared_ptr<const IBasicRule>>() << rule_peer; } QList<shared_ptr<const IBasicRule>> Rept::children() const { return QList<shared_ptr<const IBasicRule>>() << rule_peer; }
ParseResult Rept::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const { QList<ParseFork> tidy_results(QList<ParseFork> temp_results) {
ParseResult fnl_result; QList<ParseFork> 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: std::copy_if(temp_results.begin(), temp_results.end(), std::back_inserter(ret_forks),
switch (initial_fxtype) { [](ParseFork elm)->bool {
case lib_syntax::ErrDeals::Surplus: return elm.occurs == ErrDeals::Absence || elm.occurs == ErrDeals::Surplus || elm.occurs == ErrDeals::Replace;
case lib_syntax::ErrDeals::Absence: });
case lib_syntax::ErrDeals::Replace:
// 修正匹配
if (ret_forks.size())
return ret_forks;
break; // 失败匹配
case lib_syntax::ErrDeals::None: return temp_results;
// min-match }
for (auto idx = 0; idx < min_match; ++idx) {
auto result_genx = rule_peer->parse(rt_inst, temp_head, initial_fxtype);
switch (std::get<0>(result_genx.result_straight)) { QList<ParseFork> Rept::parse(const ParseFork& context) const {
case MatchResult::Part: std::function<QList<ParseFork>(const ParseFork&, int)> min_match_calc =
if(fx_type == ErrDeals::None) [&](const ParseFork& context, int times_remains)->QList<ParseFork> {
return result_genx; QList<ParseFork> retvs;
initial_fxtype = fx_type; if (!times_remains)
temp_head = head; return retvs << context;
goto retry_entry;
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: default:
temp_head = std::get<1>(result_genx.result_straight); retvs << min_match_calc(it, times_remains - 1);
break; break;
} }
} }
// max-match return retvs;
for (auto idx = min_match; idx < max_match; ++idx) { };
if (!temp_head)
std::function<QList<ParseFork>(const ParseFork&, int)> max_match_calc =
[&](const ParseFork& context, int times_remains) -> QList<ParseFork> {
QList<ParseFork> 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; break;
auto result_genx = rule_peer->parse(rt_inst, temp_head, initial_fxtype); case ErrDeals::Surplus:
auto v_result = result_genx.result_straight; case ErrDeals::Absence:
if (std::get<0>(v_result) == MatchResult::None) { case ErrDeals::Replace:
v_result = result_genx.result_repair; if (context.occurs == ErrDeals::None)
} retvs << context;
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;
default: default:
temp_head = get<1>(v_result); retvs << max_match_calc(rst, times_remains - 1);
break; break;
} }
} }
break; return retvs;;
default: };
break;
}
if(straight_flags) auto temp_results = min_match_calc(context, min_match);
fnl_result.result_straight = make_tuple(MatchResult::Success, temp_head); auto rst_itor = std::find_if(temp_results.begin(), temp_results.end(), [](ParseFork e) -> bool {
else return QList<ErrDeals>{ ErrDeals::None, ErrDeals::Surplus, ErrDeals::Absence, ErrDeals::Replace }.contains(e.occurs);
fnl_result.result_repair = make_tuple(MatchResult::Success, temp_head); });
fx_type = initial_fxtype; if(rst_itor == temp_results.end())
return fnl_result; return temp_results;
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 QString Rept::token_present() const
@ -173,40 +191,35 @@ Seqs::Seqs(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
QList<shared_ptr<const IBasicRule>> Seqs::children() const { return mbrs_store; } QList<shared_ptr<const IBasicRule>> Seqs::children() const { return mbrs_store; }
ParseResult Seqs::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const { QList<ParseFork> Seqs::parse(const ParseFork& context) const {
ParseResult result_final; function<QList<ParseFork>(const ParseFork &, QList<shared_ptr<const IBasicRule>>::const_iterator)> match_seqs =
[&](const ParseFork& context, QList<shared_ptr<const IBasicRule>>::const_iterator rule_it) -> QList<ParseFork> {
QList<ParseFork> retvs;
auto temp_head = head; auto cendx = mbrs_store.cend();
bool straight_mark = fx_type == ErrDeals::None; if(rule_it == mbrs_store.cend())
for (auto& r : mbrs_store) { return retvs << context;
auto rule_present = r->token_present();
auto rst_gene = r->parse(rt_inst, temp_head, fx_type);
auto v_result = rst_gene.result_straight; auto rule_present = (*rule_it)->token_present();
if (std::get<0>(v_result) == MatchResult::None) auto result_forks = (*rule_it)->parse(context);
v_result = rst_gene.result_repair; for (auto fork : result_forks) {
switch (fork.occurs) {
case ErrDeals::Abort:
case ErrDeals::TerminalAOT:
retvs << fork;
break;
switch (get<0>(v_result)) { default:
case MatchResult::Part: retvs << match_seqs(fork, rule_it + 1);
if (straight_mark) break;
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;
} }
}
if (straight_mark) return retvs;
result_final.result_straight = make_tuple(MatchResult::Success, temp_head); };
else
result_final.result_repair = make_tuple(MatchResult::Success, temp_head); auto temp_results = match_seqs(context, mbrs_store.cbegin());
return result_final; return tidy_results(temp_results);
} }
QString Seqs::token_present() const QString Seqs::token_present() const
@ -217,93 +230,30 @@ QString Seqs::token_present() const
return content; return content;
} }
//tuple<MatchResult, uint, shared_ptr<const IBasicRule>, shared_ptr<const Token>>
Any::Any(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {} Any::Any(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
QList<shared_ptr<const IBasicRule>> Any::children() const { return mbrs_store; } QList<shared_ptr<const IBasicRule>> Any::children() const { return mbrs_store; }
ParseResult Any::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const { QList<ParseFork> Any::parse(const ParseFork& context) const {
auto rule_present = this->token_present(); auto rule_present = this->token_present();
QList<ParseFork> temp_results;
std::tuple<std::shared_ptr<const IBasicRule>, uint64_t> temp_result = std::make_tuple(nullptr, 0); for (auto& fork : mbrs_store) {
bool straight_mark = fx_type == auto result_forks = fork->parse(context);
for (auto rst_fork : result_forks) {
switch (rst_fork.occurs) {
case ErrDeals::None:
return QList<ParseFork>{ rst_fork };
switch (fx_type) { default:
case ErrDeals::None: { temp_results << rst_fork;
ParseResult result_final; break;
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;
}
} }
for (auto& itfx : QList<ErrDeals>{ 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;
} }
}
// 分析最匹配的分支 return tidy_results(temp_results);
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));
} }
QString Any::token_present() const QString Any::token_present() const
@ -339,45 +289,67 @@ QList<shared_ptr<const IBasicRule>> ExprRule::children() const {
} }
#include <ast_novel.h> #include <ast_novel.h>
tuple<MatchResult, shared_ptr<const IWordBase>> QList<ParseFork> ExprRule::parse(const ParseFork& context) const {
ExprRule::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const {
auto text_present = this->token_present(); auto text_present = this->token_present();
shared_ptr<IExprInst> elm_ast = this->newEmptyInstance();
rt_inst->pushExprRule(this->shared_from_this()); ParseFork elm_start;
rt_inst->pushExprInst(elm_ast); elm_start.next = context.next;
auto ret_tuple = child_store->parse(rt_inst, head, fx_type); QList<ParseFork> temp_returns;
switch (get<0>(ret_tuple)) { auto result_forks = child_store->parse(elm_start);
case MatchResult::Success: for (auto fork : result_forks) {
if (!dynamic_pointer_cast<example_novel::Document>(elm_ast) && fx_type == ErrDeals::None) { switch (fork.occurs) {
rt_inst->clearErrors(rt_inst->currentFile(), head->position()); case ErrDeals::None: {
ParseFork value(context);
shared_ptr<IExprInst> 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<ParseFork>{ value };
} }
rt_inst->popExprInst(); case ErrDeals::Surplus:
rt_inst->popExprRule(); case ErrDeals::Absence:
case ErrDeals::Replace: {
ParseFork value(context);
value.error_messages << fork.error_messages;
shared_ptr<IExprInst> 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()) { value.mbrs_list << elm_ast;
rt_inst->currentExprInst()->addChild(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 { QString ExprRule::token_present() const {
return child_store->token_present(); 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) {}

View File

@ -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<ast_basic::IExprInst> inst) = 0;
virtual QList<std::shared_ptr<const ast_basic::IExprInst>> getDocInsts() const = 0;
/**
* \brief .
*
* \return
*/
virtual std::shared_ptr<ast_basic::IExprInst> currentExprInst() const = 0;
virtual void pushExprInst(std::shared_ptr<ast_basic::IExprInst> current_inst) = 0;
virtual std::shared_ptr<ast_basic::IExprInst> popExprInst() = 0;
virtual std::shared_ptr<const IBasicRule> currentExprRule() const = 0;
virtual void pushExprRule(std::shared_ptr<const IBasicRule> inst) = 0;
virtual std::shared_ptr<const IBasicRule> popExprRule() = 0;
virtual QList<std::shared_ptr<const IBasicRule>> currentExprRuleStack() const = 0;
};
/**
* @brief
*/
enum class MatchResult {
None, // 不适用
Success, // 符合匹配条件
Part, // 部分匹配
};
/** /**
* @brief * @brief
*/ */
enum class ErrDeals { enum class ErrDeals {
None, // 不修复 None, // 无错误
Surplus, // 多一个词 Surplus, // 多一个词
Absence, // 少一个词 Absence, // 少一个词
Replace, // 错一个词 Replace, // 错一个词
Abort, // 中断解析过程
TerminalAOT, // 输入提前终止
}; };
/** /**
* . * @brief
*/ */
struct ParseResult { struct LIBSYNTAX_EXPORT ParseFork {
std::tuple<MatchResult, std::shared_ptr<const lib_token::IWordBase>> result_straight = std::make_tuple(MatchResult::None, nullptr); ErrDeals occurs = ErrDeals::None; // 解析过程中的错误
std::tuple<MatchResult, std::shared_ptr<const lib_token::IWordBase>> result_repair = std::make_tuple(MatchResult::None, nullptr); QList<QString> error_messages; // 累计错误信息
QList<std::shared_ptr<const ast_basic::IExprInst>> mbrs_list; // 成员存储
QList<std::shared_ptr<const lib_token::IToken>> tokens_list; // token列表
std::shared_ptr<const lib_token::IWordBase> next = nullptr; // 下一个解析词
ParseFork();
ParseFork(const ParseFork& other);
}; };
/** /**
@ -102,12 +69,10 @@ namespace lib_syntax {
/** /**
* @brief * @brief
* @param rt_inst * @param context
* @param head * @return <>
* @param fx_type
* @return <,>
*/ */
virtual ParseResult parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, ErrDeals& fx_type) const = 0; virtual QList<ParseFork> parse(const ParseFork& context) const = 0;
/** /**
* *
@ -131,7 +96,7 @@ namespace lib_syntax {
// IBasicRule interface // IBasicRule interface
public: public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override; virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual ParseResult parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, ErrDeals& fx_type) const override; virtual QList<ParseFork> parse(const ParseFork& context) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -142,15 +107,13 @@ namespace lib_syntax {
private: private:
QList<std::shared_ptr<const IBasicRule>> mbrs_store; QList<std::shared_ptr<const IBasicRule>> mbrs_store;
std::tuple<MatchResult, uint, std::shared_ptr<const IBasicRule>, std::shared_ptr<const lib_token::IWordBase>> rule_select(std::shared_ptr<const lib_token::IWordBase> head) const;
public: public:
Any(const QList<std::shared_ptr<const IBasicRule>> mbrs); Any(const QList<std::shared_ptr<const IBasicRule>> mbrs);
// IBasicRule interface // IBasicRule interface
public: public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override; virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual ParseResult parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, ErrDeals& fx_type) const override; virtual QList<ParseFork> parse(const ParseFork& context) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -167,7 +130,7 @@ namespace lib_syntax {
// IBasicRule interface // IBasicRule interface
public: public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override; virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual ParseResult parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, ErrDeals& fx_type) const override; virtual QList<ParseFork> parse(const ParseFork& context) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -185,7 +148,7 @@ namespace lib_syntax {
// IBasicRule interface // IBasicRule interface
public: public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override; virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual ParseResult parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, ErrDeals& fx_type) const override; virtual QList<ParseFork> parse(const ParseFork& context) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -193,7 +156,7 @@ namespace lib_syntax {
/** /**
* @brief * @brief
*/ */
class LIBSYNTAX_EXPORT ExprRule : public lib_syntax::IBasicRule, public std::enable_shared_from_this<ExprRule> { class LIBSYNTAX_EXPORT ExprRule : public IBasicRule, public std::enable_shared_from_this<ExprRule> {
public: public:
typedef QList<std::shared_ptr<const lib_token::IToken>> TokenSeqs; typedef QList<std::shared_ptr<const lib_token::IToken>> TokenSeqs;
ExprRule(const QString& rule_name, int expr_mark); ExprRule(const QString& rule_name, int expr_mark);
@ -207,12 +170,12 @@ namespace lib_syntax {
// IBasicRule interface // IBasicRule interface
public: public:
virtual QList<std::shared_ptr<const lib_syntax::IBasicRule>> children() const override; virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual ParseResult parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head, ErrDeals& fx_type) const override; virtual QList<ParseFork> parse(const ParseFork& context) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
protected: protected:
std::shared_ptr<const lib_syntax::IBasicRule> child_store; std::shared_ptr<const IBasicRule> child_store;
private: private:
QString name_store; QString name_store;

View File

@ -119,7 +119,7 @@ void NovalSyntax::node_register(std::shared_ptr<const ast_gen::SyntaxElement> ro
if (!child->isAnonymous()) { if (!child->isAnonymous()) {
auto check_result = ast_gen::GlobalElement::UniquePtr->appendToCache(child); auto check_result = ast_gen::GlobalElement::UniquePtr->appendToCache(child);
if (check_result) if (check_result)
throw new lib_syntax::SyntaxException(QString(u8"SyntaxError[0x0004]系统中包含同类型重名命名节点:%1<type%2>(%3,%4)") throw new SyntaxException(QString(u8"SyntaxError[0x0004]系统中包含同类型重名命名节点:%1<type%2>(%3,%4)")
.arg(child->signature()).arg(child->typeMark()).arg(child->path()).arg(check_result->path())); .arg(child->signature()).arg(child->typeMark()).arg(child->path()).arg(check_result->path()));
} }