添加改进措施

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()) {
try {
auto parser = std::make_shared<NovelParser>();
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<std::shared_ptr<const ast_basic::IExprInst>> 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) {

View File

@ -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<lib_syntax::IContext> NovelParser::parserContext() const
std::shared_ptr<ast_gen::GlobalElement> NovelParser::parserContext() const
{
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"小说");
auto word_reader = std::make_shared<lib_token::WordReader>();
QList<ParseFork> 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<std::shared_ptr<const ast_basic::IExprInst>> 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<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;
virtual QString version() const;
std::shared_ptr<lib_syntax::IContext> parserContext() const;
QList<std::shared_ptr<const ast_basic::IExprInst>> parse(const QFileInfoList souurce_list) const;
std::shared_ptr<ast_gen::GlobalElement> parserContext() 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;
};

View File

@ -33,78 +33,3 @@ void ExpressionElement::addChild(std::shared_ptr<const IExprInst> inst) {
QList<std::shared_ptr<const IToken>> 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<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;
};
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 ¸ùÔªËØ¨Òå
*/
class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement, public ast_basic::ExpressionContext {
class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement {
private:
QString names_store;
QHash<QString, std::shared_ptr<const SyntaxElement>> node_cache;

View File

@ -168,7 +168,7 @@ namespace example_novel
}
namespace lib_syntax {
template<> class ElementRule<example_novel::TextSection> : public ExprRule {
template<> class ElementRule<example_novel::TextSection> : public lib_syntax::ExprRule {
public:
ElementRule<example_novel::TextSection>(const QString& rule_name, int expr_mark)
:ExprRule(rule_name, expr_mark) {}
@ -179,64 +179,43 @@ namespace lib_syntax {
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());
}
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>>
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();
virtual QList<ParseFork> 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<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--);
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<ParseFork>{ rst };
}break;
default:
break;
}
}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>>(); }
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) {
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<ParseFork>{result};
}
ParseResult result_ret;
QList<ParseFork> 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<WordImpl>(get<1>(match_result), head->nextWord()));
success_fork.next = make_shared<WordImpl>(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<row:%3,col:%4>“%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'<row:%2,col:%3>)。")
.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<row:%2,col:%3>,应为“%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'<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;
{
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<row:%2,col:%3>,内容为“%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'<row:%2,col:%3>,应该为'%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<WordImpl>(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'<row:%2,col:%3>)。")
.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<WordImpl>(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<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; }
ParseResult Rept::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const {
ParseResult fnl_result;
QList<ParseFork> tidy_results(QList<ParseFork> temp_results) {
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:
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<ParseFork> Rept::parse(const ParseFork& context) const {
std::function<QList<ParseFork>(const ParseFork&, int)> min_match_calc =
[&](const ParseFork& context, int times_remains)->QList<ParseFork> {
QList<ParseFork> 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<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;
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>{ 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<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
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 {
ParseResult result_final;
QList<ParseFork> Seqs::parse(const ParseFork& context) const {
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;
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<MatchResult, uint, shared_ptr<const IBasicRule>, shared_ptr<const Token>>
Any::Any(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
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();
QList<ParseFork> temp_results;
std::tuple<std::shared_ptr<const IBasicRule>, 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<ParseFork>{ 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>{ 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<shared_ptr<const IBasicRule>> ExprRule::children() const {
}
#include <ast_novel.h>
tuple<MatchResult, shared_ptr<const IWordBase>>
ExprRule::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrDeals& fx_type) const {
QList<ParseFork> ExprRule::parse(const ParseFork& context) const {
auto text_present = this->token_present();
shared_ptr<IExprInst> 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<example_novel::Document>(elm_ast) && fx_type == ErrDeals::None) {
rt_inst->clearErrors(rt_inst->currentFile(), head->position());
QList<ParseFork> 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<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();
rt_inst->popExprRule();
case ErrDeals::Surplus:
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()) {
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) {}

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
*/
enum class ErrDeals {
None, // 不修复
Surplus, // 多一个词
Absence, // 少一个词
Replace, // 错一个词
None, // 无错误
Surplus, // 多一个词
Absence, // 少一个词
Replace, // 错一个词
Abort, // 中断解析过程
TerminalAOT, // 输入提前终止
};
/**
* .
*/
struct ParseResult {
std::tuple<MatchResult, std::shared_ptr<const lib_token::IWordBase>> result_straight = std::make_tuple(MatchResult::None, nullptr);
std::tuple<MatchResult, std::shared_ptr<const lib_token::IWordBase>> result_repair = std::make_tuple(MatchResult::None, nullptr);
* @brief
*/
struct LIBSYNTAX_EXPORT ParseFork {
ErrDeals occurs = ErrDeals::None; // 解析过程中的错误
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
* @param rt_inst
* @param head
* @param fx_type
* @return <,>
* @param context
* @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
public:
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;
};
@ -142,15 +107,13 @@ namespace lib_syntax {
private:
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:
Any(const QList<std::shared_ptr<const IBasicRule>> mbrs);
// IBasicRule interface
public:
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;
};
@ -167,7 +130,7 @@ namespace lib_syntax {
// IBasicRule interface
public:
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;
};
@ -185,7 +148,7 @@ namespace lib_syntax {
// IBasicRule interface
public:
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;
};
@ -193,7 +156,7 @@ namespace lib_syntax {
/**
* @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:
typedef QList<std::shared_ptr<const lib_token::IToken>> TokenSeqs;
ExprRule(const QString& rule_name, int expr_mark);
@ -207,12 +170,12 @@ namespace lib_syntax {
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const lib_syntax::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<std::shared_ptr<const IBasicRule>> children() const override;
virtual QList<ParseFork> parse(const ParseFork& context) const override;
virtual QString token_present() const override;
protected:
std::shared_ptr<const lib_syntax::IBasicRule> child_store;
std::shared_ptr<const IBasicRule> child_store;
private:
QString name_store;

View File

@ -119,7 +119,7 @@ void NovalSyntax::node_register(std::shared_ptr<const ast_gen::SyntaxElement> 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<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()));
}