WsParser_VS/libSyntax/libsyntax.cpp

296 lines
9.6 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>>(); }
tuple<IBasicRule::MatchResult, shared_ptr<const IWordBase>>
TokenMatch::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, ErrOccurs& fx_type) const
{
if (!head) {
rt_inst->appendParseError(rt_inst->currentFile(), -1, QString(u8"Syntax[0x0000]token流%1提前终止").arg(rt_inst->currentFile()));
return make_tuple(IBasicRule::MatchResult::Fail, head);
}
auto match_result = define_peer->analysis(head);
if (get<0>(match_result)) {
rt_inst->currentExprInst()->addToken(get<0>(match_result));
if (get<1>(match_result)) {
return make_tuple(IBasicRule::MatchResult::Success, make_shared<WordImpl>(get<1>(match_result), head->nextWord()));
}
else {
return make_tuple(IBasicRule::MatchResult::Success, head->nextWord());
}
}
else {
switch (fx_type) {
case lib_syntax::IBasicRule::ErrOccurs::None:
return make_tuple(IBasicRule::MatchResult::Part, head);
case lib_syntax::IBasicRule::ErrOccurs::Replace:
fx_type = IBasicRule::ErrOccurs::None;
rt_inst->appendParseError(rt_inst->currentFile(), head->position(),
QString(u8"Syntax[0x00001]语法匹配错误不能识别token\"%1\"<row:%2,col:%3>(应该为:%4)")
.arg(head->content()).arg(head->row()).arg(head->column()).arg(this->define_peer->reviseWords()));
return make_tuple(IBasicRule::MatchResult::Success, head->nextWord());
case lib_syntax::IBasicRule::ErrOccurs::Absence:
fx_type = IBasicRule::ErrOccurs::None;
rt_inst->appendParseError(rt_inst->currentFile(), head->position(),
QString(u8"Syntax[0x00001]语法匹配错误缺少token\"%1\"<row: % 2, col : % 3>")
.arg(this->define_peer->reviseWords()).arg(head->row()).arg(head->column()));
return make_tuple(IBasicRule::MatchResult::Success, head);
case lib_syntax::IBasicRule::ErrOccurs::Surplus:
fx_type = IBasicRule::ErrOccurs::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"Syntax[0x00001]语法匹配错误多余token\"%1\"<row: % 2, col : % 3>")
.arg(head->content()).arg(head->row()).arg(head->column()));
rt_inst->currentExprInst()->addToken(get<0>(match_result));
if (get<1>(match_result)) {
return make_tuple(IBasicRule::MatchResult::Success, make_shared<WordImpl>(get<1>(match_result), temp_head->nextWord()));
}
else {
return make_tuple(IBasicRule::MatchResult::Success, temp_head->nextWord());
}
}
else {
return make_tuple(IBasicRule::MatchResult::Part, head);
}
}
break;
default:
break;
}
}
}
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; }
tuple<IBasicRule::MatchResult, shared_ptr<const IWordBase>>
Rept::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, IBasicRule::ErrOccurs& fx_type) const {
auto temp_head = head;
// min-match
for (auto idx = 0; idx < min_match; ++idx) {
auto result_gen = rule_peer->parse(rt_inst, temp_head, fx_type);
switch (get<0>(result_gen)) {
case IBasicRule::MatchResult::Fail:
return make_tuple(IBasicRule::MatchResult::Part, temp_head);
case IBasicRule::MatchResult::Part:
return make_tuple(IBasicRule::MatchResult::Part, get<1>(result_gen));
default:
temp_head = get<1>(result_gen);
break;
}
}
// max-match
for (auto idx = min_match; idx < max_match; ++idx) {
if (!temp_head)
break;
auto result_gen = rule_peer->parse(rt_inst, temp_head, fx_type);
switch (get<0>(result_gen)) {
case IBasicRule::MatchResult::Fail:
case IBasicRule::MatchResult::Part:
return make_tuple(IBasicRule::MatchResult::Success, temp_head);
default:
temp_head = get<1>(result_gen);
break;
}
}
return make_tuple(IBasicRule::MatchResult::Success, temp_head);
}
QString Rept::token_present() const
{
return u8"(" + this->rule_peer->token_present() + QString(u8"{%1, %2}").arg(min_match).arg(max_match) + u8")";
}
Seqs::Seqs(const QList<shared_ptr<const IBasicRule>> mbrs) : mbrs_store(mbrs) {}
QList<shared_ptr<const IBasicRule>> Seqs::children() const { return mbrs_store; }
tuple<IBasicRule::MatchResult, shared_ptr<const IWordBase>>
Seqs::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, IBasicRule::ErrOccurs& fx_type) const {
auto temp_head = head;
for (auto& r : mbrs_store) {
auto rst_gene = r->parse(rt_inst, temp_head, fx_type);
switch (get<0>(rst_gene)) {
case IBasicRule::MatchResult::Fail:
return make_tuple(IBasicRule::MatchResult::Part, temp_head);
case IBasicRule::MatchResult::Part:
return rst_gene;
case IBasicRule::MatchResult::Success:
temp_head = get<1>(rst_gene);
break;
default:
break;
}
}
return make_tuple(IBasicRule::MatchResult::Success, temp_head);
}
QString Seqs::token_present() const
{
QString content;
for (auto& it : children())
content += it->token_present();
return QString(u8"(%1)").arg(content);
}
//tuple<IBasicRule::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; }
class words_span {
public:
int row_span, column_span;
words_span(int rspan, int cspan) :row_span(rspan), column_span(cspan) {}
bool operator>(const words_span& other) {
if (row_span > other.row_span)
return true;
if (row_span == other.row_span)
return column_span > other.column_span;
return false;
}
};
tuple<IBasicRule::MatchResult, shared_ptr<const IWordBase>>
Any::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, IBasicRule::ErrOccurs& fx_type) const {
tuple<shared_ptr<const IBasicRule>, uint64_t> temp_result = make_tuple(nullptr, 0);
auto rule_present = this->token_present();
for (auto& fork : mbrs_store) {
auto gen = fork->parse(rt_inst, head, fx_type);
switch (get<0>(gen)) {
// 遇到成功的直接返回解析结果
case IBasicRule::MatchResult::Success:
return gen;
case IBasicRule::MatchResult::Fail: {
if (!get<0>(temp_result))
temp_result = make_tuple(fork, 0);
}break;
case IBasicRule::MatchResult::Part: {
auto span = get<1>(gen)->position() - head->position();
if (span >= get<1>(temp_result))
temp_result = make_tuple(fork, span);
}
default:
break;
}
}
// 分析最匹配的分支
rt_inst->clearErrors(rt_inst->currentFile(), head->position());
auto temp = get<0>(temp_result)->parse(rt_inst, head, fx_type);
return make_tuple(IBasicRule::MatchResult::Part, get<1>(temp));
}
QString Any::token_present() const
{
QString members_content;
for (auto& it : children()) {
members_content += it->token_present() + u8"|";
}
return u8"(" + members_content.mid(0, members_content.size() - 1) + u8")";
}
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>
tuple<IBasicRule::MatchResult, shared_ptr<const IWordBase>>
ExprRule::parse(shared_ptr<IContext> rt_inst, shared_ptr<const IWordBase> head, IBasicRule::ErrOccurs& fx_type) const {
QList<IBasicRule::ErrOccurs> opts_list = {
IBasicRule::ErrOccurs::None, IBasicRule::ErrOccurs::Surplus, IBasicRule::ErrOccurs::Absence, IBasicRule::ErrOccurs::Replace };
auto opt_current_itor = opts_list.cbegin();
tuple<IBasicRule::MatchResult, shared_ptr<const IWordBase>> ret_tuple;
do {
auto opt_val = *opt_current_itor;
shared_ptr<IExprInst> elm_ast = this->newEmptyInstance();
auto text_present = this->token_present();
rt_inst->pushExprRule(this->shared_from_this());
rt_inst->pushExprInst(elm_ast);
ret_tuple = child_store->parse(rt_inst, head, opt_val);
auto tokens_decl = elm_ast->tokens();
switch (get<0>(ret_tuple)) {
case IBasicRule::MatchResult::Fail:
case IBasicRule::MatchResult::Part:
rt_inst->popExprInst();
rt_inst->popExprRule();
break;
case IBasicRule::MatchResult::Success: {
if (!dynamic_pointer_cast<example_novel::Document>(elm_ast) && opt_val == IBasicRule::ErrOccurs::None) {
auto start_pos = head->position();
rt_inst->clearErrors(rt_inst->currentFile(), start_pos);
}
rt_inst->popExprInst();
rt_inst->popExprRule();
if (rt_inst->currentExprInst()) {
rt_inst->currentExprInst()->addChild(elm_ast);
}
else {
rt_inst->appendDocInst(elm_ast);
}
}break;
default:
break;
}
opt_current_itor++;
} while (fx_type != IBasicRule::ErrOccurs::None && opt_current_itor != opts_list.cend());
return ret_tuple;
}
QString ExprRule::token_present() const {
return child_store->token_present();
}