WsParser_VS/libSyntax/libsyntax.cpp

368 lines
11 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 <tuple>
#include <QDebug>
using namespace lib_syntax;
using namespace std;
using namespace lib_token;
using namespace lib_words;
using namespace ast_basic;
Any::Any(const QList<std::shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) { }
QList<std::shared_ptr<const IBasicRule>> Any::children() const {
return mbrs_store;
}
QList<std::shared_ptr<const MatchCursor>> Any::parse(std::shared_ptr<const MatchCursor> cursor) const {
if (cursor->mustStop())
return QList<std::shared_ptr<const MatchCursor>>() << cursor;
QList<std::shared_ptr<const MatchCursor>> result_list;
for (auto rx : this->children())
result_list.append(rx->parse(cursor));
return result_list;
}
QString Any::present() const {
QString members_content;
for (auto& it : children()) {
members_content += it->present() + u8"|";
}
return members_content.mid(0, members_content.size() - 1);
}
QList<QString> lib_syntax::Any::invokeSegments(const QString& in_cursor_name, const QString& out_list_name) const {
QList<QString> lines;
lines << QString(u8"if (%1->mustStop())").arg(in_cursor_name);
lines << QString(u8" return QList<std::shared_ptr<const MatchCursor>>() << %1; ").arg(in_cursor_name);
lines << QString(u8"QList<std::shared_ptr<const MatchCursor>> result_list_%1;").arg((uint64_t) this);
for (auto rule : children()) {
auto segments = rule->invokeSegments(in_cursor_name, QString(u8"result_list_%1").arg((uint64_t) this));
if (segments.size() == 1) {
lines.append(segments);
}
else {
lines << u8"{";
lines.append(segments);
lines << u8"}";
}
}
lines << QString(u8"%2 = result_list_%1;").arg((uint64_t) this).arg(out_list_name);
}
QString lib_syntax::Any::implementSegments(const QString& in_cursor_name, QList<QString>& lines) const {
return QString();
}
Seqs::Seqs(const QList<std::shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) { }
QList<std::shared_ptr<const IBasicRule>> Seqs::children() const {
return mbrs_store;
}
QList<std::shared_ptr<const MatchCursor>> Seqs::parse(std::shared_ptr<const MatchCursor> cursor) const {
if (cursor->mustStop())
return QList<std::shared_ptr<const MatchCursor>>() << cursor;
QList<std::shared_ptr<const MatchCursor>> results;
QList<std::shared_ptr<const MatchCursor>> bridge_list{ cursor };
for (auto rule : this->children()) {
QList<std::shared_ptr<const MatchCursor>> current_result;
std::for_each(bridge_list.begin(), bridge_list.end(),
[&](std::shared_ptr<const MatchCursor> vcurs) {
if (vcurs->mustStop())
results.push_back(vcurs);
else {
current_result.append(rule->parse(vcurs));
}
});
bridge_list = current_result;
}
results.append(bridge_list);
return results;
}
QString Seqs::present() const {
QString content;
for (auto& it : children())
content += it->present() + " ";
return content.mid(0, content.size() - 1);
}
QList<QString> lib_syntax::Seqs::invokeSegments(const QString& in_cursor_name, const QString& out_list_name) const {
QList<QString> lines;
lines << QString(u8"if (%1->mustStop())").arg(in_cursor_name);
lines << QString(u8" return QList<std::shared_ptr<const MatchCursor>>() << %1; ").arg(in_cursor_name);
int times = 0;
lines << QString(u8"QList<std::shared_ptr<const MatchCursor>> bridge_list{ %1 };").arg(in_cursor_name);
for (auto rule : children()) {
auto segments = rule->invokeSegments(in_cursor_name, QString(u8"result_list_%1").arg((uint64_t) this));
if (segments.size() == 1) {
lines.append(segments);
}
else {
lines << u8"{";
lines.append(segments);
lines << u8"}";
}
}
lines << QString(u8"%2 = result_list_%1;").arg((uint64_t) this).arg(out_list_name);
}
Rept::Rept(std::shared_ptr<const IBasicRule> rule, int min, int max)
: rule_peer(rule), min_match(min), max_match(max) { }
QList<std::shared_ptr<const IBasicRule>> Rept::children() const {
return QList<std::shared_ptr<const IBasicRule>>() << rule_peer;
}
QList<std::shared_ptr<const MatchCursor>> Rept::parse(std::shared_ptr<const MatchCursor> cursor) const {
if (cursor->mustStop())
return QList<std::shared_ptr<const MatchCursor>>() << cursor;
QList<std::shared_ptr<const MatchCursor>> results;
QList<std::shared_ptr<const MatchCursor>> bridge_list{ cursor };
// <20><>С<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
for (auto idx = 0; idx < min_match; ++idx) {
QList<std::shared_ptr<const MatchCursor>> current_list;
// <20><><EFBFBD><EFBFBD>ÿһ<C3BF>ο<EFBFBD><CEBF><EFBFBD>ƥ<EFBFBD><C6A5>
std::for_each(bridge_list.begin(), bridge_list.end(),
[&](std::shared_ptr<const MatchCursor> curs) {
if (curs->mustStop())
results.push_back(curs);
else {
current_list.append(this->rule_peer->parse(curs));
}
});
bridge_list = current_list;
}
// <20>鲢ʧ<E9B2A2>ܷ<EFBFBD>֧
std::copy_if(bridge_list.begin(), bridge_list.end(), std::back_inserter(results),
[&](std::shared_ptr<const MatchCursor> ins) { return ins->mustStop(); });
// <20><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>ʧ<EFBFBD>ܷ<EFBFBD>֧
for (auto idx = 0; idx < bridge_list.size(); ++idx)
if (bridge_list.at(idx)->mustStop())
bridge_list.removeAt(idx--);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сƥ<D0A1><C6A5>
if (!bridge_list.size())
return results;
// <20><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (auto idx = min_match; idx < max_match; ++idx) {
QList<std::shared_ptr<const MatchCursor>> current_list;
// ƥ<><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>
std::for_each(bridge_list.begin(), bridge_list.end(),
[&](std::shared_ptr<const MatchCursor> ins) {
current_list.append(this->rule_peer->parse(ins));
});
// <20>Ƴ<EFBFBD>ʧ<EFBFBD>ܷ<EFBFBD>֧
for (auto idx = 0; idx < current_list.size(); ++idx) {
auto rst_branch = current_list.at(idx);
if (rst_branch->mustStop() && rst_branch->currentWords()) {
results.append(rst_branch->previous());
current_list.removeAt(idx--);
}
if (rst_branch->mustStop() && !rst_branch->currentWords()) {
results.append(rst_branch);
current_list.removeAt(idx--);
}
}
if (!current_list.size())
break;
bridge_list = current_list;
}
results.append(bridge_list);
return results;
}
QString Rept::present() const {
if (min_match == 0 && max_match == INT_MAX)
return u8"(" + this->rule_peer->present() + QString(u8")*");
else if (min_match == 1 && max_match == INT_MAX)
return u8"(" + this->rule_peer->present() + QString(u8")+");
else if (min_match == 0 && max_match == 1)
return u8"(" + this->rule_peer->present() + QString(u8")?");
return u8"(" + this->rule_peer->present() + QString(u8"){%1, %2}").arg(min_match).arg(max_match);
}
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), mark_store(expr_mark) { }
std::shared_ptr<const ExprRule> ExprRule::reloadRule(std::shared_ptr<const IBasicRule> rule) const {
auto ninst = this->make_copy();
ninst->child_store = rule;
return ninst;
}
QString ExprRule::name() const {
return name_store;
}
int ExprRule::typeMark() const {
return this->mark_store;
}
QList<std::shared_ptr<const IBasicRule>> ExprRule::children() const {
return QList<std::shared_ptr<const IBasicRule>>() << this->child_store;
}
#include <ast_novel.h>
QString ExprRule::present() const {
return child_store->present();
}
QList<QString> lib_syntax::ExprRule::invokeSegments(const QString& in_cursor_name, const QString& out_list_name) const {
return QList<QString>() << QString(u8"%1=exprs_%2(%3); //%4")
.arg(out_list_name).arg((uint64_t) this).arg(in_cursor_name).arg(name());
}
QString lib_syntax::ExprRule::implementSegments(const QString& in_cursor_name, QList<QString>& lines) const {
lines << u8"if (" + in_cursor_name + "->mustStop())";
lines << u8" return QList<std::shared_ptr<const MatchCursor>>() << " + in_cursor_name + ";";
lines << u8"auto t_this = " + in_cursor_name + "->currentToken();";
lines << u8"auto w_this = " + in_cursor_name + "->currentWords();";
lines << u8"auto split_begin = std::make_shared<lib_token::ExprBeginToken<ExprType>>(shared_from_this(), t_this);";
lines << u8"auto ncursor = std::make_shared<MatchCursor>(" + in_cursor_name + ");";
lines << u8"ncursor->setCurrent(split_begin, w_this);";
lines << u8"ncursor->enterExprs();";
lines << u8"auto nbranch = this->child_store->parse(ncursor);";
lines << u8"decltype(nbranch) list_ok;";
lines << u8"// ѡ<><D1A1><EFBFBD><EFBFBD>ȫƥ<C8AB><C6A5><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD>";
lines << u8"std::copy_if(nbranch.begin(), nbranch.end(), std::back_inserter(list_ok),"
"[](std::shared_ptr<const MatchCursor> ins) { return !ins->exprsErrorCount(); });";
lines << u8"if (!list_ok.size()) {";
lines << u8" // ѡ<><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
lines << u8" std::copy_if(nbranch.begin(), nbranch.end(), std::back_inserter(list_ok),"
"[](std::shared_ptr<const MatchCursor> ins) { return !ins->mustStop(); });";
lines << u8" // ƥ<><C6A5>ʧ<EFBFBD>ܵ<EFBFBD>";
lines << u8" if (!list_ok.size())";
lines << u8" list_ok = nbranch;";
lines << u8"}";
lines << u8"decltype(list_ok) branch_procs;";
lines << u8"std::for_each(list_ok.begin(), list_ok.end(), [&](std::shared_ptr<const MatchCursor> curs) {";
lines << u8" if (curs->mustStop()) {";
lines << u8" branch_procs.append(curs);";
lines << u8" }";
lines << u8" else {";
lines << u8" auto t_end = curs->currentToken();";
lines << u8" auto w_end = curs->currentWords();";
lines << u8" auto ecursor = std::make_shared<MatchCursor>(curs);";
lines << u8" ecursor->quitExprs();";
lines << u8" auto split_end = std::make_shared<lib_token::ExprEndToken<ExprType>>(split_begin, t_end);";
lines << u8" ecursor->setCurrent(split_end, w_end);";
lines << u8" branch_procs.append(ecursor);";
lines << u8" }";
lines << u8"});";
lines << u8"return branch_procs;";
return QString(u8"exprs_%1").arg((uint64_t) this);
}
MatchCursor::MatchCursor(const QString& path) :_file_path(path) { }
MatchCursor::MatchCursor(std::shared_ptr<const MatchCursor> other_ptr)
: _prev_cursor(other_ptr),
_file_path(other_ptr->_file_path),
_total_errors(other_ptr->_total_errors),
_exprs_errors(other_ptr->_exprs_errors),
_current_token(other_ptr->_current_token),
_remains_word(other_ptr->_remains_word) { }
std::shared_ptr<const MatchCursor> MatchCursor::previous() const {
return _prev_cursor;
}
QString MatchCursor::filePath() const {
return _file_path;
}
void MatchCursor::enterExprs() {
auto new_expr = std::make_shared<ErrsPack>();
this->_exprs_errors.push_back(new_expr);
}
void MatchCursor::logExprsError(const QString& msg) {
this->_total_errors.push_back(msg);
this->_exprs_errors.last()->addError(msg);
}
void MatchCursor::quitExprs() {
this->_exprs_errors.pop_back();
}
bool MatchCursor::mustStop() const {
return exprsErrorCount() >= 2 || parse_stop();
}
int MatchCursor::exprsErrorCount() const {
if (this->_exprs_errors.size())
return this->_exprs_errors.last()->errorCount();
return 0;
}
int MatchCursor::totalErrorCount() const {
return this->_total_errors.size();
}
QList<QString> MatchCursor::totalErrors() const {
return this->_total_errors;
}
void MatchCursor::setCurrent(std::shared_ptr<const IActionToken> t, std::shared_ptr<const IPrimitiveWord> remains) {
this->_current_token = t;
this->_remains_word = remains;
}
std::shared_ptr<const IActionToken> MatchCursor::currentToken() const {
return this->_current_token;
}
std::shared_ptr<const IPrimitiveWord> MatchCursor::currentWords() const {
return this->_remains_word;
}
bool lib_syntax::MatchCursor::parse_stop() const {
return !currentWords();
}
void MatchCursor::ErrsPack::addError(const QString& msg) {
this->_error_collection.append(msg);
}
QList<QString> MatchCursor::ErrsPack::errors() const {
return _error_collection;
}
uint64_t MatchCursor::ErrsPack::errorCount() const {
return _error_collection.size();
}