WsParser_VS/libSyntax/libsyntax.cpp

373 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "libsyntax.h"
#include "ast_basic.h"
#include <QDebug>
using namespace lib_syntax;
using namespace std;
using namespace lib_token;
using namespace ast_basic;
TokenMatch::TokenMatch(shared_ptr<const ITokenDefine> define) : define_peer(define) {}
QList<shared_ptr<const IBasicRule>> TokenMatch::children() const { return QList<shared_ptr<const IBasicRule>>(); }
QList<ParseFork> TokenMatch::parse(const ParseFork& context) const
{
auto head = context.next;
if (!head) {
ParseFork result(context);
result.error_messages << u8"输入流提前终止";
result.next = nullptr;
result.occurs = ErrDeals::TerminalAOT;
return QList<ParseFork>{result};
}
if (head->content() == u8"SDK反拉扥") {
qDebug() << true;
}
QList<ParseFork> result_list;
auto match_result = define_peer->analysis(head);
if (get<0>(match_result)) {
ParseFork success_fork(context);
success_fork.tokens_list << get<0>(match_result);
if (get<1>(match_result)) {
success_fork.next = make_shared<WordImpl>(get<1>(match_result), head->nextWord());
}
else {
success_fork.next = head->nextWord();
}
result_list << success_fork;
}
else {
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;
return result_list << fail_fork;
}
// 缺一个
ParseFork absence_fork(context);
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;
result_list << absence_fork;
// 错一个
ParseFork replace_fork(context);
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;
result_list << replace_fork;
// 多一个
auto temp_head = head->nextWord();
if(temp_head){
auto match_result = define_peer->analysis(temp_head);
if (get<0>(match_result)) {
ParseFork surplus_fork(context);
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);
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();
result_list << surplus_fork;
}
}
}
return result_list;
}
QString TokenMatch::token_present() const {
return QString(u8"%1").arg(this->define_peer->reviseWords());
}
Rept::Rept(shared_ptr<const IBasicRule> rule, int min, int max) : rule_peer(rule), min_match(min), max_match(max) {}
QList<shared_ptr<const IBasicRule>> Rept::children() const { return QList<shared_ptr<const IBasicRule>>() << rule_peer; }
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;
});
// 成功匹配
if (ret_forks.size())
return ret_forks;
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;
// 失败匹配
return temp_results;
}
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;
if (!times_remains)
return retvs << context;
auto result_present = rule_peer->token_present();
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:
retvs << min_match_calc(it, times_remains - 1);
break;
}
}
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_present = rule_peer->token_present();
auto result_forks = rule_peer->parse(context);
for (auto rst : result_forks) {
switch (rst.occurs) {
case ErrDeals::Abort:
case ErrDeals::TerminalAOT:
retvs << context;
break;
case ErrDeals::Surplus:
case ErrDeals::Absence:
case ErrDeals::Replace:
if (context.occurs == ErrDeals::None)
retvs << context;
default:
retvs << max_match_calc(rst, times_remains - 1);
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 (rst_itor == temp_results.end())
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
{
if (min_match == 0 && max_match == INT_MAX)
return u8"(" + this->rule_peer->token_present() + QString(u8")*");
if (min_match == 1 && max_match == INT_MAX)
return u8"(" + this->rule_peer->token_present() + QString(u8")+");
return u8"(" + this->rule_peer->token_present() + QString(u8"){%1, %2}").arg(min_match).arg(max_match);
}
Seqs::Seqs(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
QList<shared_ptr<const IBasicRule>> Seqs::children() const { return mbrs_store; }
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 cendx = mbrs_store.cend();
if (rule_it == mbrs_store.cend())
return retvs << context;
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;
default:
retvs << match_seqs(fork, rule_it + 1);
break;
}
}
return retvs;
};
auto temp_results = match_seqs(context, mbrs_store.cbegin());
return tidy_results(temp_results);
}
QString Seqs::token_present() const
{
QString content;
for (auto& it : children())
content += it->token_present() + u8" ";
return content.mid(0, content.size() -1);
}
Any::Any(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
QList<shared_ptr<const IBasicRule>> Any::children() const { return mbrs_store; }
QList<ParseFork> Any::parse(const ParseFork& context) const {
auto rule_present = this->token_present();
QList<ParseFork> temp_results;
for (auto& fork : mbrs_store) {
auto fork_present = fork->token_present();
auto result_forks = fork->parse(context);
for (auto rst_fork : result_forks) {
switch (rst_fork.occurs) {
case ErrDeals::None:
return QList<ParseFork>{ rst_fork };
default:
temp_results << rst_fork;
break;
}
}
}
return tidy_results(temp_results);
}
QString Any::token_present() const
{
QString members_content;
for (auto& it : children()) {
members_content += it->token_present() + u8"|";
}
return members_content.mid(0, members_content.size() - 1);
}
SyntaxException::SyntaxException(const QString& message) { this->msg_store = message; }
QString SyntaxException::message() const { return msg_store; }
ExprRule::ExprRule(const QString& rule_name, int expr_mark) : name_store(rule_name) {
this->mark_store = expr_mark;
}
shared_ptr<const ExprRule> ExprRule::reloadRule(shared_ptr<const IBasicRule> rule) {
auto ninst = makeCopy();
ninst->child_store = rule;
return ninst;
}
QString ExprRule::name() const { return name_store; }
int ExprRule::typeMark() const { return this->mark_store; }
QList<shared_ptr<const IBasicRule>> ExprRule::children() const {
return QList<shared_ptr<const IBasicRule>>() << this->child_store;
}
#include <ast_novel.h>
QList<ParseFork> ExprRule::parse(const ParseFork& context) const {
auto text_present = this->token_present();
ParseFork elm_start;
elm_start.next = context.next;
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 };
}
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);
value.mbrs_list << elm_ast;
value.next = fork.next;
temp_returns << value;
} break;
default:
break;
}
}
// 修正后的完整匹配结果
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), next(other.next) {}