WsParser_VS/libSyntax/libsyntax.h

258 lines
8.5 KiB
C++
Raw 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 <libtoken.h>
#include <memory>
#include <tuple>
#include <functional>
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<ast_basic::IExprInst> inst) = 0;
virtual QList<std::shared_ptr<const ast_basic::IExprInst>> getDocInsts() const = 0;
/**
* \brief 当前表达式元素.
*
* \return 返回当前表达式
*/
virtual std::shared_ptr<ast_basic::IExprInst> currentExprInst() const = 0;
virtual void pushExprInst(std::shared_ptr<ast_basic::IExprInst> current_inst) = 0;
virtual std::shared_ptr<ast_basic::IExprInst> popExprInst() = 0;
virtual std::shared_ptr<const IBasicRule> currentExprRule() const = 0;
virtual void pushExprRule(std::shared_ptr<const IBasicRule> inst) = 0;
virtual std::shared_ptr<const IBasicRule> popExprRule() = 0;
virtual QList<std::shared_ptr<const IBasicRule>> currentExprRuleStack() const = 0;
};
/**
* @brief 基础语法匹配规则接口
*/
class IBasicRule {
public:
virtual ~IBasicRule() = default;
/**
* @brief 子规则
* @return
*/
virtual QList<std::shared_ptr<const IBasicRule>> children() const = 0;
/**
* @brief 匹配结果
*/
enum class MatchResult {
Success, // 符合匹配条件
Part, // 部分匹配
Fail // 从第一个词起完全不匹配
};
/**
* @brief 解析
* @param rt_inst 解析上下文
* @param head 列表头
* @return 返回结果<匹配完成新列表头,匹配长度>
*/
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>>
parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const = 0;
/**
* 返回匹配语法规则的词法序列表达
*
* \return 词法表达序列
*/
virtual QString token_present() const = 0;
};
template<typename elem>
using token_proc = void(*)(std::shared_ptr<elem> expr_inst, std::shared_ptr<const lib_token::IToken> token);
/**
* @brief token匹配
*/
template<typename elem, token_proc<elem> xproc = nullptr>
class TokenMatch : public IBasicRule, public std::enable_shared_from_this<TokenMatch<elem, xproc>> {
private:
std::shared_ptr<const lib_token::ITokenDefine> define_peer;
public:
TokenMatch(std::shared_ptr<const lib_token::ITokenDefine> define) : define_peer(define) {}
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override { return QList<std::shared_ptr<const IBasicRule>>(); }
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>> parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> 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<elem>(current_inst), std::get<0>(match_result));
}
if (std::get<1>(match_result)) {
return std::make_tuple(IBasicRule::MatchResult::Success, std::make_shared<WordImpl>(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\"<row:%2,col:%3>(应该为:%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<Any> {
private:
QList<std::shared_ptr<const IBasicRule>> mbrs_store;
std::tuple<MatchResult, uint, std::shared_ptr<const IBasicRule>, std::shared_ptr<const lib_token::IWordBase>> rule_select(std::shared_ptr<const lib_token::IWordBase> head) const;
public:
Any(const QList<std::shared_ptr<const IBasicRule>> mbrs);
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>>
parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
virtual QString token_present() const override;
};
/**
* @brief 语法规则序列匹配
*/
class LIBSYNTAX_EXPORT Seqs : public IBasicRule, public std::enable_shared_from_this<Seqs> {
private:
QList<std::shared_ptr<const IBasicRule>> mbrs_store;
public:
Seqs(const QList<std::shared_ptr<const IBasicRule>> mbrs);
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>>
parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
virtual QString token_present() const override;
};
/**
* @brief 语法规则重复匹配
*/
class LIBSYNTAX_EXPORT Rept : public IBasicRule, public std::enable_shared_from_this<Rept> {
private:
std::shared_ptr<const IBasicRule> rule_peer;
int min_match, max_match;
public:
Rept(std::shared_ptr<const IBasicRule> rule, int min, int max);
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const IBasicRule>> children() const override;
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>>
parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
virtual QString token_present() const override;
};
// 组合语法实体解析 ===================================================================================================
/**
* @brief 对应语法表达式解析规则
*/
class LIBSYNTAX_EXPORT ExprRule : public lib_syntax::IBasicRule, public std::enable_shared_from_this<ExprRule> {
public:
typedef QList<std::shared_ptr<const lib_token::IToken>> TokenSeqs;
ExprRule(const QString& rule_name, int expr_mark);
virtual std::shared_ptr<const ExprRule> reloadRule(std::shared_ptr<const IBasicRule> rule);
virtual QString name() const;
virtual int typeMark() const;
virtual std::shared_ptr<ast_basic::IExprInst> newEmptyInstance() const = 0;
virtual std::shared_ptr<ExprRule> makeCopy() const = 0;
// IBasicRule interface
public:
virtual QList<std::shared_ptr<const lib_syntax::IBasicRule>> children() const override;
virtual std::tuple<IBasicRule::MatchResult, std::shared_ptr<const lib_token::IWordBase>>
parse(std::shared_ptr<IContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
virtual QString token_present() const override;
protected:
std::shared_ptr<const lib_syntax::IBasicRule> child_store;
private:
QString name_store;
int mark_store;
};
/**
* 语法元素解析规则.
*/
template<class ExprType>
class ElementRule : public ExprRule {
public:
ElementRule(const QString& rule_name, int expr_mark)
:ExprRule(rule_name, expr_mark) {}
virtual std::shared_ptr<ast_basic::IExprInst> newEmptyInstance() const {
return std::dynamic_pointer_cast<ast_basic::IExprInst>(
std::make_shared<ExprType>(this->shared_from_this()));
}
virtual std::shared_ptr<ExprRule> makeCopy() const {
return std::make_shared<ElementRule<ExprType>>(name(), typeMark());
}
};
} // namespace lib_syntax