#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: /** * 返回匹配语法规则的词法序列表达 * * \return 词法表达序列 */ virtual QString present() const = 0; /** * @brief 解析 * @param rt_inst 解析上下文 * @param head 列表头 * @return 返回结果<匹配完成新列表头,匹配长度> */ virtual QList> parse(std::shared_ptr cursor) const = 0; /** * @brief 子规则 * @return */ virtual QList> children() 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; virtual std::shared_ptr reloadRule(std::shared_ptr rule) const; // IBasicRule interface public: virtual QList> children() const override; virtual QString present() const override; protected: std::shared_ptr child_store; virtual std::shared_ptr make_copy() const = 0; private: QString name_store; int mark_store; }; /** * @brief token匹配 */ template XProc = nullptr> 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(u8"%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(u8"Syntax[0x00001]语法匹配错误,缺失\"%1\">") .arg(this->_define_peers->reviseWords()).arg(current->filePath())); clone_ins->logExprsError(QString(u8"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(u8"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(u8"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(u8"%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(u8"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>(); } }; /** * 语法元素解析规则. */ template class ElementRule : public ExprRule { public: ElementRule(const QString& rule_name, int expr_mark) :ExprRule(rule_name, expr_mark) { } 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->child_store->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: virtual std::shared_ptr make_copy() const { return std::make_shared>(this->name(), this->typeMark()); } }; } // namespace lib_syntax