WsParser_VS/libSyntax/libsyntax.cpp

242 lines
7.7 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<std::shared_ptr<const BaseRule>> TokenMatch::children() const { return QList<std::shared_ptr<const BaseRule>>(); }
std::tuple<BaseRule::MatchResult, std::shared_ptr<const IWordBase>> TokenMatch::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
if (!head) {
rt_inst->appendParseErrors(-1, QString(u8"Syntax[0x0000]token流%1提前终止").arg(rt_inst->currentFile()));
return std::make_tuple(BaseRule::MatchResult::Fail, head);
}
auto match_result = define_peer->analysis(head);
if (std::get<0>(match_result)) {
rt_inst->currentInst()->addToken(std::get<0>(match_result));
}
else {
rt_inst->appendParseErrors(head->position(),
QString(u8"Syntax[0x00001]语法匹配错误不能识别token%1<%2,%3>(%4)")
.arg(head->content()).arg(head->row()).arg(head->column()).arg(head->file()));
return std::make_tuple(BaseRule::MatchResult::Part, head);
}
if (std::get<1>(match_result)) {
return std::make_tuple(BaseRule::MatchResult::Success, std::make_shared<WordImpl>(std::get<1>(match_result), head->nextWord()));
}
else {
return std::make_tuple(BaseRule::MatchResult::Success, head->nextWord());
}
}
QString TokenMatch::token_present() const {
return QString(u8"<%1>").arg(this->define_peer->typeName());
}
Rept::Rept(std::shared_ptr<const BaseRule> rule, int min, int max) : rule_peer(rule), min_match(min), max_match(max) {}
QList<std::shared_ptr<const BaseRule>> Rept::children() const { return QList<std::shared_ptr<const BaseRule>>() << rule_peer; }
std::tuple<BaseRule::MatchResult, std::shared_ptr<const IWordBase>> Rept::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) 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);
switch (std::get<0>(result_gen)) {
case BaseRule::MatchResult::Fail:
return std::make_tuple(BaseRule::MatchResult::Part, temp_head);
case BaseRule::MatchResult::Part:
return std::make_tuple(BaseRule::MatchResult::Part, std::get<1>(result_gen));
default:
temp_head = std::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);
switch (std::get<0>(result_gen)) {
case BaseRule::MatchResult::Fail:
case BaseRule::MatchResult::Part:
return std::make_tuple(BaseRule::MatchResult::Success, temp_head);
default:
temp_head = std::get<1>(result_gen);
break;
}
}
return std::make_tuple(BaseRule::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<std::shared_ptr<const BaseRule>> mbrs) : mbrs_store(mbrs) {}
QList<std::shared_ptr<const BaseRule>> Seqs::children() const { return mbrs_store; }
std::tuple<BaseRule::MatchResult, std::shared_ptr<const IWordBase>> Seqs::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
auto temp_head = head;
for (auto& r : mbrs_store) {
auto rst_gene = r->parse(rt_inst, temp_head);
switch (std::get<0>(rst_gene)) {
case BaseRule::MatchResult::Fail:
return std::make_tuple(BaseRule::MatchResult::Part, temp_head);
case BaseRule::MatchResult::Part:
return rst_gene;
case BaseRule::MatchResult::Success:
temp_head = std::get<1>(rst_gene);
break;
default:
break;
}
}
return std::make_tuple(BaseRule::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);
}
//std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const Token>>
Any::Any(const QList<std::shared_ptr<const BaseRule>> mbrs) : mbrs_store(mbrs) {}
QList<std::shared_ptr<const BaseRule>> 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;
}
};
std::tuple<BaseRule::MatchResult, std::shared_ptr<const IWordBase>> Any::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
std::tuple<std::shared_ptr<const BaseRule>, int> temp_result = std::make_tuple(nullptr, -1);
auto rule_present = this->token_present();
for (auto& fork : mbrs_store) {
auto gen = fork->parse(rt_inst, head);
switch (std::get<0>(gen)) {
// 遇到成功的直接返回解析结果
case BaseRule::MatchResult::Success:
return gen;
case BaseRule::MatchResult::Fail: {
if (!std::get<0>(temp_result))
temp_result = std::make_tuple(fork, 0);
}break;
case BaseRule::MatchResult::Part: {
auto span = std::get<1>(gen)->position() - head->position();
if (span > std::get<1>(temp_result))
temp_result = std::make_tuple(fork, span);
}
default:
break;
}
}
// 分析最匹配的分支
rt_inst->clearErrors(head->position());
auto temp = std::get<0>(temp_result)->parse(rt_inst, head);
return std::make_tuple(BaseRule::MatchResult::Part, std::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->filter_proc = [](const TokenSeqs& seqs) { return seqs; };
this->mark_store = expr_mark;
}
std::shared_ptr<const ExprRule> ExprRule::reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule) {
auto ninst = makeCopy();
ninst->child_store = rule;
ninst->filter_proc = filter;
return ninst;
}
QString ExprRule::name() const { return name_store; }
int ExprRule::typeMark() const { return this->mark_store; }
QList<std::shared_ptr<const BaseRule>> ExprRule::children() const {
return QList<std::shared_ptr<const BaseRule>>() << this->child_store;
}
std::tuple<BaseRule::MatchResult, std::shared_ptr<const IWordBase>>
ExprRule::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
std::shared_ptr<ExprInst> elm_ast = this->newEmptyInstance();
auto text_present = this->token_present();
rt_inst->pushExpressionRule(this->shared_from_this());
rt_inst->pushInst(elm_ast);
auto rstg = child_store->parse(rt_inst, head);
auto tokens_decl = this->filter_proc(elm_ast->tokens());
elm_ast->tokensReset(tokens_decl);
switch (std::get<0>(rstg)) {
case BaseRule::MatchResult::Fail:
case BaseRule::MatchResult::Part:
rt_inst->popInst();
rt_inst->popExpressionRule();
break;
case BaseRule::MatchResult::Success: {
rt_inst->clearErrors(tokens_decl.first()->position());
rt_inst->popInst();
rt_inst->popExpressionRule();
if (rt_inst->currentInst()) {
rt_inst->currentInst()->addChild(elm_ast);
}
else {
rt_inst->appendDoc(elm_ast);
}
}break;
default:
break;
}
return rstg;
}
QString ExprRule::token_present() const {
return QString(u8"(%1)").arg(child_store->token_present());
}