#pragma once #include "libsyntax_global.h" #include "libtokens.h" #include "tokens_impl.h" #include #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: ErrsPack(); ErrsPack(const ErrsPack& other); 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 QString parseSyntax() const; virtual void enterExprs(); virtual void logExprsError(const QString& msg); virtual void quitExprs(); virtual int exprsErrorCount() const; virtual int totalErrorCount() const; virtual QList totalErrors() const; 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 t, std::shared_ptr remains); virtual std::shared_ptr token() const; virtual std::shared_ptr words() const; private: QString _file_path; std::shared_ptr _prev_cursor = nullptr; bool _parse_stop_with_errors = false, _parse_complete = false; QList _total_errors; // 所有解析错误 QList> _exprs_errors; // 当前表达式解析错误 std::shared_ptr _current_token = nullptr; // 当前Token std::shared_ptr _remains_word = nullptr; // 剩余词语 }; /** * @brief 基础语法匹配规则接口 */ class IBasicRule { public: /** * @brief 子规则 * @return */ virtual QList> children() const = 0; /** * 返回匹配语法规则的词法序列表达 * * \return 词法表达序列 */ virtual QString present() const = 0; /** * @brief 解析 * @param cursor 解析游标 * @param out 解析结束的分支存储集合 * @return 返回结果<匹配分支> */ virtual QList> parse(std::shared_ptr cursor) const = 0; }; // 组合语法实体解析 ===================================================================================== /** * @brief 语法规则或匹配 */ class LIBSYNTAX_EXPORT __anyone_impl : public IBasicRule, public std::enable_shared_from_this<__anyone_impl> { private: QList> mbrs_store; public: __anyone_impl(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 __sequence_impl : public IBasicRule, public std::enable_shared_from_this<__sequence_impl> { private: QList> mbrs_store; public: __sequence_impl(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 __repeat_impl : public IBasicRule, public std::enable_shared_from_this<__repeat_impl> { private: std::shared_ptr rule_peer; int min_match, max_match; public: __repeat_impl(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 __token_match_impl : public IBasicRule, public std::enable_shared_from_this<__token_match_impl> { private: std::shared_ptr _define_peers; public: __token_match_impl(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 { // 如果提前结束,记录错误并返回 if (!current->words()) { // 只有在表达式的起始点遇到nullptr,才是正常结束。 if (current->token()->tokenType() != lib_token::IActionToken::Type::ElementBegin) { auto ncurs = std::make_shared(current); ncurs->logExprsError(QString("SyntaxError[0x00001]输入错误,程序提前结束:%1。").arg(current->filePath())); ncurs->setFailure(); return QList>() << ncurs; } while (current->token()->tokenType() == lib_token::IActionToken::Type::ElementBegin) current = current->previous(); auto ncurs = std::make_shared(current); ncurs->setComplete(); return QList>() << 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>(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("SyntaxError[0x00002]语法匹配错误,缺失\"%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("SyntaxError[0x00003]语法匹配错误,请修正\"%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; // 多一个 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>(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("SyntaxError[0x00004]语法匹配错误,请删除\"%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&& std::derived_from class ElementRule : public ExprRule { public: ElementRule(const QString& rule_name) :ExprRule(rule_name, mark), _children_store(std::make_shared()) { } 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->parseFailure() && cursor->parseComplete()) return QList>() << cursor; auto syntax = present(); auto t_this = cursor->token(); auto w_this = cursor->words(); // 起始Token打点 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) branch_procs; std::copy_if(nbranch.begin(), nbranch.end(), std::back_inserter(branch_procs), [&](std::shared_ptr 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 ins) { return !ins->parseFailure(); }); } if (!branch_procs.size()) branch_procs = nbranch; decltype(nbranch) results_fnl; for (auto curs : branch_procs) { if (curs->parseFailure()) results_fnl.append(curs); else { auto t_end = curs->token(); auto w_end = curs->words(); auto ecursor = std::make_shared(curs); ecursor->quitExprs(); auto split_end = std::make_shared>(split_begin, t_end); ecursor->setCurrent(split_end, w_end); results_fnl.append(ecursor); } } return results_fnl; } protected: std::shared_ptr _children_store; }; } // namespace lib_syntax