添加改进措施
This commit is contained in:
parent
26eab5a092
commit
0df0e77df5
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue