移除冗余层次,语法规则解析直出语法结构
This commit is contained in:
parent
fc1e13b74d
commit
c8fedda85b
|
@ -23,37 +23,29 @@ QString NovelParser::version() const
|
|||
}
|
||||
|
||||
std::shared_ptr<const ast_gen::ElementAccess> NovelParser::parse(const QFileInfoList source_list) const {
|
||||
QList<std::shared_ptr<const ast_basic::TokenNode>> forst_root;
|
||||
QList<std::shared_ptr<const ast_basic::Expression>> forst_root;
|
||||
auto lex_reader = NovalSyntax::getLexReader();
|
||||
auto context = std::make_shared<ast_gen::GlobalElement>(u8"С˵");
|
||||
|
||||
auto time_stamp = QTime::currentTime();
|
||||
for (auto& file : source_list) {
|
||||
auto tokens = lex_reader->extractFrom(file.canonicalFilePath());
|
||||
auto exprs_result = std::make_shared<lib_syntax::ExprsChecker>(this->syntax_defines)->parseFrom(tokens);
|
||||
auto exprs_result = this->syntax_defines->parse(context, tokens);
|
||||
forst_root.append(exprs_result);
|
||||
}
|
||||
auto current_stamp = QTime::currentTime();
|
||||
qDebug() << QString(u8"词法解析+语法解析消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp));
|
||||
|
||||
|
||||
std::function<QList<std::shared_ptr<const ast_basic::ExprNode>>(QList<std::shared_ptr<const ast_basic::TokenNode>> input)> summary =
|
||||
[&](QList<std::shared_ptr<const ast_basic::TokenNode>> input) -> QList<std::shared_ptr<const ast_basic::ExprNode>> {
|
||||
QList<std::shared_ptr<const ast_basic::ExprNode>> temp;
|
||||
|
||||
if (input.size()) {
|
||||
auto item = std::dynamic_pointer_cast<const ast_basic::ExprNode>(input.first());
|
||||
temp << item;
|
||||
temp.append(summary(input.mid(1)));
|
||||
}
|
||||
|
||||
return temp;
|
||||
};
|
||||
|
||||
time_stamp = QTime::currentTime();
|
||||
auto tree_visit = std::make_shared<example_novel::NovelExprsVisitor>();
|
||||
auto vinst = std::make_shared<ast_gen::ExprTreeParser>(tree_visit);
|
||||
auto resultx = vinst->parse("test", summary(forst_root));
|
||||
auto novel_accesstree = vinst->tidy(resultx);
|
||||
QList<std::shared_ptr<ast_gen::SyntaxElement>> docs_node;
|
||||
for (auto &it : forst_root) {
|
||||
auto xitem = std::dynamic_pointer_cast<const ast_gen::SyntaxElement>(it);
|
||||
docs_node.append(std::const_pointer_cast<ast_gen::SyntaxElement>(xitem));
|
||||
context->addChild(docs_node.last());
|
||||
}
|
||||
|
||||
auto x_root = NovalSyntax::tidy(context, docs_node);
|
||||
auto novel_accesstree = std::make_shared<ast_gen::ElementAccess>(x_root);
|
||||
current_stamp = QTime::currentTime();
|
||||
qDebug() << QString(u8"程序结构重建消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp));
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
class NovelParser
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<const lib_syntax::ExprRule> syntax_defines;
|
||||
std::shared_ptr<const lib_syntax::ExpressionRule> syntax_defines;
|
||||
QList<std::shared_ptr<const lib_parse::CheckProvider>> checker_list;
|
||||
std::shared_ptr<const lib_parse::Analyzer> analyzer_ref;
|
||||
|
||||
|
|
|
@ -4,65 +4,71 @@ using namespace ast_basic;
|
|||
using namespace lib_token;
|
||||
using namespace lib_syntax;
|
||||
|
||||
TokenNodeImpl::TokenNodeImpl(std::shared_ptr<const Token> word) : word_store(word) {}
|
||||
ExpressionElement::ExpressionElement(std::shared_ptr<const lib_syntax::ExpressionRule> bind) : _expr_rule(bind) {}
|
||||
|
||||
QString TokenNodeImpl::filePath() const
|
||||
std::shared_ptr<const lib_syntax::ExpressionRule> ast_basic::ExpressionElement::definedRule() const {
|
||||
return _expr_rule;
|
||||
}
|
||||
|
||||
QString ast_basic::ExpressionElement::filePath() const {
|
||||
if(tokens_bind.size())
|
||||
throw new SyntaxException(u8"InternalError[0x0002]Ò»¸ö¿ÕµÄ·Ç·¨ÎÞЧ½Úµã");
|
||||
|
||||
return tokens_bind.first()->file();
|
||||
}
|
||||
|
||||
void ast_basic::ExpressionElement::tokensReset(const QList<std::shared_ptr<const lib_token::Token>>& list) {
|
||||
this->tokens_bind = list;
|
||||
}
|
||||
|
||||
void ast_basic::ExpressionElement::addToken(std::shared_ptr<const lib_token::Token> token_inst) {
|
||||
this->tokens_bind.append(token_inst);
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const Expression>> ast_basic::ExpressionElement::children() const {
|
||||
return this->children_store;
|
||||
}
|
||||
|
||||
void ast_basic::ExpressionElement::addChild(std::shared_ptr<const Expression> inst) {
|
||||
this->children_store.append(inst);
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const Token>> ExpressionElement::tokens() const {
|
||||
return this->tokens_bind;
|
||||
}
|
||||
|
||||
std::shared_ptr<ast_basic::Expression> ast_basic::ExpressionContext::currentInst() const
|
||||
{
|
||||
return word_store->file();
|
||||
if(expression_stack.size())
|
||||
return expression_stack.last();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool TokenNodeImpl::isLeaf() const { return true; }
|
||||
|
||||
QList<std::shared_ptr<const Token>> TokenNodeImpl::tokens() const { return QList<std::shared_ptr<const lib_token::Token>>() << word_store; }
|
||||
|
||||
std::shared_ptr<const TokenNode> TokenNodeImpl::filledWith(const QList<std::shared_ptr<const TokenNode>>& tokens) const {
|
||||
Q_UNUSED(tokens);
|
||||
throw new lib_syntax::SyntaxException(u8"InternalError[0x0001]不能对TokenNode调用filledWith");
|
||||
}
|
||||
|
||||
ExprNodeImpl::ExprNodeImpl(std::shared_ptr<const lib_syntax::ExprRule> bind) : _expr_rule(bind) {}
|
||||
|
||||
QString ExprNodeImpl::filePath() const
|
||||
void ast_basic::ExpressionContext::pushInst(std::shared_ptr<ast_basic::Expression> current_inst)
|
||||
{
|
||||
auto toks = tokens();
|
||||
if (toks.size())
|
||||
return toks.first()->file();
|
||||
auto exprs = exprNodes();
|
||||
if (exprs.size())
|
||||
return exprs.first()->filePath();
|
||||
|
||||
throw new SyntaxException(u8"InternalError[0x0002]一个空的非法无效节点");
|
||||
if(!expression_stack.size() || expression_stack.last() != current_inst)
|
||||
expression_stack.append(current_inst);
|
||||
}
|
||||
|
||||
bool ExprNodeImpl::isLeaf() const { return false; }
|
||||
|
||||
std::shared_ptr<const ExprRule> ExprNodeImpl::defined() const { return this->_expr_rule; }
|
||||
|
||||
QList<std::shared_ptr<const ExprNode>> ExprNodeImpl::exprNodes() const {
|
||||
QList<std::shared_ptr<const ExprNode>> listret;
|
||||
for (auto& it : children_store)
|
||||
if (!it->isLeaf())
|
||||
listret.append(std::dynamic_pointer_cast<const ExprNode>(it));
|
||||
return listret;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode> > ExprNodeImpl::childTokensMid(int index, int length) const
|
||||
std::shared_ptr<ast_basic::Expression> ast_basic::ExpressionContext::popInst()
|
||||
{
|
||||
if (index >= 0 && length > 0 && index + length <= children_store.size())
|
||||
return children_store.mid(index, length);
|
||||
|
||||
return QList<std::shared_ptr<const TokenNode>>();
|
||||
auto lastx = expression_stack.takeLast();
|
||||
return lastx;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const Token>> ExprNodeImpl::tokens() const {
|
||||
QList<std::shared_ptr<const lib_token::Token>> retlist;
|
||||
for (auto& it : children_store)
|
||||
retlist.append(it->tokens());
|
||||
return retlist;
|
||||
std::shared_ptr<const lib_syntax::BaseRule> ast_basic::ExpressionContext::currentExpressionRule() const {
|
||||
if(rule_stack.size())
|
||||
return rule_stack.last();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const TokenNode> ExprNodeImpl::filledWith(const QList<std::shared_ptr<const TokenNode>>& child_nodes) const {
|
||||
auto vinst = std::make_shared<ExprNodeImpl>(this->_expr_rule);
|
||||
vinst->children_store.append(child_nodes);
|
||||
return vinst;
|
||||
void ast_basic::ExpressionContext::pushExpressionRule(std::shared_ptr<const lib_syntax::BaseRule> inst) {
|
||||
if(!rule_stack.size() || rule_stack.last() != inst)
|
||||
rule_stack.append(inst);
|
||||
}
|
||||
|
||||
std::shared_ptr<const lib_syntax::BaseRule> ast_basic::ExpressionContext::popExpressionRule()
|
||||
{
|
||||
return rule_stack.takeLast();
|
||||
}
|
||||
|
|
|
@ -7,105 +7,102 @@
|
|||
|
||||
namespace ast_basic {
|
||||
// 抽象语法树 ================================================================================================
|
||||
|
||||
/**
|
||||
* @brief 抽象语法树节点/叶节点/词法节点
|
||||
*/
|
||||
class TokenNode {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取文件路径
|
||||
* @return
|
||||
*/
|
||||
virtual QString filePath() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 是否属于叶子节点
|
||||
* @return
|
||||
*/
|
||||
virtual bool isLeaf() const = 0;
|
||||
/**
|
||||
* @brief 获取节点定义包含Token集合
|
||||
* @return
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const lib_token::Token>> tokens() const = 0;
|
||||
/**
|
||||
* @brief 重置节点内子节点
|
||||
* @param tokens
|
||||
* @return
|
||||
*/
|
||||
virtual std::shared_ptr<const TokenNode> filledWith(const QList<std::shared_ptr<const TokenNode>>& child_nodes) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 抽象语法树集合节点/表达式节点
|
||||
*/
|
||||
class ExprNode : public TokenNode {
|
||||
class Expression {
|
||||
public:
|
||||
virtual ~Expression() = default;
|
||||
|
||||
/**
|
||||
* @brief 表达式定义规则
|
||||
* @brief 获取表达式的解析规则
|
||||
* @return
|
||||
*/
|
||||
virtual std::shared_ptr<const lib_syntax::ExprRule> defined() const = 0;
|
||||
/**
|
||||
* @brief 直接子表达式集合
|
||||
* @return
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const ExprNode>> exprNodes() const = 0;
|
||||
virtual std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const = 0;
|
||||
|
||||
//=====================================================
|
||||
/**
|
||||
* @brief 获取TokenNode,以直接子元素计算
|
||||
* @param index 起始元素索引 0起始
|
||||
* @param length 长度
|
||||
* 获取语法节点的源码文件路径.
|
||||
*
|
||||
* \return 文件路径
|
||||
*/
|
||||
virtual QString filePath() const = 0;
|
||||
/**
|
||||
* 获取语法节点关联token序列.
|
||||
*
|
||||
* \return token序列
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const lib_token::Token>> tokens() const = 0;
|
||||
virtual void tokensReset(const QList<std::shared_ptr<const lib_token::Token>> &list) = 0;
|
||||
/**
|
||||
* 解析过程中,向表达式内部添加token实例.
|
||||
*
|
||||
* \param token_inst 实例
|
||||
*/
|
||||
virtual void addToken(std::shared_ptr<const lib_token::Token> token_inst) = 0;
|
||||
|
||||
//=====================================================
|
||||
/**
|
||||
* @brief 子表达式集合
|
||||
* @return
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const TokenNode>> childTokensMid(int index, int length = 1) const = 0;
|
||||
virtual QList<std::shared_ptr<const Expression>> children() const = 0;
|
||||
/**
|
||||
* @brief 添加子表达式.
|
||||
*
|
||||
* \param inst 子表达式实例
|
||||
*/
|
||||
virtual void addChild(std::shared_ptr<const Expression> inst) = 0;
|
||||
};
|
||||
|
||||
|
||||
// 基础语法树构成 ==========================================================================================
|
||||
|
||||
/**
|
||||
* @brief 词法定义节点
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT TokenNodeImpl : public ast_basic::TokenNode {
|
||||
private:
|
||||
std::shared_ptr<const lib_token::Token> word_store;
|
||||
|
||||
public:
|
||||
TokenNodeImpl(std::shared_ptr<const lib_token::Token> word);
|
||||
|
||||
// TokenNode interface
|
||||
public:
|
||||
virtual QString filePath() const override;
|
||||
virtual bool isLeaf() const override;
|
||||
virtual QList<std::shared_ptr<const lib_token::Token>> tokens() const override;
|
||||
virtual std::shared_ptr<const TokenNode> filledWith(const QList<std::shared_ptr<const TokenNode> >& tokens) const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 表达式节点
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT ExprNodeImpl : public ast_basic::ExprNode {
|
||||
class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression,
|
||||
public std::enable_shared_from_this<ExpressionElement> {
|
||||
private:
|
||||
std::shared_ptr<const lib_syntax::ExprRule> _expr_rule;
|
||||
QList<std::shared_ptr<const TokenNode>> children_store;
|
||||
std::shared_ptr<const lib_syntax::ExpressionRule> _expr_rule;
|
||||
QList<std::shared_ptr<const Expression>> children_store;
|
||||
QList<std::shared_ptr<const lib_token::Token>> tokens_bind;
|
||||
|
||||
public:
|
||||
ExprNodeImpl(std::shared_ptr<const lib_syntax::ExprRule> bind);
|
||||
ExpressionElement(std::shared_ptr<const lib_syntax::ExpressionRule> bind);
|
||||
|
||||
// TokenNode interface
|
||||
public:
|
||||
virtual QString filePath() const override;
|
||||
virtual bool isLeaf() const override;
|
||||
virtual QList<std::shared_ptr<const lib_token::Token>> tokens() const override;
|
||||
virtual std::shared_ptr<const TokenNode> filledWith(const QList<std::shared_ptr<const TokenNode> >& child_nodes) const override;
|
||||
// 通过 Expression 继承
|
||||
std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const override;
|
||||
|
||||
QString filePath() const override;
|
||||
|
||||
QList<std::shared_ptr<const lib_token::Token>> tokens() const override;
|
||||
|
||||
void tokensReset(const QList<std::shared_ptr<const lib_token::Token>>& list) override;
|
||||
|
||||
void addToken(std::shared_ptr<const lib_token::Token> token_inst) override;
|
||||
|
||||
QList<std::shared_ptr<const Expression>> children() const override;
|
||||
|
||||
void addChild(std::shared_ptr<const Expression> inst) override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT ExpressionContext : public lib_syntax::ParseContext, public std::enable_shared_from_this<ExpressionContext> {
|
||||
private:
|
||||
QList<std::shared_ptr<const lib_syntax::BaseRule>> rule_stack;
|
||||
QList<std::shared_ptr<Expression>> expression_stack;
|
||||
|
||||
// ExprNode interface
|
||||
public:
|
||||
virtual std::shared_ptr<const lib_syntax::ExprRule> defined() const override;
|
||||
virtual QList<std::shared_ptr<const ExprNode>> exprNodes() const override;
|
||||
virtual QList<std::shared_ptr<const TokenNode> > childTokensMid(int index, int length) const override;
|
||||
ExpressionContext(){}
|
||||
|
||||
|
||||
// 通过 ParseContext 继承
|
||||
std::shared_ptr<ast_basic::Expression> currentInst() const override;
|
||||
void pushInst(std::shared_ptr<ast_basic::Expression> current_inst) override;
|
||||
std::shared_ptr<ast_basic::Expression> popInst() override;
|
||||
|
||||
std::shared_ptr<const lib_syntax::BaseRule> currentExpressionRule() const override;
|
||||
void pushExpressionRule(std::shared_ptr<const lib_syntax::BaseRule> inst) override;
|
||||
std::shared_ptr<const lib_syntax::BaseRule> popExpressionRule() override;
|
||||
|
||||
};
|
||||
}
|
|
@ -2,105 +2,27 @@
|
|||
|
||||
using namespace ast_gen;
|
||||
|
||||
ExprTreeParser::ExprTreeParser(std::shared_ptr<const ExprVisitor> vistor) : visitor_store(vistor) {}
|
||||
GlobalElement* GlobalElement::UniquePtr = nullptr;
|
||||
|
||||
typedef std::shared_ptr<const SyntaxElement> E;
|
||||
typedef QList<std::shared_ptr<const SyntaxElement>> Es;
|
||||
typedef std::shared_ptr<const ast_basic::ExprNode> Expr;
|
||||
|
||||
QList<std::shared_ptr<const SyntaxElement>> ExprTreeParser::parse(const QString& name,
|
||||
const QList<std::shared_ptr<const ast_basic::ExprNode>>& forest) const {
|
||||
std::function<Es(Expr, E)> visit_loop = [&](Expr n, E p) -> Es {
|
||||
QList<std::shared_ptr<const SyntaxElement>> temp_list;
|
||||
auto node = this->visitor_store->visit(n, p);
|
||||
if (node)
|
||||
temp_list.append(node);
|
||||
|
||||
for (auto& it : n->exprNodes()) {
|
||||
temp_list.append(visit_loop(it, node));
|
||||
}
|
||||
|
||||
return temp_list;
|
||||
};
|
||||
|
||||
QList<std::shared_ptr<const SyntaxElement>> temp_list;
|
||||
auto root = std::make_shared<GlobalElement>(name);
|
||||
temp_list << root;
|
||||
|
||||
for (auto& tree : forest) {
|
||||
temp_list.append(visit_loop(tree, root));
|
||||
}
|
||||
|
||||
return temp_list;
|
||||
GlobalElement::GlobalElement(const QString& name) :names_store(name) {
|
||||
UniquePtr = this;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ElementAccess> ExprTreeParser::tidy(const QList<std::shared_ptr<const SyntaxElement>>& nodes) const {
|
||||
auto temp = nodes.first();
|
||||
while (temp->parent()) {
|
||||
temp = temp->parent();
|
||||
}
|
||||
|
||||
auto core_cache = std::static_pointer_cast<GlobalElement>(std::const_pointer_cast<SyntaxElement>(temp));
|
||||
core_cache->clearCache();
|
||||
for (auto& it : nodes) {
|
||||
if (!it->isAnonymous()) {
|
||||
core_cache->appendToCache(it);
|
||||
}
|
||||
}
|
||||
|
||||
auto root = std::make_shared<ElementAccess>(temp);
|
||||
for (auto& node : nodes)
|
||||
tidy_branch(root, node);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void ExprTreeParser::tidy_branch(std::shared_ptr<ElementAccess> root, std::shared_ptr<const SyntaxElement> node) const {
|
||||
QList<std::shared_ptr<const SyntaxElement>> link;
|
||||
while (node) {
|
||||
link.prepend(node);
|
||||
node = node->parent();
|
||||
}
|
||||
|
||||
std::function<void(std::shared_ptr<ElementAccess> pnode, QList<std::shared_ptr<const SyntaxElement>>)> merge =
|
||||
[&](std::shared_ptr<ElementAccess> pnode, QList<std::shared_ptr<const SyntaxElement>> remains) {
|
||||
if (!remains.size())
|
||||
return;
|
||||
|
||||
auto current = remains.first();
|
||||
for (auto& c_a : pnode->children()) {
|
||||
if (c_a->element() == current) {
|
||||
merge(std::const_pointer_cast<ElementAccess>(c_a), remains.mid(1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto new_branch = std::make_shared<ElementAccess>(current);
|
||||
pnode->appendChild(new_branch);
|
||||
if (remains.size() > 1)
|
||||
merge(new_branch, remains.mid(1));
|
||||
};
|
||||
|
||||
merge(root, link.mid(1));
|
||||
}
|
||||
|
||||
GlobalElement::GlobalElement(const QString& name) :names_store(name) {}
|
||||
|
||||
void GlobalElement::clearCache() { node_cache.clear(); }
|
||||
|
||||
void GlobalElement::appendToCache(std::shared_ptr<const SyntaxElement> named_node) {
|
||||
auto mixed_key = QString(u8"%1<%2>").arg(named_node->signature()).arg(named_node->typeMark());
|
||||
if (node_cache.contains(mixed_key))
|
||||
throw new lib_syntax::SyntaxException(
|
||||
QString(u8"Parse[0x0004]系统中包含同类型重名命名节点:%1<type:%2>").arg(named_node->signature()).arg(named_node->typeMark()));
|
||||
node_cache[mixed_key] = named_node;
|
||||
auto mixed_key = QString(u8"%1<%2>").arg(named_node->signature()).arg(named_node->typeMark());
|
||||
if (node_cache.contains(mixed_key))
|
||||
throw new lib_syntax::SyntaxException(
|
||||
QString(u8"Parse[0x0004]系统中包含同类型重名命名节点:%1<type:%2>").arg(named_node->signature()).arg(named_node->typeMark()));
|
||||
node_cache[mixed_key] = named_node;
|
||||
}
|
||||
|
||||
std::shared_ptr<const SyntaxElement> GlobalElement::getNamedNodeBy(int type, const QString& signature) const {
|
||||
auto mixed_key = QString(u8"%1<%2>").arg(signature).arg(type);
|
||||
if (!node_cache.contains(mixed_key))
|
||||
throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0005]系统中不包含指定签名的节点:%1<type:%2>").arg(signature).arg(type));
|
||||
return node_cache[mixed_key];
|
||||
auto mixed_key = QString(u8"%1<%2>").arg(signature).arg(type);
|
||||
if (!node_cache.contains(mixed_key))
|
||||
throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0005]系统中不包含指定签名的节点:%1<type:%2>").arg(signature).arg(type));
|
||||
return node_cache[mixed_key];
|
||||
}
|
||||
|
||||
int GlobalElement::typeMark() const { return 0; }
|
||||
|
@ -113,28 +35,42 @@ QString GlobalElement::path() const { return u8""; }
|
|||
|
||||
std::shared_ptr<const SyntaxElement> GlobalElement::parent() const { return nullptr; }
|
||||
|
||||
void ast_gen::GlobalElement::setParent(std::shared_ptr<const SyntaxElement> inst) {}
|
||||
|
||||
QList<std::shared_ptr<const TokenAccess>> GlobalElement::selfTokens() const { return QList<std::shared_ptr<const TokenAccess>>(); }
|
||||
|
||||
std::shared_ptr<const ast_basic::Expression> ast_gen::GlobalElement::bindExpression() const
|
||||
{
|
||||
return bind_exprs;
|
||||
}
|
||||
|
||||
void GlobalElement::addChild(std::shared_ptr<ast_gen::SyntaxElement> citem) {
|
||||
auto convx = std::dynamic_pointer_cast<ast_basic::Expression>(citem);
|
||||
bind_exprs->addChild(convx);
|
||||
}
|
||||
|
||||
ElementAccess::ElementAccess(std::shared_ptr<const SyntaxElement> point) { peers = point; }
|
||||
|
||||
std::shared_ptr<const SyntaxElement> ElementAccess::element() const { return peers; }
|
||||
|
||||
QList<std::shared_ptr<const ElementAccess>> ElementAccess::children() const { return children_store; }
|
||||
QList<std::shared_ptr<const ElementAccess>> ElementAccess::children() const {
|
||||
auto expression_inst = element()->bindExpression();
|
||||
auto children = expression_inst->children();
|
||||
|
||||
void ElementAccess::appendChild(std::shared_ptr<const ElementAccess> inst) { children_store.append(inst); }
|
||||
QList<std::shared_ptr<const ElementAccess>> retvalues;
|
||||
for (auto item : children) {
|
||||
auto elem_inst = std::dynamic_pointer_cast<const SyntaxElement>(item);
|
||||
retvalues.append(std::make_shared<ElementAccess>(elem_inst));
|
||||
}
|
||||
return retvalues;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenAccess>> ElementAccess::tokens() const {
|
||||
QList<std::shared_ptr<const TokenAccess>> tokens_retv;
|
||||
tokens_retv.append(element()->selfTokens());
|
||||
for (auto& it : children()) {
|
||||
tokens_retv.append(it->tokens());
|
||||
}
|
||||
|
||||
return tokens_retv;
|
||||
return element()->selfTokens();
|
||||
}
|
||||
|
||||
TokenAccess::TokenAccess(std::shared_ptr<const SyntaxElement> elm_inst, std::shared_ptr<const lib_token::Token> token_inst)
|
||||
: element_bind(elm_inst), token_store(token_inst) {}
|
||||
: element_bind(elm_inst), token_store(token_inst) {}
|
||||
|
||||
std::shared_ptr<const SyntaxElement> TokenAccess::bind() const { return element_bind; }
|
||||
|
||||
|
|
|
@ -15,6 +15,14 @@ namespace ast_gen
|
|||
*/
|
||||
class SyntaxElement {
|
||||
public:
|
||||
virtual ~SyntaxElement() = default;
|
||||
/**
|
||||
* 绑定表达式实体.
|
||||
*
|
||||
* \return 表达式实例
|
||||
*/
|
||||
virtual std::shared_ptr<const ast_basic::Expression> bindExpression() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 类型标记
|
||||
* @return
|
||||
|
@ -42,9 +50,10 @@ namespace ast_gen
|
|||
|
||||
/**
|
||||
* @brief 获取父元素
|
||||
* @return
|
||||
* @return 未设置parent,返回nullptr
|
||||
*/
|
||||
virtual std::shared_ptr<const SyntaxElement> parent() const = 0;
|
||||
virtual void setParent(std::shared_ptr<const SyntaxElement> inst) = 0;
|
||||
|
||||
/**
|
||||
* @brief 定义元素自身的Token集合
|
||||
|
@ -59,7 +68,6 @@ namespace ast_gen
|
|||
class LIBSYNTAX_EXPORT ElementAccess {
|
||||
private:
|
||||
std::shared_ptr<const SyntaxElement> peers;
|
||||
QList<std::shared_ptr<const ElementAccess>> children_store;
|
||||
|
||||
public:
|
||||
ElementAccess(std::shared_ptr<const SyntaxElement> point);
|
||||
|
@ -67,8 +75,6 @@ namespace ast_gen
|
|||
std::shared_ptr<const SyntaxElement> element() const;
|
||||
|
||||
QList<std::shared_ptr<const ElementAccess>> children() const;
|
||||
void appendChild(std::shared_ptr<const ElementAccess> inst);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取该元素下所有Token定义
|
||||
|
@ -91,13 +97,15 @@ namespace ast_gen
|
|||
/**
|
||||
* @brief 根元素定义
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement {
|
||||
class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement, public ast_basic::ExpressionContext {
|
||||
private:
|
||||
QList<std::shared_ptr<const SyntaxElement>> children_store;
|
||||
QString names_store;
|
||||
QHash<QString, std::shared_ptr<const SyntaxElement>> node_cache;
|
||||
|
||||
std::shared_ptr<ast_basic::Expression> bind_exprs = std::make_shared<ast_basic::ExpressionElement>(nullptr);
|
||||
|
||||
public:
|
||||
static GlobalElement* UniquePtr;
|
||||
GlobalElement(const QString& name);
|
||||
|
||||
virtual void clearCache();
|
||||
|
@ -110,6 +118,8 @@ namespace ast_gen
|
|||
*/
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> getNamedNodeBy(int type, const QString& signature) const;
|
||||
|
||||
virtual void addChild(std::shared_ptr<ast_gen::SyntaxElement> citem);
|
||||
|
||||
// ParseElement interface
|
||||
public:
|
||||
virtual int typeMark() const override;
|
||||
|
@ -117,47 +127,10 @@ namespace ast_gen
|
|||
virtual QString signature() const override;
|
||||
virtual QString path() const override;
|
||||
virtual std::shared_ptr<const SyntaxElement> parent() const override;
|
||||
virtual void setParent(std::shared_ptr<const SyntaxElement> inst) override;
|
||||
virtual QList<std::shared_ptr<const TokenAccess>> selfTokens() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 语法树节点访问器
|
||||
*/
|
||||
class ExprVisitor {
|
||||
public:
|
||||
/**
|
||||
* @brief 解析表达式节点,转换成语法元素实体
|
||||
* @param expr 表达式节点
|
||||
* @param pnode 父节点
|
||||
* @return 该节点转换成的语法元素节点
|
||||
*/
|
||||
virtual std::shared_ptr<const SyntaxElement> visit(std::shared_ptr<const ast_basic::ExprNode> expr, std::shared_ptr<const SyntaxElement> pnode) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 抽象语法树解析器
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT ExprTreeParser {
|
||||
private:
|
||||
std::shared_ptr<const ExprVisitor> visitor_store;
|
||||
void tidy_branch(std::shared_ptr<ElementAccess> root, std::shared_ptr<const SyntaxElement> node) const;
|
||||
|
||||
public:
|
||||
ExprTreeParser(std::shared_ptr<const ExprVisitor> vistor);
|
||||
|
||||
/**
|
||||
* @brief 解析语法内容,生成倒立语法树
|
||||
* @param name 生成产物名称
|
||||
* @param forest 表达式森林,全部的表达式树
|
||||
* @return 语法树的所有叶子节点
|
||||
*/
|
||||
QList<std::shared_ptr<const SyntaxElement>> parse(const QString& name, const QList<std::shared_ptr<const ast_basic::ExprNode>>& forest) const;
|
||||
|
||||
/**
|
||||
* @brief 整理语法树节点,生成语法元素访问树
|
||||
* @param nodes
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<const ElementAccess> tidy(const QList<std::shared_ptr<const SyntaxElement>>& nodes) const;
|
||||
// 通过 SyntaxElement 继承
|
||||
std::shared_ptr<const ast_basic::Expression> bindExpression() const override;
|
||||
};
|
||||
}
|
|
@ -3,245 +3,151 @@
|
|||
|
||||
using namespace example_novel;
|
||||
|
||||
TextSection::TextSection(const QString& text, const QString path, std::shared_ptr<const SyntaxElement> parent)
|
||||
: content_store(text), file_path(path), pnode_store(parent) {}
|
||||
TextSection::TextSection(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
QString example_novel::TextSection::content() const
|
||||
{
|
||||
return this->content_store;
|
||||
QString text;
|
||||
for (auto& t : selfTokens()) {
|
||||
text += t->token()->content() + " ";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
int TextSection::typeMark() const { return (int)NovelNode::TextSection; }
|
||||
|
||||
bool example_novel::TextSection::isAnonymous() const
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString TextSection::path() const { return file_path; }
|
||||
|
||||
QString TextSection::signature() const { return u8"::section"; }
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> TextSection::parent() const { return pnode_store; }
|
||||
FragmentRefers::FragmentRefers(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > TextSection::selfTokens() const {
|
||||
return TokenSL::selfTokens();
|
||||
}
|
||||
QString FragmentRefers::storyRefer() const { return selfTokens()[5]->token()->content(); }
|
||||
|
||||
FragmentRefers::FragmentRefers(const QString& story, const QString& fragment, const QString& path, std::shared_ptr<const SyntaxElement> parent)
|
||||
: story_ref(story), fragm_ref(fragment), path_store(path), pnode_store(parent) {}
|
||||
|
||||
QString FragmentRefers::storyRefer() const { return story_ref; }
|
||||
|
||||
QString FragmentRefers::fragmentRefer() const { return fragm_ref; }
|
||||
QString FragmentRefers::fragmentRefer() const { return selfTokens()[3]->token()->content(); }
|
||||
|
||||
QString FragmentRefers::referSignature() const {
|
||||
return story_ref + u8"&" + fragm_ref;
|
||||
return storyRefer() + u8"&" + fragmentRefer();
|
||||
}
|
||||
|
||||
int FragmentRefers::typeMark() const { return (int)NovelNode::FragmentRefer; }
|
||||
|
||||
bool example_novel::FragmentRefers::isAnonymous() const
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString FragmentRefers::path() const { return path_store; }
|
||||
|
||||
QString FragmentRefers::signature() const {
|
||||
QString signature = u8"@" + storyRefer() + u8"&" + fragmentRefer();
|
||||
return parent()->signature() + signature;
|
||||
QString signature = u8"@" + storyRefer() + u8"&" + fragmentRefer();
|
||||
return parent()->signature() + signature;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> FragmentRefers::parent() const { return pnode_store; }
|
||||
FragmentDefine::FragmentDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > FragmentRefers::selfTokens() const {
|
||||
return TokenSL::selfTokens();
|
||||
}
|
||||
|
||||
FragmentDefine::FragmentDefine(const QString& name, const QString& path, std::shared_ptr<const SyntaxElement> parent)
|
||||
: name_store(name), path_store(path), pnode_store(parent) {}
|
||||
|
||||
QString FragmentDefine::name() const { return name_store; }
|
||||
QString FragmentDefine::name() const { return selfTokens()[2]->token()->content(); }
|
||||
|
||||
int FragmentDefine::typeMark() const { return (int)NovelNode::FragmentDefine; }
|
||||
|
||||
bool example_novel::FragmentDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString FragmentDefine::path() const { return path_store; }
|
||||
|
||||
QString FragmentDefine::signature() const { return parent()->signature() + u8"&" + name(); }
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> FragmentDefine::parent() const { return pnode_store; }
|
||||
StoryDefine::StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > FragmentDefine::selfTokens() const {
|
||||
return TokenSL::selfTokens();
|
||||
}
|
||||
QString StoryDefine::name() const { return selfTokens()[3]->token()->content(); }
|
||||
|
||||
StoryDefine::StoryDefine(const QString name, int sort, const QString path, std::shared_ptr<const SyntaxElement> parent)
|
||||
: name_store(name), sort_index(sort), path_store(path), pnode_store(parent) {}
|
||||
|
||||
QString StoryDefine::name() const { return name_store; }
|
||||
|
||||
int StoryDefine::sort() const { return sort_index; }
|
||||
int StoryDefine::sort() const { return selfTokens()[2]->token()->content().toInt(); }
|
||||
|
||||
int StoryDefine::typeMark() const { return (int)NovelNode::StoryDefine; }
|
||||
|
||||
bool example_novel::StoryDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString StoryDefine::path() const { return path_store; }
|
||||
|
||||
QString StoryDefine::signature() const { return name_store; }
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> StoryDefine::parent() const { return pnode_store; }
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > StoryDefine::selfTokens() const {
|
||||
return TokenSL::selfTokens();
|
||||
}
|
||||
QString StoryDefine::signature() const { return name(); }
|
||||
|
||||
#include "syntax_novel.h"
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> NovelExprsVisitor::visit(std::shared_ptr<const ast_basic::ExprNode> expr, std::shared_ptr<const ast_gen::SyntaxElement> pnode) const
|
||||
{
|
||||
auto tidy_tokens = [&](std::shared_ptr<const ast_basic::ExprNode> expr) {
|
||||
auto vtokens = expr->tokens();
|
||||
for (auto& cld : expr->exprNodes()) {
|
||||
auto remove_tokens = cld->tokens();
|
||||
for (auto& rit : remove_tokens)
|
||||
vtokens.removeAll(rit);
|
||||
}
|
||||
return vtokens;
|
||||
};
|
||||
|
||||
switch (expr->defined()->typeMark()) {
|
||||
case example_novel::NovelExprs::DOC_DEFINES:
|
||||
return std::make_shared<Document>(expr->filePath(), pnode);
|
||||
case example_novel::NovelExprs::STORY_DEFINES: {
|
||||
auto name = expr->tokens().at(3)->content();
|
||||
auto sort = expr->tokens().at(2)->content().toInt();
|
||||
|
||||
auto rinst = std::make_shared<StoryDefine>(name, sort, expr->filePath(), pnode);
|
||||
rinst->appendDefinedTokens(rinst, tidy_tokens(expr));
|
||||
return rinst;
|
||||
}
|
||||
case example_novel::NovelExprs::FRAG_DEFINES: {
|
||||
auto name = expr->tokens().at(2)->content();
|
||||
auto inst = std::make_shared<FragmentDefine>(name, expr->filePath(), pnode);
|
||||
inst->appendDefinedTokens(inst, tidy_tokens(expr));
|
||||
return inst;
|
||||
}
|
||||
case example_novel::NovelExprs::FRAG_REFERS: {
|
||||
auto fragm_ref = expr->tokens().at(3)->content();
|
||||
auto story_ref = expr->tokens().at(5)->content();
|
||||
auto inst = std::make_shared<FragmentRefers>(story_ref, fragm_ref, expr->filePath(), pnode);
|
||||
inst->appendDefinedTokens(inst, tidy_tokens(expr));
|
||||
return inst;
|
||||
}
|
||||
case example_novel::NovelExprs::DESC_SECTION:
|
||||
{
|
||||
QString content = u8"";
|
||||
for (auto& t : expr->tokens())
|
||||
content += t->content();
|
||||
auto inst = std::make_shared<TextSection>(content, expr->filePath(), pnode);
|
||||
inst->appendDefinedTokens(inst, tidy_tokens(expr));
|
||||
return inst;
|
||||
}
|
||||
case example_novel::NovelExprs::ARTICLE_DEFINE:
|
||||
{
|
||||
auto name = expr->tokens().at(2)->content();
|
||||
auto inst = std::make_shared<ArticleDefine>(name, expr->filePath(), pnode);
|
||||
inst->appendDefinedTokens(inst, tidy_tokens(expr));
|
||||
return inst;
|
||||
}
|
||||
case example_novel::NovelExprs::VOLUME_DEFINE:
|
||||
{
|
||||
auto name = expr->tokens().at(2)->content();
|
||||
auto inst = std::make_shared<VolumeDefine>(name, expr->filePath(), pnode);
|
||||
inst->appendDefinedTokens(inst, tidy_tokens(expr));
|
||||
return inst;
|
||||
}
|
||||
default:
|
||||
throw new lib_syntax::SyntaxException(u8"InternalError[0x0003]ÀàÐÍÆ¥Åä´íÎó");
|
||||
}
|
||||
}
|
||||
|
||||
Document::Document(const QString& path, std::shared_ptr<const SyntaxElement> pnode)
|
||||
: path_store(path), pnode_store(pnode) {}
|
||||
Document::Document(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
int Document::typeMark() const { return (int)NovelNode::Document; }
|
||||
|
||||
bool example_novel::Document::isAnonymous() const
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Document::path() const { return path_store; }
|
||||
|
||||
QString Document::signature() const { return QString(u8"::document<%1>").arg(path()); }
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> Document::parent() const { return pnode_store; }
|
||||
example_novel::AbstractImpl::AbstractImpl(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: ExpressionElement(rule_bind) {}
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > Document::selfTokens() const
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > AbstractImpl::selfTokens() const {
|
||||
auto tokensx = ast_basic::ExpressionElement::tokens();
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess>> values;
|
||||
for (auto xit : tokensx) {
|
||||
values.append(std::make_shared<ast_gen::TokenAccess>(std::dynamic_pointer_cast<const ast_gen::SyntaxElement>(shared_from_this()), xit));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> example_novel::AbstractImpl::parent() const
|
||||
{
|
||||
return QList<std::shared_ptr<const ast_gen::TokenAccess>>();
|
||||
return this->parent_store;
|
||||
}
|
||||
|
||||
void TokenSL::appendDefinedTokens(std::shared_ptr<const ast_gen::SyntaxElement> elm, QList<std::shared_ptr<const lib_token::Token>> tokens) {
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess>> access;
|
||||
for (auto& t : tokens)
|
||||
this->tokens_store << std::make_shared<ast_gen::TokenAccess>(elm, t);
|
||||
void example_novel::AbstractImpl::setParent(std::shared_ptr<const ast_gen::SyntaxElement> inst)
|
||||
{
|
||||
this->parent_store = inst;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > TokenSL::selfTokens() const {
|
||||
return tokens_store;
|
||||
|
||||
// ͨ¹ý SyntaxElement ¼Ì³Ð
|
||||
std::shared_ptr<const ast_basic::Expression> example_novel::AbstractImpl::bindExpression() const {
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
VolumeDefine::VolumeDefine(const QString& name, const QString& path, std::shared_ptr<const SyntaxElement> parent)
|
||||
: name_store(name), path_store(path), pnode_store(parent) {}
|
||||
QString example_novel::AbstractImpl::path() const
|
||||
{
|
||||
return ast_basic::ExpressionElement::filePath();
|
||||
}
|
||||
|
||||
QString VolumeDefine::name() const { return name_store; }
|
||||
VolumeDefine::VolumeDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
QString VolumeDefine::name() const { return selfTokens()[2]->token()->content(); }
|
||||
|
||||
int VolumeDefine::typeMark() const { return (int)NovelNode::VolumeDefine; }
|
||||
|
||||
bool example_novel::VolumeDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString VolumeDefine::path() const { return path_store; }
|
||||
|
||||
QString VolumeDefine::signature() const { return name(); }
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> VolumeDefine::parent() const { return pnode_store; }
|
||||
ArticleDefine::ArticleDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > VolumeDefine::selfTokens() const {
|
||||
return TokenSL::selfTokens();
|
||||
}
|
||||
|
||||
ArticleDefine::ArticleDefine(const QString& name, const QString& path, std::shared_ptr<const SyntaxElement> parent)
|
||||
: name_store(name), path_store(path), pnode_store(parent) {}
|
||||
|
||||
QString ArticleDefine::name() const { return name_store; }
|
||||
QString ArticleDefine::name() const { return selfTokens()[2]->token()->content(); }
|
||||
|
||||
int ArticleDefine::typeMark() const { return (int)NovelNode::ArticleDefine; }
|
||||
|
||||
bool example_novel::ArticleDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ArticleDefine::path() const { return path_store; }
|
||||
|
||||
QString ArticleDefine::signature() const { return parent()->signature() + u8"&" + name(); }
|
||||
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> ArticleDefine::parent() const { return pnode_store; }
|
||||
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess> > ArticleDefine::selfTokens() const {
|
||||
return TokenSL::selfTokens();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,24 +14,26 @@ namespace example_novel
|
|||
VolumeDefine = 7,
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT TokenSL {
|
||||
class LIBSYNTAX_EXPORT AbstractImpl :
|
||||
public ast_basic::ExpressionElement, public ast_gen::SyntaxElement {
|
||||
private:
|
||||
QList<std::shared_ptr<const ast_gen::TokenAccess>> tokens_store;
|
||||
std::shared_ptr<const SyntaxElement> parent_store = nullptr;
|
||||
|
||||
public:
|
||||
virtual void appendDefinedTokens(std::shared_ptr<const ast_gen::SyntaxElement> elm, QList<std::shared_ptr<const lib_token::Token> > tokens);
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess>> selfTokens() const;
|
||||
explicit AbstractImpl(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
// ͨ¹ý SyntaxElement ¼Ì³Ð
|
||||
virtual std::shared_ptr<const ast_basic::Expression> bindExpression() const override;
|
||||
QString path() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual void setParent(std::shared_ptr<const ast_gen::SyntaxElement> inst) override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess>> selfTokens() const override;
|
||||
};
|
||||
|
||||
|
||||
class LIBSYNTAX_EXPORT TextSection : public ast_gen::SyntaxElement, public TokenSL {
|
||||
private:
|
||||
QString content_store;
|
||||
QString file_path;
|
||||
std::shared_ptr<const SyntaxElement> pnode_store;
|
||||
|
||||
class LIBSYNTAX_EXPORT TextSection : public AbstractImpl {
|
||||
public:
|
||||
TextSection(const QString& text, const QString path, std::shared_ptr<const SyntaxElement> parent);
|
||||
TextSection(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString content() const;
|
||||
|
||||
|
@ -39,21 +41,12 @@ namespace example_novel
|
|||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess> > selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT FragmentRefers : public ast_gen::SyntaxElement, public TokenSL {
|
||||
private:
|
||||
QString story_ref;
|
||||
QString fragm_ref;
|
||||
QString path_store;
|
||||
std::shared_ptr<const SyntaxElement> pnode_store;
|
||||
|
||||
class LIBSYNTAX_EXPORT FragmentRefers : public AbstractImpl {
|
||||
public:
|
||||
FragmentRefers(const QString& story, const QString& fragment, const QString& path, std::shared_ptr<const SyntaxElement> parent);
|
||||
FragmentRefers(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString storyRefer() const;
|
||||
QString fragmentRefer() const;
|
||||
|
@ -63,20 +56,12 @@ namespace example_novel
|
|||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess> > selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT FragmentDefine : public ast_gen::SyntaxElement, public TokenSL {
|
||||
private:
|
||||
QString name_store;
|
||||
QString path_store;
|
||||
std::shared_ptr<const SyntaxElement> pnode_store;
|
||||
|
||||
class LIBSYNTAX_EXPORT FragmentDefine : public AbstractImpl {
|
||||
public:
|
||||
FragmentDefine(const QString& name, const QString& path, std::shared_ptr<const SyntaxElement> parent);
|
||||
FragmentDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString name() const;
|
||||
|
||||
|
@ -84,20 +69,12 @@ namespace example_novel
|
|||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess> > selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT ArticleDefine : public ast_gen::SyntaxElement, public TokenSL {
|
||||
private:
|
||||
QString name_store;
|
||||
QString path_store;
|
||||
std::shared_ptr<const SyntaxElement> pnode_store;
|
||||
|
||||
class LIBSYNTAX_EXPORT ArticleDefine : public AbstractImpl{
|
||||
public:
|
||||
ArticleDefine(const QString& name, const QString& path, std::shared_ptr<const SyntaxElement> parent);
|
||||
ArticleDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString name() const;
|
||||
|
||||
|
@ -105,20 +82,12 @@ namespace example_novel
|
|||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess> > selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT VolumeDefine : public ast_gen::SyntaxElement, public TokenSL {
|
||||
private:
|
||||
QString name_store;
|
||||
QString path_store;
|
||||
std::shared_ptr<const SyntaxElement> pnode_store;
|
||||
|
||||
class LIBSYNTAX_EXPORT VolumeDefine : public AbstractImpl {
|
||||
public:
|
||||
VolumeDefine(const QString& name, const QString& path, std::shared_ptr<const SyntaxElement> parent);
|
||||
VolumeDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString name() const;
|
||||
|
||||
|
@ -126,58 +95,31 @@ namespace example_novel
|
|||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess> > selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT StoryDefine : public ast_gen::SyntaxElement, public TokenSL {
|
||||
private:
|
||||
QString name_store;
|
||||
int sort_index;
|
||||
QString path_store;
|
||||
std::shared_ptr<const SyntaxElement> pnode_store;
|
||||
|
||||
class LIBSYNTAX_EXPORT StoryDefine : public AbstractImpl {
|
||||
public:
|
||||
StoryDefine(const QString name, int sort, const QString path, std::shared_ptr<const SyntaxElement> parent);
|
||||
StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString name() const;
|
||||
int sort() const;
|
||||
|
||||
// SyntaxElement interface
|
||||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString signature() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT Document : public AbstractImpl {
|
||||
public:
|
||||
Document(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
// SyntaxElement interface
|
||||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess> > selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT Document : public ast_gen::SyntaxElement {
|
||||
private:
|
||||
QString path_store;
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> pnode_store;
|
||||
|
||||
public:
|
||||
Document(const QString& path, std::shared_ptr<const ast_gen::SyntaxElement> pnode);
|
||||
|
||||
// SyntaxElement interface
|
||||
public:
|
||||
virtual int typeMark() const override;
|
||||
virtual bool isAnonymous() const override;
|
||||
virtual QString path() const override;
|
||||
virtual QString signature() const override;
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> parent() const override;
|
||||
virtual QList<std::shared_ptr<const ast_gen::TokenAccess>> selfTokens() const override;
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT NovelExprsVisitor : public ast_gen::ExprVisitor {
|
||||
|
||||
// ExprVisitor interface
|
||||
public:
|
||||
virtual std::shared_ptr<const ast_gen::SyntaxElement> visit(std::shared_ptr<const ast_basic::ExprNode> expr, std::shared_ptr<const ast_gen::SyntaxElement> pnode) const override;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -19,20 +19,21 @@ std::tuple<BaseRule::MatchResult, uint> TokenMatch::match(const QList<std::share
|
|||
return std::make_tuple(MatchResult::Fail, 0);
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode>> TokenMatch::parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
std::shared_ptr<const Expression> TokenMatch::parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
if (stream.size()) {
|
||||
auto current = stream.first();
|
||||
if (current->define()->name() == define_peer->name())
|
||||
return QList<std::shared_ptr<const ast_basic::TokenNode>>() << std::make_shared<const TokenNodeImpl>(stream.first());
|
||||
if (current->define()->name() == define_peer->name()){
|
||||
rt_inst->currentInst()->addToken(current);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
throw new SyntaxException(
|
||||
QString(u8"Syntax[0x00001]语法匹配错误,不能识别token:%1<%2,%3>").arg(current->content()).arg(current->row()).arg(current->column()));
|
||||
throw new SyntaxException(QString(u8"Syntax[0x00001]语法匹配错误,不能识别token:%1<%2,%3>")
|
||||
.arg(current->content()).arg(current->row()).arg(current->column()));
|
||||
}
|
||||
throw new SyntaxException(u8"Syntax[0x0000]tokenÁ÷ÌáǰÖÕÖ¹");
|
||||
}
|
||||
|
||||
QString TokenMatch::token_present() const
|
||||
{
|
||||
QString TokenMatch::token_present() const {
|
||||
return QString(u8"<%1>").arg(this->define_peer->name());
|
||||
}
|
||||
|
||||
|
@ -70,15 +71,17 @@ std::tuple<BaseRule::MatchResult, uint> Rept::match(const QList<std::shared_ptr<
|
|||
return std::make_tuple(MatchResult::Success, token_offset);
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode>> Rept::parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
QList<std::shared_ptr<const TokenNode>> list_retvs;
|
||||
|
||||
std::shared_ptr<const Expression> Rept::parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
auto token_offset = 0;
|
||||
|
||||
// min-match
|
||||
for (auto idx = 0; idx < min_match; ++idx) {
|
||||
auto result = rule_peer->match(stream.mid(token_offset));
|
||||
|
||||
list_retvs.append(rule_peer->parse(stream.mid(token_offset)));
|
||||
auto result_gen = rule_peer->parse(rt_inst, stream.mid(token_offset));
|
||||
if(result_gen)
|
||||
rt_inst->currentInst()->addChild(result_gen);
|
||||
|
||||
token_offset += std::get<1>(result);
|
||||
}
|
||||
|
||||
|
@ -89,16 +92,19 @@ QList<std::shared_ptr<const TokenNode>> Rept::parse(const QList<std::shared_ptr<
|
|||
switch (std::get<0>(result)) {
|
||||
case MatchResult::Fail:
|
||||
case MatchResult::Part:
|
||||
return list_retvs;
|
||||
return nullptr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
list_retvs.append(rule_peer->parse(stream.mid(token_offset)));
|
||||
auto result_gen = rule_peer->parse(rt_inst, stream.mid(token_offset));
|
||||
if (result_gen)
|
||||
rt_inst->currentInst()->addChild(result_gen);
|
||||
|
||||
token_offset += std::get<1>(result);
|
||||
}
|
||||
|
||||
return list_retvs;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString Rept::token_present() const
|
||||
|
@ -130,18 +136,18 @@ std::tuple<BaseRule::MatchResult, uint> Seqs::match(const QList<std::shared_ptr<
|
|||
return std::make_tuple(MatchResult::Success, token_offset);
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode>> Seqs::parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
QList<std::shared_ptr<const TokenNode>> list_retv;
|
||||
|
||||
std::shared_ptr<const Expression> Seqs::parse(std::shared_ptr<ParseContext> rt_inst,const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
auto token_offset = 0;
|
||||
for (auto& r : mbrs_store) {
|
||||
list_retv.append(r->parse(stream.mid(token_offset)));
|
||||
auto rst_gene = r->parse(rt_inst, stream.mid(token_offset));
|
||||
if(rst_gene)
|
||||
rt_inst->currentInst()->addChild(rst_gene);
|
||||
|
||||
auto result = r->match(stream.mid(token_offset));
|
||||
token_offset += std::get<1>(result);
|
||||
}
|
||||
|
||||
return list_retv;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString Seqs::token_present() const
|
||||
|
@ -190,9 +196,9 @@ std::tuple<BaseRule::MatchResult, uint> Any::match(const QList<std::shared_ptr<c
|
|||
return std::make_tuple(std::get<0>(item), std::get<1>(item));
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode>> Any::parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
std::shared_ptr<const Expression> Any::parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
auto temp = rule_select(stream);
|
||||
return std::get<2>(temp)->parse(stream);
|
||||
return std::get<2>(temp)->parse(rt_inst, stream);
|
||||
}
|
||||
|
||||
QString Any::token_present() const
|
||||
|
@ -204,48 +210,49 @@ QString Any::token_present() const
|
|||
return u8"(" + members_content.mid(0, members_content.size() - 1) + u8")";
|
||||
}
|
||||
|
||||
ExprRule::ExprRule(const QString& rule_name, int expr_mark) : name_store(rule_name) {
|
||||
this->filter_proc = [](const TokenSeqs& seqs) { return seqs; };
|
||||
this->mark_store = expr_mark;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ExprRule> ExprRule::reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule) {
|
||||
auto ninst = std::make_shared<ExprRule>(this->name(), this->typeMark());
|
||||
ninst->child_store = rule;
|
||||
ninst->filter_proc = filter;
|
||||
return ninst;
|
||||
}
|
||||
|
||||
QString ExprRule::name() const { return name_store; }
|
||||
|
||||
int ExprRule::typeMark() const { return this->mark_store; }
|
||||
|
||||
QList<std::shared_ptr<const BaseRule>> ExprRule::children() const { return QList<std::shared_ptr<const BaseRule>>() << this->child_store; }
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint> ExprRule::match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
return child_store->match(stream);
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode>> ExprRule::parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
auto primary_tokens = child_store->parse(stream);
|
||||
auto remains_tokens = this->filter_proc(primary_tokens);
|
||||
return QList<std::shared_ptr<const TokenNode>>() << ExprNodeImpl(shared_from_this()).filledWith(remains_tokens);
|
||||
}
|
||||
|
||||
QString ExprRule::token_present() const
|
||||
{
|
||||
return QString(u8"(%1)").arg(child_store->token_present());
|
||||
}
|
||||
|
||||
SyntaxException::SyntaxException(const QString& message) { this->msg_store = message; }
|
||||
|
||||
QString SyntaxException::message() const { return msg_store; }
|
||||
|
||||
ExprsChecker::ExprsChecker(std::shared_ptr<const ExprRule> parse_tree) : syntax_tree_root(parse_tree) {}
|
||||
|
||||
QList<std::shared_ptr<const TokenNode>> ExprsChecker::parseFrom(const QList<std::shared_ptr<const lib_token::Token>>& all_tokens) {
|
||||
if (!all_tokens.size())
|
||||
return QList<std::shared_ptr<const TokenNode>>();
|
||||
|
||||
return this->syntax_tree_root->parse(all_tokens);
|
||||
lib_syntax::ExpressionRule::ExpressionRule(const QString& rule_name, int expr_mark) : name_store(rule_name) {
|
||||
this->filter_proc = [](const TokenSeqs& seqs) { return seqs; };
|
||||
this->mark_store = expr_mark;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ExpressionRule> lib_syntax::ExpressionRule::reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule) {
|
||||
auto ninst = makeCopy();
|
||||
ninst->child_store = rule;
|
||||
ninst->filter_proc = filter;
|
||||
return ninst;
|
||||
}
|
||||
|
||||
QString lib_syntax::ExpressionRule::name() const { return name_store; }
|
||||
|
||||
int lib_syntax::ExpressionRule::typeMark() const { return this->mark_store; }
|
||||
|
||||
QList<std::shared_ptr<const lib_syntax::BaseRule>> lib_syntax::ExpressionRule::children() const {
|
||||
return QList<std::shared_ptr<const BaseRule>>() << this->child_store;
|
||||
}
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint> lib_syntax::ExpressionRule::match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
return child_store->match(stream);
|
||||
}
|
||||
|
||||
std::shared_ptr<const ast_basic::Expression> lib_syntax::ExpressionRule::parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const {
|
||||
std::shared_ptr<ast_basic::Expression> elm_ast = this->newEmptyInstance();
|
||||
|
||||
rt_inst->pushExpressionRule(this->shared_from_this());
|
||||
rt_inst->pushInst(elm_ast);
|
||||
|
||||
child_store->parse(rt_inst, stream);
|
||||
auto tokens_decl = this->filter_proc(elm_ast->tokens());
|
||||
elm_ast->tokensReset(tokens_decl);
|
||||
|
||||
rt_inst->popExpressionRule();
|
||||
return rt_inst->popInst();
|
||||
}
|
||||
|
||||
QString lib_syntax::ExpressionRule::token_present() const {
|
||||
return QString(u8"(%1)").arg(child_store->token_present());
|
||||
}
|
||||
|
|
|
@ -5,182 +5,215 @@
|
|||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
|
||||
namespace ast_basic {
|
||||
class TokenNode;
|
||||
class ExprNode;
|
||||
class Expression;
|
||||
class ExpressionElement;
|
||||
}
|
||||
|
||||
namespace lib_syntax {
|
||||
/**
|
||||
* @brief 语法异常
|
||||
*/
|
||||
class SyntaxException {
|
||||
private:
|
||||
QString msg_store;
|
||||
/**
|
||||
* @brief 语法异常
|
||||
*/
|
||||
class SyntaxException {
|
||||
private:
|
||||
QString msg_store;
|
||||
|
||||
public:
|
||||
SyntaxException(const QString& message);
|
||||
virtual ~SyntaxException() = default;
|
||||
public:
|
||||
SyntaxException(const QString& message);
|
||||
virtual ~SyntaxException() = default;
|
||||
|
||||
virtual QString message() const;
|
||||
};
|
||||
virtual QString message() const;
|
||||
};
|
||||
|
||||
// 基础语法解析接口 ===================================================================================================
|
||||
/**
|
||||
* @brief 基础语法匹配规则接口
|
||||
*/
|
||||
class BaseRule {
|
||||
public:
|
||||
/**
|
||||
* @brief 子规则
|
||||
* @return
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 匹配结果
|
||||
*/
|
||||
enum class MatchResult {
|
||||
Success, // 符合匹配条件
|
||||
Part, // 部分匹配
|
||||
Fail // 从第一个词起完全不匹配
|
||||
};
|
||||
class BaseRule;
|
||||
// 基础语法解析接口 ===================================================================================================
|
||||
/**
|
||||
* @brief 解析上下文接口
|
||||
*/
|
||||
class ParseContext {
|
||||
public:
|
||||
virtual ~ParseContext() = default;
|
||||
|
||||
/**
|
||||
* @brief token流匹配
|
||||
* @return 首部对齐,匹配token集合
|
||||
*/
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const = 0;
|
||||
/**
|
||||
* \brief 当前表达式元素.
|
||||
*
|
||||
* \return 返回当前表达式
|
||||
*/
|
||||
virtual std::shared_ptr<ast_basic::Expression> currentInst() const = 0;
|
||||
virtual void pushInst(std::shared_ptr<ast_basic::Expression> current_inst) = 0;
|
||||
virtual std::shared_ptr<ast_basic::Expression> popInst() = 0;
|
||||
|
||||
/**
|
||||
* @brief 解析
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const ast_basic::TokenNode>> parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const = 0;
|
||||
virtual std::shared_ptr<const BaseRule> currentExpressionRule() const = 0;
|
||||
virtual void pushExpressionRule(std::shared_ptr<const BaseRule> inst) = 0;
|
||||
virtual std::shared_ptr<const BaseRule> popExpressionRule() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 返回匹配语法规则的词法序列表达
|
||||
*
|
||||
* \return 词法表达序列
|
||||
*/
|
||||
virtual QString token_present() const = 0;
|
||||
};
|
||||
/**
|
||||
* @brief 基础语法匹配规则接口
|
||||
*/
|
||||
class BaseRule {
|
||||
public:
|
||||
virtual ~BaseRule() = default;
|
||||
/**
|
||||
* @brief 子规则
|
||||
* @return
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const = 0;
|
||||
|
||||
/**
|
||||
* @brief token匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT TokenMatch : public BaseRule {
|
||||
private:
|
||||
std::shared_ptr<const lib_token::TokenDefine> define_peer;
|
||||
/**
|
||||
* @brief 匹配结果
|
||||
*/
|
||||
enum class MatchResult {
|
||||
Success, // 符合匹配条件
|
||||
Part, // 部分匹配
|
||||
Fail // 从第一个词起完全不匹配
|
||||
};
|
||||
|
||||
public:
|
||||
TokenMatch(std::shared_ptr<const lib_token::TokenDefine> define);
|
||||
/**
|
||||
* @brief token流匹配
|
||||
* @return 首部对齐,匹配token集合
|
||||
*/
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const = 0;
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QList<std::shared_ptr<const ast_basic::TokenNode>> parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
/**
|
||||
* @brief 解析
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
virtual std::shared_ptr<const ast_basic::Expression> parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const = 0;
|
||||
|
||||
/**
|
||||
* @brief 语法规则或匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT Any : public BaseRule {
|
||||
private:
|
||||
QList<std::shared_ptr<const BaseRule>> mbrs_store;
|
||||
/**
|
||||
* 返回匹配语法规则的词法序列表达
|
||||
*
|
||||
* \return 词法表达序列
|
||||
*/
|
||||
virtual QString token_present() const = 0;
|
||||
};
|
||||
|
||||
std::tuple<MatchResult, uint, std::shared_ptr<const BaseRule>> rule_select(const QList<std::shared_ptr<const lib_token::Token>>& stream) const;
|
||||
|
||||
public:
|
||||
Any(const QList<std::shared_ptr<const BaseRule>> mbrs);
|
||||
/**
|
||||
* @brief token匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT TokenMatch : public BaseRule, public std::enable_shared_from_this<TokenMatch> {
|
||||
private:
|
||||
std::shared_ptr<const lib_token::TokenDefine> define_peer;
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QList<std::shared_ptr<const ast_basic::TokenNode>> parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
public:
|
||||
TokenMatch(std::shared_ptr<const lib_token::TokenDefine> define);
|
||||
|
||||
/**
|
||||
* @brief 语法规则序列匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT Seqs : public BaseRule {
|
||||
private:
|
||||
QList<std::shared_ptr<const BaseRule>> mbrs_store;
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual std::shared_ptr<const ast_basic::Expression> parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
public:
|
||||
Seqs(const QList<std::shared_ptr<const BaseRule>> mbrs);
|
||||
/**
|
||||
* @brief 语法规则或匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT Any : public BaseRule, public std::enable_shared_from_this<Any> {
|
||||
private:
|
||||
QList<std::shared_ptr<const BaseRule>> mbrs_store;
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QList<std::shared_ptr<const ast_basic::TokenNode>> parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
std::tuple<MatchResult, uint, std::shared_ptr<const BaseRule>> rule_select(const QList<std::shared_ptr<const lib_token::Token>>& stream) const;
|
||||
|
||||
/**
|
||||
* @brief 语法规则重复匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT Rept : public BaseRule {
|
||||
private:
|
||||
std::shared_ptr<const BaseRule> rule_peer;
|
||||
int min_match, max_match;
|
||||
public:
|
||||
Any(const QList<std::shared_ptr<const BaseRule>> mbrs);
|
||||
|
||||
public:
|
||||
Rept(std::shared_ptr<const BaseRule> rule, int min, int max);
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual std::shared_ptr<const ast_basic::Expression> parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QList<std::shared_ptr<const ast_basic::TokenNode>> parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
/**
|
||||
* @brief 语法规则序列匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT Seqs : public BaseRule, public std::enable_shared_from_this<Seqs> {
|
||||
private:
|
||||
QList<std::shared_ptr<const BaseRule>> mbrs_store;
|
||||
|
||||
// 组合语法实体解析 ===================================================================================================
|
||||
/**
|
||||
* @brief 对应语法表达式解析规则
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT ExprRule : public lib_syntax::BaseRule, public std::enable_shared_from_this<ExprRule> {
|
||||
private:
|
||||
std::shared_ptr<const lib_syntax::BaseRule> child_store;
|
||||
QString name_store;
|
||||
int mark_store;
|
||||
std::function<QList<std::shared_ptr<const ast_basic::TokenNode>>(const QList<std::shared_ptr<const ast_basic::TokenNode>>& primary)> filter_proc;
|
||||
public:
|
||||
Seqs(const QList<std::shared_ptr<const BaseRule>> mbrs);
|
||||
|
||||
public:
|
||||
typedef QList<std::shared_ptr<const ast_basic::TokenNode>> TokenSeqs;
|
||||
ExprRule(const QString& rule_name, int expr_mark);
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual std::shared_ptr<const ast_basic::Expression> parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
virtual std::shared_ptr<const ExprRule> reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule);
|
||||
virtual QString name() const;
|
||||
virtual int typeMark() const;
|
||||
/**
|
||||
* @brief 语法规则重复匹配
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT Rept : public BaseRule, public std::enable_shared_from_this<Rept> {
|
||||
private:
|
||||
std::shared_ptr<const BaseRule> rule_peer;
|
||||
int min_match, max_match;
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const lib_syntax::BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QList<std::shared_ptr<const ast_basic::TokenNode>> parse(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
public:
|
||||
Rept(std::shared_ptr<const BaseRule> rule, int min, int max);
|
||||
|
||||
/**
|
||||
* @brief 语法检查核对工具
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT ExprsChecker {
|
||||
public:
|
||||
ExprsChecker(std::shared_ptr<const ExprRule> parse_tree);
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual std::shared_ptr<const ast_basic::Expression> parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
QList<std::shared_ptr<const ast_basic::TokenNode>> parseFrom(const QList<std::shared_ptr<const lib_token::Token>>& all_tokens);
|
||||
// 组合语法实体解析 ===================================================================================================
|
||||
/**
|
||||
* @brief 对应语法表达式解析规则
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT ExpressionRule : public lib_syntax::BaseRule, public std::enable_shared_from_this<ExpressionRule> {
|
||||
public:
|
||||
typedef QList<std::shared_ptr<const lib_token::Token>> TokenSeqs;
|
||||
ExpressionRule(const QString& rule_name, int expr_mark);
|
||||
|
||||
private:
|
||||
std::shared_ptr<const ExprRule> syntax_tree_root;
|
||||
};
|
||||
virtual std::shared_ptr<const ExpressionRule> reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule);
|
||||
virtual QString name() const;
|
||||
virtual int typeMark() const;
|
||||
|
||||
virtual std::shared_ptr<ast_basic::Expression> newEmptyInstance() const = 0;
|
||||
virtual std::shared_ptr<ExpressionRule> makeCopy() const = 0;
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
virtual QList<std::shared_ptr<const lib_syntax::BaseRule>> children() const override;
|
||||
virtual std::tuple<MatchResult, uint> match(const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual std::shared_ptr<const ast_basic::Expression> parse(std::shared_ptr<ParseContext> rt_inst, const QList<std::shared_ptr<const lib_token::Token>>& stream) const override;
|
||||
virtual QString token_present() const override;
|
||||
|
||||
private:
|
||||
std::function<TokenSeqs(const TokenSeqs&)> filter_proc;
|
||||
std::shared_ptr<const lib_syntax::BaseRule> child_store;
|
||||
QString name_store;
|
||||
int mark_store;
|
||||
};
|
||||
|
||||
/**
|
||||
* 语法元素解析规则.
|
||||
*/
|
||||
template<class ExprType>
|
||||
class ElementRule : public ExpressionRule {
|
||||
public:
|
||||
ElementRule(const QString& rule_name, int expr_mark)
|
||||
:ExpressionRule(rule_name, expr_mark){}
|
||||
|
||||
virtual std::shared_ptr<ast_basic::Expression> newEmptyInstance() const {
|
||||
return std::dynamic_pointer_cast<ast_basic::Expression>(
|
||||
std::make_shared<ExprType>(this->shared_from_this()));
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<ExpressionRule> makeCopy() const {
|
||||
return std::make_shared<ElementRule<ExprType>>(name(), typeMark());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace lib_syntax
|
|
@ -1,5 +1,6 @@
|
|||
#include "syntax_novel.h"
|
||||
#include <tokens_novel.h>
|
||||
#include "ast_novel.h"
|
||||
|
||||
using namespace lib_syntax;
|
||||
using namespace example_novel;
|
||||
|
@ -38,78 +39,93 @@ auto newl = std::make_shared<NewLine>();
|
|||
|
||||
|
||||
QList<std::shared_ptr<const BaseRule>> LinesMerge(const QList<std::shared_ptr<const BaseRule>>& mbrs) {
|
||||
QList<std::shared_ptr<const BaseRule>> values_ret;
|
||||
for (auto& item : mbrs) {
|
||||
values_ret << item << OptMulT(newl);
|
||||
}
|
||||
return values_ret;
|
||||
QList<std::shared_ptr<const BaseRule>> values_ret;
|
||||
for (auto& item : mbrs) {
|
||||
values_ret << item << OptMulT(newl);
|
||||
}
|
||||
return values_ret;
|
||||
}
|
||||
QList<std::shared_ptr<const BaseRule>> LinesMerge(std::shared_ptr<const BaseRule> item) {
|
||||
return QList<std::shared_ptr<const BaseRule>>() << item << OptMulT(newl);
|
||||
return QList<std::shared_ptr<const BaseRule>>() << item << OptMulT(newl);
|
||||
}
|
||||
|
||||
// remove-return
|
||||
auto remove_nl = [](const ExprRule::TokenSeqs& p)->ExprRule::TokenSeqs {
|
||||
ExprRule::TokenSeqs result;
|
||||
for (auto& n : p) {
|
||||
if (n->isLeaf()) {
|
||||
auto target_token = n->tokens().first();
|
||||
if (target_token->define()->name() == newl->name())
|
||||
continue;
|
||||
}
|
||||
result.append(n);
|
||||
}
|
||||
return result;
|
||||
auto remove_nl = [](const ExpressionRule::TokenSeqs& p)->ExpressionRule::TokenSeqs {
|
||||
ExpressionRule::TokenSeqs result;
|
||||
for (auto& n : p) {
|
||||
if (n->define()->name() == newl->name())
|
||||
continue;
|
||||
result.append(n);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto decl_comp = std::make_shared<const Any>(Rules{MR(numbers), MR(vtext), MR(name_text), MR(split_mark)});
|
||||
auto decl_expr = ExprRule(u8"decl_section", (int)NovelExprs::DESC_SECTION).reloadRule(remove_nl,
|
||||
std::make_shared<const Seqs>(LinesMerge(MultiR(decl_comp))
|
||||
auto decl_comp = std::make_shared<const Any>(Rules{ MR(numbers), MR(vtext), MR(name_text), MR(split_mark) });
|
||||
auto decl_expr = ElementRule<TextSection>(u8"decl_section", (int)NovelExprs::DESC_SECTION).reloadRule(remove_nl,
|
||||
std::make_shared<const Seqs>(LinesMerge(MultiR(decl_comp))
|
||||
));
|
||||
|
||||
auto fragment_decl = ElementRule<FragmentDefine>(u8"fragment_define", (int)NovelExprs::FRAG_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{ MR(leftb), MR(frag_key), MR(name_text) }) <<
|
||||
OptMulR(decl_expr) <<
|
||||
LinesMerge(MR(rightb))
|
||||
));
|
||||
|
||||
auto fragment_decl = ExprRule(u8"fragment_define", (int)NovelExprs::FRAG_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{MR(leftb), MR(frag_key), MR(name_text)}) <<
|
||||
OptMulR(decl_expr) <<
|
||||
LinesMerge(MR(rightb))
|
||||
auto fragment_refer = ElementRule<FragmentRefers>(u8"fragment_refer", (int)NovelExprs::FRAG_REFERS).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{ MR(leftb), MR(refers), MR(frag_key), MR(name_text), MR(split_mark), MR(name_text) }) <<
|
||||
OptMulR(decl_expr) <<
|
||||
LinesMerge(MR(rightb))
|
||||
));
|
||||
|
||||
auto fragment_refer = ExprRule(u8"fragment_refer", (int)NovelExprs::FRAG_REFERS).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{MR(leftb), MR(refers), MR(frag_key), MR(name_text), MR(split_mark), MR(name_text)}) <<
|
||||
OptMulR(decl_expr) <<
|
||||
LinesMerge(MR(rightb))
|
||||
));
|
||||
|
||||
auto fragment_comp = std::make_shared<const Any>(Rules{fragment_decl, fragment_refer, decl_expr});
|
||||
auto story_define = ExprRule(u8"story_define", (int)NovelExprs::STORY_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{MR(leftb), MR(story_key), MR(numbers), MR(name_text)}) <<
|
||||
OptMulR(fragment_comp) <<
|
||||
LinesMerge(MR(rightb))
|
||||
auto fragment_comp = std::make_shared<const Any>(Rules{ fragment_decl, fragment_refer, decl_expr });
|
||||
auto story_define = ElementRule<StoryDefine>(u8"story_define", (int)NovelExprs::STORY_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{ MR(leftb), MR(story_key), MR(numbers), MR(name_text) }) <<
|
||||
OptMulR(fragment_comp) <<
|
||||
LinesMerge(MR(rightb))
|
||||
));
|
||||
// ===================================================================
|
||||
auto article_decl = ExprRule(u8"article_define", (int)NovelExprs::ARTICLE_DEFINE).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{MR(leftb), MR(article_key), MR(name_text)}) <<
|
||||
OptMulR(std::make_shared<const Any>(Rules{ fragment_refer, decl_expr })) <<
|
||||
LinesMerge(MR(rightb))
|
||||
auto article_decl = ElementRule<ArticleDefine>(u8"article_define", (int)NovelExprs::ARTICLE_DEFINE).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{ MR(leftb), MR(article_key), MR(name_text) }) <<
|
||||
OptMulR(std::make_shared<const Any>(Rules{ fragment_refer, decl_expr })) <<
|
||||
LinesMerge(MR(rightb))
|
||||
));
|
||||
|
||||
auto volume_decl = ExprRule(u8"volume_define", (int)NovelExprs::VOLUME_DEFINE).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{MR(leftb), MR(volume_key), MR(name_text)}) <<
|
||||
OptMulR(std::make_shared<const Any>(Rules{ decl_expr, article_decl })) <<
|
||||
LinesMerge(MR(rightb))
|
||||
auto volume_decl = ElementRule<VolumeDefine>(u8"volume_define", (int)NovelExprs::VOLUME_DEFINE).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
LinesMerge(Rules{ MR(leftb), MR(volume_key), MR(name_text) }) <<
|
||||
OptMulR(std::make_shared<const Any>(Rules{ decl_expr, article_decl })) <<
|
||||
LinesMerge(MR(rightb))
|
||||
));
|
||||
|
||||
auto document_define = ExprRule(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
Rules{
|
||||
OptMulT(newl),
|
||||
MultiR(std::make_shared<const Any>(Rules{story_define, volume_decl}))
|
||||
}
|
||||
auto document_define = ElementRule<Document>(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
|
||||
Rules{
|
||||
OptMulT(newl),
|
||||
MultiR(std::make_shared<const Any>(Rules{story_define, volume_decl}))
|
||||
}
|
||||
));
|
||||
|
||||
std::shared_ptr<const ExprRule> NovalSyntax::getParseTree() { return document_define; }
|
||||
std::shared_ptr<const ExpressionRule> NovalSyntax::getParseTree() { return document_define; }
|
||||
std::shared_ptr<const ast_gen::SyntaxElement> example_novel::NovalSyntax::tidy(std::shared_ptr<const ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
|
||||
{
|
||||
for (auto& cinst : children) {
|
||||
cinst->setParent(root);
|
||||
if (!cinst->isAnonymous())
|
||||
ast_gen::GlobalElement::UniquePtr->appendToCache(cinst);
|
||||
|
||||
QList<std::shared_ptr<ast_gen::SyntaxElement>> child_items;
|
||||
for (auto& it : cinst->bindExpression()->children()) {
|
||||
auto const_it = std::dynamic_pointer_cast<const ast_gen::SyntaxElement>(it);
|
||||
child_items.append(std::const_pointer_cast<ast_gen::SyntaxElement>(const_it));
|
||||
}
|
||||
|
||||
tidy(cinst, child_items);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
std::shared_ptr<const TokenReader> NovalSyntax::getLexReader()
|
||||
{
|
||||
auto inst = std::make_shared<lib_token::TokenReader>(QList<std::shared_ptr<const lib_token::TokenDefine>>()
|
||||
<< leftb << rightb << refers << split_mark << story_key << frag_key << volume_key << article_key << numbers << name_text << vtext << newl);
|
||||
return inst;
|
||||
auto inst = std::make_shared<lib_token::TokenReader>(QList<std::shared_ptr<const lib_token::TokenDefine>>()
|
||||
<< leftb << rightb << refers << split_mark << story_key << frag_key << volume_key << article_key << numbers << name_text << vtext << newl);
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ast_basic.h"
|
||||
#include "ast_gen.h"
|
||||
#include "libsyntax.h"
|
||||
#include <libtoken.h>
|
||||
#include <tokens_novel.h>
|
||||
|
@ -35,7 +36,9 @@ namespace example_novel {
|
|||
* @brief 获取novel语法解析树
|
||||
* @return
|
||||
*/
|
||||
static std::shared_ptr<const lib_syntax::ExprRule> getParseTree();
|
||||
static std::shared_ptr<const lib_syntax::ExpressionRule> getParseTree();
|
||||
|
||||
static std::shared_ptr<const ast_gen::SyntaxElement> tidy(std::shared_ptr<const ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> docs);
|
||||
};
|
||||
|
||||
} // namespace example_novel
|
Loading…
Reference in New Issue