WsParser_VS/libSyntax/libsyntax.h

382 lines
13 KiB
C++
Raw Permalink 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.

#pragma once
#include "libsyntax_global.h"
#include "libtokens.h"
#include "tokens_impl.h"
#include <memory>
#include <QtCore/QList>
#include <QtCore/QDebug>
#include <QtCore/QHash>
#include <tuple>
#include <functional>
#include "ast_basic.h"
namespace lib_syntax {
/**
* @brief 语法异常
*/
class LIBSYNTAX_EXPORT SyntaxException {
private:
QString msg_store;
public:
SyntaxException(const QString& message);
virtual ~SyntaxException() = default;
virtual QString message() const;
};
// 基础语法解析接口 ====================================================================================
/**
* @brief 解析上下文接口
*/
class LIBSYNTAX_EXPORT MatchCursor {
public:
class ErrsPack {
public:
ErrsPack();
ErrsPack(const ErrsPack& other);
void addError(std::shared_ptr<const lib_words::IPrimitiveWord>, const QString& msg);
QList<std::pair<std::shared_ptr<const lib_words::IPrimitiveWord>, QString>> errors() const;
uint64_t errorCount() const;
private:
QList<std::pair<std::shared_ptr<const lib_words::IPrimitiveWord>, QString>> _error_collection;
};
MatchCursor(const QString& path);
MatchCursor(std::shared_ptr<const MatchCursor> other_ptr);
virtual ~MatchCursor() = default;
bool operator>(const MatchCursor& other) const;
virtual std::shared_ptr<const MatchCursor> previous() const;
virtual QString filePath() const;
virtual QString parseSyntax() const;
virtual void enterExprs();
virtual void logExprsError(std::shared_ptr<const lib_words::IPrimitiveWord> t, const QString& msg);
virtual void quitExprs();
virtual int exprsErrorCount() const;
virtual int totalErrorCount() const;
virtual QList<QString> totalErrors() const;
virtual void mergeWith(const MatchCursor &other);
virtual bool parseFailure() const;
virtual void setFailure(bool mark = true);
virtual bool parseComplete() const;
virtual void setComplete(bool mark = true);
virtual void setCurrent(std::shared_ptr<const lib_token::IActionToken> t, std::shared_ptr<const lib_words::IPrimitiveWord> remains);
virtual std::shared_ptr<const lib_token::IActionToken> token() const;
virtual std::shared_ptr<const lib_words::IPrimitiveWord> words() const;
private:
QString _file_path;
std::shared_ptr<const MatchCursor> _prev_cursor = nullptr;
bool _parse_stop_with_errors = false, _parse_complete = false;
QHash<qulonglong, QStringList> _total_errors; // 所有解析错误
QList<std::shared_ptr<ErrsPack>> _exprs_errors; // 当前表达式解析错误
std::shared_ptr<const lib_token::IActionToken> _current_token = nullptr; // 当前Token
std::shared_ptr<const lib_words::IPrimitiveWord> _remains_word = nullptr; // 剩余词语
};
/**
* @brief 基础语法匹配规则接口
*/
class IBasicRule {
public:
/**
* @brief 子规则
* @return
*/
virtual QList<std::shared_ptr<const IBasicRule>> children() const = 0;
/**
* 返回匹配语法规则的词法序列表达
*
* \return 词法表达序列
*/
virtual QString present() const = 0;
/**
* @brief 解析
* @param cursor 解析游标
* @param out 解析结束的分支存储集合
* @return 返回结果<匹配分支>
*/
virtual QList<std::shared_ptr<const MatchCursor>> parse(std::shared_ptr<const MatchCursor> cursor) const = 0;
};
// 组合语法实体解析 =====================================================================================
/**
* @brief 语法规则或匹配
*/
class LIBSYNTAX_EXPORT __anyone_impl : public IBasicRule, public std::enable_shared_from_this<__anyone_impl> {
private:
QList<std::shared_ptr<const IBasicRule>> mbrs_store;
public:
__anyone_impl(const QList<std::shared_ptr<const IBasicRule>> mbrs);
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual QList<std::shared_ptr<const MatchCursor>> parse(std::shared_ptr<const MatchCursor> cursor) const override;
virtual QString present() const override;
};
/**
* @brief 语法规则序列匹配
*/
class LIBSYNTAX_EXPORT __sequence_impl : public IBasicRule, public std::enable_shared_from_this<__sequence_impl> {
private:
QList<std::shared_ptr<const IBasicRule>> mbrs_store;
public:
__sequence_impl(const QList<std::shared_ptr<const IBasicRule>> mbrs);
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual QList<std::shared_ptr<const MatchCursor>> parse(std::shared_ptr<const MatchCursor> cursor) const override;
virtual QString present() const override;
};
/**
* @brief 语法规则重复匹配
*/
class LIBSYNTAX_EXPORT __repeat_impl : public IBasicRule, public std::enable_shared_from_this<__repeat_impl> {
private:
std::shared_ptr<const IBasicRule> rule_peer;
int min_match, max_match;
public:
__repeat_impl(std::shared_ptr<const IBasicRule> rule, int min, int max);
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual QList<std::shared_ptr<const MatchCursor>> parse(std::shared_ptr<const MatchCursor> cursor) const override;
virtual QString present() const override;
};
/**
* @brief 对应语法表达式解析规则
*/
class LIBSYNTAX_EXPORT ExprRule : public IBasicRule, public std::enable_shared_from_this<ExprRule> {
public:
ExprRule(const QString& rule_name, int expr_mark);
virtual QString name() const;
virtual int typeMark() const;
protected:
virtual QList<std::shared_ptr<const MatchCursor>> expr_rule_parse(std::shared_ptr<const MatchCursor> cursor) const = 0;
private:
QString name_store;
int mark_store;
};
/**
* @brief token匹配
*/
template<typename ELEM, lib_token::TokenProc<ELEM> XProc = nullptr>
requires std::derived_from<ELEM, ast_basic::IExprInstance>
class __token_match_impl : public IBasicRule, public std::enable_shared_from_this<__token_match_impl<ELEM, XProc>> {
private:
std::shared_ptr<const lib_token::ITokenProcess> _define_peers;
public:
__token_match_impl(std::shared_ptr<const lib_token::ITokenProcess> define) : _define_peers(define) {
}
// IBasicRule interface
public:
virtual QString present() const override {
return QString("%1").arg(this->_define_peers->reviseWords());
}
virtual QList<std::shared_ptr<const MatchCursor>> parse(std::shared_ptr<const MatchCursor> current) const override {
// 如果提前结束,记录错误并返回
if (!current->words()) {
// 只有在表达式的起始点遇到nullptr才是正常结束。
if (current->token()->tokenType() != lib_token::IActionToken::Type::ElementBegin) {
auto ncurs = std::make_shared<MatchCursor>(current);
ncurs->logExprsError(nullptr, QString("SyntaxError[0x00001]输入错误,程序提前结束:%1。").arg(current->filePath()));
ncurs->setFailure();
return QList<std::shared_ptr<const MatchCursor>>() << ncurs;
}
while (current->token()->tokenType() == lib_token::IActionToken::Type::ElementBegin)
current = current->previous();
auto ncurs = std::make_shared<MatchCursor>(current);
ncurs->setComplete();
return QList<std::shared_ptr<const MatchCursor>>() << ncurs;
}
auto w_this = current->words();
auto t_this = current->token();
auto match_result = _define_peers->analysis(w_this);
// 解析成功
if (std::get<0>(match_result)) {
auto chain = std::make_shared<lib_token::ActionToken<ELEM, XProc>>(std::get<0>(match_result), t_this);
auto remains = w_this->nextWord();
if (std::get<1>(match_result)) {
remains = std::make_shared<lib_words::WordImpl>(std::get<1>(match_result), remains);
}
auto clone_ins = std::make_shared<MatchCursor>(current);
clone_ins->setCurrent(chain, remains);
return QList<std::shared_ptr<const MatchCursor>>() << clone_ins;
}
else {
QList<std::shared_ptr<const MatchCursor>> retvals;
// 少一个
auto short_one = std::make_shared<MatchCursor>(current);
short_one->logExprsError(w_this, QString("SyntaxError[0x00002]语法匹配错误,缺失\"%1\"<row:%2,col:%3,file<%4>>")
.arg(this->_define_peers->reviseWords()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file()));
auto tkins0 = std::make_shared<lib_token::TokenContent>(w_this->row(), w_this->column(), w_this->position(),
QString("<+%1>").arg(this->_define_peers->reviseWords()), w_this->file(), this->_define_peers);
auto tkchain0 = std::make_shared<lib_token::ActionToken<ELEM, XProc>>(tkins0, t_this);
short_one->setCurrent(tkchain0, w_this);
retvals << short_one;
// 错一个
auto error_one = std::make_shared<MatchCursor>(current);
error_one->logExprsError(w_this, QString("SyntaxError[0x00003]语法匹配错误,请修正\"%1\"<row:%2,col:%3,file<%4>>")
.arg(w_this->content()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file()));
auto tkins = std::make_shared<lib_token::TokenContent>(w_this->row(), w_this->column(), w_this->position(),
QString("<%1(%2)>").arg(w_this->content()).arg(this->_define_peers->reviseWords()), w_this->file(), this->_define_peers);
auto tkchain = std::make_shared<lib_token::ActionToken<ELEM, XProc>>(tkins, t_this);
error_one->setCurrent(tkchain, w_this->nextWord());
retvals << error_one;
// 多一个
auto nx_word = w_this->nextWord();
if (nx_word) {
auto nx_result = this->_define_peers->analysis(nx_word);
if (std::get<0>(nx_result)) {
auto chain = std::make_shared<lib_token::ActionToken<ELEM, XProc>>(std::get<0>(nx_result), t_this);
auto remains = nx_word->nextWord();
if (std::get<1>(nx_result)) {
remains = std::make_shared<lib_words::WordImpl>(std::get<1>(nx_result), remains);
}
auto clone_ins = std::make_shared<MatchCursor>(current);
clone_ins->logExprsError(w_this, QString("SyntaxError[0x00004]语法匹配错误,请删除\"%1\"<row:%2,col:%3,file<%4>>")
.arg(w_this->content()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file()));
clone_ins->setCurrent(chain, remains);
retvals << clone_ins;
}
}
return retvals;
}
}
virtual QList<std::shared_ptr<const IBasicRule>> children() const override {
return QList<std::shared_ptr<const IBasicRule>>();
}
};
/**
* @brief 基础模板化语法元素解析规则.
*/
template<class ExprType, int mark, typename R>
requires std::derived_from<ExprType, ast_basic::IExprInstance>&& std::derived_from<R, lib_syntax::IBasicRule>
class ElementRule : public ExprRule {
public:
ElementRule(const QString& rule_name)
:ExprRule(rule_name, mark), _children_store(std::make_shared<R>()) {
}
virtual QList<std::shared_ptr<const IBasicRule>> children() const {
return QList<std::shared_ptr<const IBasicRule>>() << this->_children_store;
}
virtual QString present() const {
return this->_children_store->present();
}
virtual QList<std::shared_ptr<const MatchCursor>> parse(std::shared_ptr<const MatchCursor> cursor) const override {
// 提前结束,直接返回
if (cursor->parseFailure() || cursor->parseComplete())
return QList<std::shared_ptr<const MatchCursor>>() << cursor;
auto syntax = present();
auto t_this = cursor->token();
auto w_this = cursor->words();
// 起始Token打点
auto split_begin = std::make_shared<lib_token::ExprBeginToken<ExprType>>(shared_from_this(), t_this);
auto ncursor = std::make_shared<MatchCursor>(cursor);
ncursor->setCurrent(split_begin, w_this);
ncursor->enterExprs();
// 表达式语法解析
auto nbranch = this->expr_rule_parse(ncursor);
// 语法完全匹配的分支
decltype(nbranch) branch_procs;
std::copy_if(nbranch.begin(), nbranch.end(),
std::back_inserter(branch_procs),
[&](std::shared_ptr<const MatchCursor> ins) {
return ins->totalErrorCount() == cursor->totalErrorCount() || ins->parseComplete();
});
// 语法修正后能匹配的分支
if (!branch_procs.size()) {
std::copy_if(nbranch.begin(), nbranch.end(),
std::back_inserter(branch_procs),
[](std::shared_ptr<const MatchCursor> ins) { return !ins->parseFailure(); });
if(branch_procs.size()){
auto first_cursor = branch_procs.first();
for (auto curr = ++branch_procs.begin(); curr != branch_procs.end(); curr++) {
std::const_pointer_cast<lib_syntax::MatchCursor>(first_cursor)->mergeWith(**curr);
}
branch_procs = { first_cursor };
}
}
// 表达式匹配结尾
if (branch_procs.size()) {
decltype(nbranch) results_fnl;
for (auto curs : branch_procs) {
auto t_end = curs->token();
auto w_end = curs->words();
auto ecursor = std::make_shared<MatchCursor>(curs);
ecursor->quitExprs();
auto split_end = std::make_shared<lib_token::ExprEndToken<ExprType>>(split_begin, t_end);
ecursor->setCurrent(split_end, w_end);
results_fnl.append(ecursor);
if (curs->totalErrorCount() == cursor->totalErrorCount()) {
results_fnl.clear();
results_fnl.append(ecursor);
break;
}
}
return results_fnl;
}
// 匹配失败
return nbranch;
}
protected:
std::shared_ptr<const IBasicRule> _children_store;
};
} // namespace lib_syntax