#pragma once #include "libsyntax_global.h" #include #include #include #include namespace ast_basic { class IExprInst; class ExprElement; } namespace lib_syntax { class IBasicRule; /** * @brief 语法异常 */ class LIBSYNTAX_EXPORT SyntaxException { private: QString msg_store; public: SyntaxException(const QString& message); virtual ~SyntaxException() = default; virtual QString message() const; }; // 基础语法解析接口 =================================================================================================== /** * @brief 解析上下文接口 */ class IContext { public: virtual ~IContext() = default; virtual void setCurrentFile(const QString& path) = 0; virtual QString currentFile() const = 0; virtual void appendParseErrors(const QString& file_path, int start, const QString& error_msg) = 0; virtual QStringList errors() const = 0; virtual void clearErrors(const QString& file_path, int start) = 0; virtual void appendDocInst(std::shared_ptr inst) = 0; virtual QList> getDocInsts() const = 0; /** * \brief 当前表达式元素. * * \return 返回当前表达式 */ virtual std::shared_ptr currentExprInst() const = 0; virtual void pushExprInst(std::shared_ptr current_inst) = 0; virtual std::shared_ptr popExprInst() = 0; virtual std::shared_ptr currentExprRule() const = 0; virtual void pushExprRule(std::shared_ptr inst) = 0; virtual std::shared_ptr popExprRule() = 0; virtual QList> currentExprRuleStack() const = 0; }; /** * @brief 基础语法匹配规则接口 */ class IBasicRule { public: virtual ~IBasicRule() = default; /** * @brief 子规则 * @return */ virtual QList> children() const = 0; /** * @brief 匹配结果 */ enum class MatchResult { Success, // 符合匹配条件 Part, // 部分匹配 Fail // 从第一个词起完全不匹配 }; /** * @brief 解析 * @param rt_inst 解析上下文 * @param head 列表头 * @return 返回结果<匹配完成新列表头,匹配长度> */ virtual std::tuple> parse(std::shared_ptr rt_inst, std::shared_ptr head) const = 0; /** * 返回匹配语法规则的词法序列表达 * * \return 词法表达序列 */ virtual QString token_present() const = 0; }; template using token_proc = void(*)(std::shared_ptr expr_inst, std::shared_ptr token); /** * @brief token匹配 */ template xproc = nullptr> class TokenMatch : public IBasicRule, public std::enable_shared_from_this> { private: std::shared_ptr define_peer; public: TokenMatch(std::shared_ptr define) : define_peer(define) {} // IBasicRule interface public: virtual QList> children() const override { return QList>(); } virtual std::tuple> parse(std::shared_ptr rt_inst, std::shared_ptr head) const override { if (!head) { rt_inst->appendParseErrors(rt_inst->currentFile(), -1, QString(u8"Syntax[0x0000]token流(%1)提前终止").arg(rt_inst->currentFile())); return std::make_tuple(IBasicRule::MatchResult::Fail, head); } auto match_result = define_peer->analysis(head); if (std::get<0>(match_result)) { auto current_inst = rt_inst->currentExprInst(); current_inst->addToken(std::get<0>(match_result)); if (xproc) { xproc(std::dynamic_pointer_cast(current_inst), std::get<0>(match_result)); } if (std::get<1>(match_result)) { return std::make_tuple(IBasicRule::MatchResult::Success, std::make_shared(std::get<1>(match_result), head->nextWord())); } else { return std::make_tuple(IBasicRule::MatchResult::Success, head->nextWord()); } } else { rt_inst->appendParseErrors(rt_inst->currentFile(), head->position(), QString(u8"Syntax[0x00001]语法匹配错误,无法识别\"%1\"(应该为:%4)\n\t目标语法:%5。\n") .arg(head->content()).arg(head->row()).arg(head->column()).arg(this->define_peer->reviseWords()) .arg(rt_inst->currentExprRule()->token_present())); return std::make_tuple(IBasicRule::MatchResult::Part, head); } } virtual QString token_present() const override { return QString(u8"%1").arg(this->define_peer->reviseWords()); } }; /** * @brief 语法规则或匹配 */ class LIBSYNTAX_EXPORT Any : public IBasicRule, public std::enable_shared_from_this { private: QList> mbrs_store; std::tuple, std::shared_ptr> rule_select(std::shared_ptr head) const; public: Any(const QList> mbrs); // IBasicRule interface public: virtual QList> children() const override; virtual std::tuple> parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_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 std::tuple> parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_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 std::tuple> parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; }; // 组合语法实体解析 =================================================================================================== /** * @brief 对应语法表达式解析规则 */ class LIBSYNTAX_EXPORT ExprRule : public lib_syntax::IBasicRule, public std::enable_shared_from_this { public: typedef QList> TokenSeqs; ExprRule(const QString& rule_name, int expr_mark); virtual std::shared_ptr reloadRule(std::shared_ptr rule); virtual QString name() const; virtual int typeMark() const; virtual std::shared_ptr newEmptyInstance() const = 0; virtual std::shared_ptr makeCopy() const = 0; // IBasicRule interface public: virtual QList> children() const override; virtual std::tuple> parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; protected: std::shared_ptr child_store; private: QString name_store; int mark_store; }; /** * 语法元素解析规则. */ template class ElementRule : public ExprRule { public: ElementRule(const QString& rule_name, int expr_mark) :ExprRule(rule_name, expr_mark) {} virtual std::shared_ptr newEmptyInstance() const { return std::dynamic_pointer_cast( std::make_shared(this->shared_from_this())); } virtual std::shared_ptr makeCopy() const { return std::make_shared>(name(), typeMark()); } }; } // namespace lib_syntax