WsParser_VS/libSyntax/libsyntax.cpp

226 lines
7.3 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<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> TokenMatch::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
if (!head)
throw new InputTerminal(rt_inst->currentFile());
if (head->content() == u8"³õÓö½­·ãµÄ") {
qDebug() << u8"³õÓö½­·ãµÄ";
}
auto match_result = define_peer->analysis(head);
if (std::get<0>(match_result)) {
rt_inst->currentInst()->addToken(std::get<0>(match_result));
}
else {
throw new MismatchException(head);
}
if (std::get<1>(match_result)) {
return std::make_tuple(nullptr, std::make_shared<WordImpl>(std::get<1>(match_result), head->nextWord()));
}
else {
return std::make_tuple(nullptr, 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<std::shared_ptr<const Expression>, 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);
if (std::get<0>(result_gen))
rt_inst->currentInst()->addChild(std::get<0>(result_gen));
temp_head = std::get<1>(result_gen);
}
// max-match
for (auto idx = min_match; idx < max_match; ++idx) {
try {
auto result_gen = rule_peer->parse(rt_inst, temp_head);
if (std::get<0>(result_gen))
rt_inst->currentInst()->addChild(std::get<0>(result_gen));
temp_head = std::get<1>(result_gen);
}
catch (SyntaxException* ex) {
delete ex;
return std::make_tuple(nullptr, temp_head);
}
}
return std::make_tuple(nullptr, 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<std::shared_ptr<const Expression>, 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);
temp_head = std::get<1>(rst_gene);
if (std::get<0>(rst_gene))
rt_inst->currentInst()->addChild(std::get<0>(rst_gene));
}
return std::make_tuple(nullptr, 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<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> Any::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
std::function<words_span(std::shared_ptr<const IWordBase>, std::shared_ptr<const IWordBase>)> measure_span =
[&](std::shared_ptr<const IWordBase> anchor, std::shared_ptr<const IWordBase> head)->words_span {
return words_span(anchor->row() - head->row(), anchor->column() - head->column());
};
std::tuple<std::shared_ptr<const BaseRule>, words_span> temp_result = std::make_tuple(mbrs_store.first(), words_span(0,0));
for (auto& fork : mbrs_store) {
try {
auto gen = fork->parse(rt_inst, head);
// Óöµ½³É¹¦µÄÖ±½Ó·µ»Ø½âÎö½á¹û
if (std::get<0>(gen))
rt_inst->currentInst()->addChild(std::get<0>(gen));
return std::make_tuple(nullptr, std::get<1>(gen));
}
// Óï·¨´íÎóµÄ»á½øÐбȽÏ
catch (MismatchException* ex) {
auto current_span = measure_span(ex->targetWord(), head);
if (current_span > std::get<1>(temp_result))
temp_result = std::make_tuple(fork, current_span);
delete ex;
}
}
// ·ÖÎö×îÆ¥ÅäµÄ·ÖÖ§
return std::get<0>(temp_result)->parse(rt_inst, head);
}
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; }
ExpressionRule::ExpressionRule(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 ExpressionRule> ExpressionRule::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 ExpressionRule::name() const { return name_store; }
int ExpressionRule::typeMark() const { return this->mark_store; }
QList<std::shared_ptr<const BaseRule>> ExpressionRule::children() const {
return QList<std::shared_ptr<const BaseRule>>() << this->child_store;
}
std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> ExpressionRule::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
std::shared_ptr<Expression> elm_ast = this->newEmptyInstance();
rt_inst->pushExpressionRule(this->shared_from_this());
rt_inst->pushInst(elm_ast);
try {
auto rstg = child_store->parse(rt_inst, head);
auto tokens_decl = this->filter_proc(elm_ast->tokens());
elm_ast->tokensReset(tokens_decl);
rt_inst->popInst();
rt_inst->popExpressionRule();
return std::make_tuple(elm_ast, std::get<1>(rstg));
}
catch (...) {
rt_inst->popInst();
rt_inst->popExpressionRule();
throw;
}
}
QString ExpressionRule::token_present() const {
return QString(u8"(%1)").arg(child_store->token_present());
}
MismatchException::MismatchException(std::shared_ptr<const lib_token::IWordBase> inst) :SyntaxException(
QString(u8"Syntax[0x00001]Ó﷨ƥÅä´íÎ󣬲»ÄÜʶ±ðtoken£º%1<%2,%3>(%4)")
.arg(inst->content()).arg(inst->row()).arg(inst->column()).arg(inst->file())), target(inst) {}
std::shared_ptr<const IWordBase>MismatchException::targetWord() const {
return this->target;
}
InputTerminal::InputTerminal(const QString& file_path)
:SyntaxException(QString(u8"Syntax[0x0000]tokenÁ÷£¨%1£©ÌáǰÖÕÖ¹").arg(file_path)) {}