#pragma once #include "libsyntax_global.h" #include "libtokens.h" #include "tokens_impl.h" #include #include #include #include #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: void addError(const QString& msg); QList errors() const; uint64_t errorCount() const; private: QList _error_collection; }; MatchCursor(const QString& path); MatchCursor(std::shared_ptr other_ptr); virtual ~MatchCursor() = default; virtual std::shared_ptr previous() const; virtual QString filePath() const; virtual void enterExprs(); virtual void logExprsError(const QString& msg); virtual void quitExprs(); virtual bool mustStop() const; virtual int exprsErrorCount() const; virtual int totalErrorCount() const; virtual QList totalErrors() const; virtual void setCurrent(std::shared_ptr t, std::shared_ptr remains); virtual std::shared_ptr currentToken() const; virtual std::shared_ptr currentWords() const; private: QString _file_path; std::shared_ptr _prev_cursor = nullptr; QList _total_errors; // 所有解析错误 QList> _exprs_errors; // 当前表达式解析错误 std::shared_ptr _current_token = nullptr; // 当前Token std::shared_ptr _remains_word = nullptr; // 剩余词语 bool parse_stop() const; }; /** * @brief 基础语法匹配规则接口 */ class IBasicRule { public: /** * @brief 子规则 * @return */ virtual QList> children() const = 0; /** * 返回匹配语法规则的词法序列表达 * * \return 词法表达序列 */ virtual QString present() const = 0; /** * @brief 解析 * @param cursor 解析游标 * @return 返回结果<匹配分支> */ virtual QList> parse(std::shared_ptr cursor) const = 0; }; // 组合语法实体解析 ===================================================================================== /** * @brief 语法规则或匹配 */ class LIBSYNTAX_EXPORT Any : public IBasicRule, public std::enable_shared_from_this { private: QList> mbrs_store; public: Any(const QList> mbrs); // IBasicRule interface public: virtual QList> children() const override; virtual QList> parse(std::shared_ptr cursor) const override; virtual QString present() const override; }; /** * @brief 语法规则序列匹配 */ class LIBSYNTAX_EXPORT Seqs : public IBasicRule, public std::enable_shared_from_this { private: QList> mbrs_store; public: Seqs(const QList> mbrs); // IBasicRule interface public: virtual QList> children() const override; virtual QList> parse(std::shared_ptr cursor) const override; virtual QString present() const override; }; /** * @brief 语法规则重复匹配 */ class LIBSYNTAX_EXPORT Rept : public IBasicRule, public std::enable_shared_from_this { private: std::shared_ptr rule_peer; int min_match, max_match; public: Rept(std::shared_ptr rule, int min, int max); // IBasicRule interface public: virtual QList> children() const override; virtual QList> parse(std::shared_ptr cursor) const override; virtual QString present() const override; }; /** * @brief 对应语法表达式解析规则 */ class LIBSYNTAX_EXPORT ExprRule : public IBasicRule, public std::enable_shared_from_this { public: ExprRule(const QString& rule_name, int expr_mark); virtual QString name() const; virtual int typeMark() const; protected: virtual QList> expr_rule_parse(std::shared_ptr cursor) const = 0; private: QString name_store; int mark_store; }; /** * @brief token匹配 */ template XProc = nullptr> requires std::derived_from class TokenMatch : public IBasicRule, public std::enable_shared_from_this> { private: std::shared_ptr _define_peers; public: TokenMatch(std::shared_ptr define) : _define_peers(define) { } // IBasicRule interface public: virtual QString present() const override { return QString("%1").arg(this->_define_peers->reviseWords()); } virtual QList> parse(std::shared_ptr current) const override { auto w_this = current->currentWords(); if (!w_this) { auto clone_ins = std::make_shared(current); clone_ins->logExprsError(QString("Syntax[0x00001]语法匹配错误,缺失\"%1\">") .arg(this->_define_peers->reviseWords()).arg(current->filePath())); clone_ins->logExprsError(QString("Syntax[0x00001]输入流提前结束,<%1>").arg(current->filePath())); return QList>() << clone_ins; } auto t_this = current->currentToken(); auto match_result = _define_peers->analysis(w_this); if (std::get<0>(match_result)) { auto chain = std::make_shared>(std::get<0>(match_result), t_this); auto remains = w_this->nextWord(); if (std::get<1>(match_result)) { remains = std::make_shared(std::get<1>(match_result), remains); } auto clone_ins = std::make_shared(current); clone_ins->setCurrent(chain, remains); return QList>() << clone_ins; } else { QList> retvals; // 少一个 { auto short_one = std::make_shared(current); short_one->logExprsError(QString("Syntax[0x00001]语法匹配错误,缺失\"%1\">") .arg(this->_define_peers->reviseWords()) .arg(w_this->row()).arg(w_this->column()).arg(w_this->file())); retvals << short_one; } // 错一个 { auto error_one = std::make_shared(current); error_one->logExprsError(QString("Syntax[0x00001]语法匹配错误,请修正\"%1\">") .arg(w_this->content()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file())); auto tkins = std::make_shared( w_this->row(), w_this->column(), w_this->position(), QString("%2_%1").arg((uint64_t) error_one.get()).arg(this->_define_peers->reviseWords()), w_this->file(), this->_define_peers); auto tkchain = std::make_shared>(tkins, t_this); error_one->setCurrent(tkchain, w_this->nextWord()); retvals << error_one; } // 多一个 if (w_this->nextWord()) { auto nx_word = w_this->nextWord(); auto nx_result = this->_define_peers->analysis(nx_word); if (std::get<0>(nx_result)) { auto chain = std::make_shared>(std::get<0>(nx_result), t_this); auto remains = nx_word->nextWord(); if (std::get<1>(nx_result)) { remains = std::make_shared(std::get<1>(nx_result), remains); } auto clone_ins = std::make_shared(current); clone_ins->logExprsError(QString("Syntax[0x00001]语法匹配错误,请删除\"%1\">") .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> children() const override { return QList>(); } }; /** * @brief 基础模板化语法元素解析规则. */ template requires std::derived_from class ElementRule : public ExprRule { public: ElementRule(const QString& rule_name, std::shared_ptr children) :ExprRule(rule_name, mark), _children_store(children) { } virtual QList> children() const { return QList>() << this->_children_store; } virtual QString present() const { return this->_children_store->present(); } virtual QList> parse(std::shared_ptr cursor) const override { if (cursor->mustStop()) return QList>() << cursor; auto t_this = cursor->currentToken(); auto w_this = cursor->currentWords(); auto split_begin = std::make_shared>(shared_from_this(), t_this); auto ncursor = std::make_shared(cursor); ncursor->setCurrent(split_begin, w_this); ncursor->enterExprs(); auto nbranch = this->expr_rule_parse(ncursor); decltype(nbranch) list_ok; // 选择完全匹配成功的 std::copy_if(nbranch.begin(), nbranch.end(), std::back_inserter(list_ok), [](std::shared_ptr ins) { return !ins->exprsErrorCount(); }); if (!list_ok.size()) { // 选择被修正的 std::copy_if(nbranch.begin(), nbranch.end(), std::back_inserter(list_ok), [](std::shared_ptr ins) { return !ins->mustStop(); }); // 匹配失败的 if (!list_ok.size()) list_ok = nbranch; } decltype(list_ok) branch_procs; std::for_each(list_ok.begin(), list_ok.end(), [&](std::shared_ptr curs) { if (curs->mustStop()) { branch_procs.append(curs); } else { auto t_end = curs->currentToken(); auto w_end = curs->currentWords(); auto ecursor = std::make_shared(curs); ecursor->quitExprs(); auto split_end = std::make_shared>(split_begin, t_end); ecursor->setCurrent(split_end, w_end); branch_procs.append(ecursor); } }); return branch_procs; } protected: std::shared_ptr _children_store; }; } // namespace lib_syntax