From c8fedda85b3e9dd9972c4a790ee97ec2e1e71667 Mon Sep 17 00:00:00 2001 From: codeboss <2422523675@qq.com> Date: Tue, 18 Jun 2024 11:54:36 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=86=97=E4=BD=99=E5=B1=82?= =?UTF-8?q?=E6=AC=A1=EF=BC=8C=E8=AF=AD=E6=B3=95=E8=A7=84=E5=88=99=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E7=9B=B4=E5=87=BA=E8=AF=AD=E6=B3=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsNovelParser/novelparser.cpp | 32 ++-- WsNovelParser/novelparser.h | 2 +- libSyntax/ast_basic.cpp | 104 ++++++----- libSyntax/ast_basic.h | 147 ++++++++------- libSyntax/ast_gen.cpp | 136 ++++---------- libSyntax/ast_gen.h | 65 ++----- libSyntax/ast_novel.cpp | 220 +++++++---------------- libSyntax/ast_novel.h | 124 ++++--------- libSyntax/libsyntax.cpp | 127 ++++++------- libSyntax/libsyntax.h | 325 +++++++++++++++++++--------------- libSyntax/syntax_novel.cpp | 120 +++++++------ libSyntax/syntax_novel.h | 5 +- 12 files changed, 609 insertions(+), 798 deletions(-) diff --git a/WsNovelParser/novelparser.cpp b/WsNovelParser/novelparser.cpp index 6c5f52e..6b377c8 100644 --- a/WsNovelParser/novelparser.cpp +++ b/WsNovelParser/novelparser.cpp @@ -23,37 +23,29 @@ QString NovelParser::version() const } std::shared_ptr NovelParser::parse(const QFileInfoList source_list) const { - QList> forst_root; + QList> forst_root; auto lex_reader = NovalSyntax::getLexReader(); + auto context = std::make_shared(u8"小说"); auto time_stamp = QTime::currentTime(); for (auto& file : source_list) { auto tokens = lex_reader->extractFrom(file.canonicalFilePath()); - auto exprs_result = std::make_shared(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> input)> summary = - [&](QList> input) -> QList> { - QList> temp; - - if (input.size()) { - auto item = std::dynamic_pointer_cast(input.first()); - temp << item; - temp.append(summary(input.mid(1))); - } - - return temp; - }; - time_stamp = QTime::currentTime(); - auto tree_visit = std::make_shared(); - auto vinst = std::make_shared(tree_visit); - auto resultx = vinst->parse("test", summary(forst_root)); - auto novel_accesstree = vinst->tidy(resultx); + QList> docs_node; + for (auto &it : forst_root) { + auto xitem = std::dynamic_pointer_cast(it); + docs_node.append(std::const_pointer_cast(xitem)); + context->addChild(docs_node.last()); + } + + auto x_root = NovalSyntax::tidy(context, docs_node); + auto novel_accesstree = std::make_shared(x_root); current_stamp = QTime::currentTime(); qDebug() << QString(u8"程序结构重建消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp)); diff --git a/WsNovelParser/novelparser.h b/WsNovelParser/novelparser.h index 3239f79..f2aba35 100644 --- a/WsNovelParser/novelparser.h +++ b/WsNovelParser/novelparser.h @@ -8,7 +8,7 @@ class NovelParser { private: - std::shared_ptr syntax_defines; + std::shared_ptr syntax_defines; QList> checker_list; std::shared_ptr analyzer_ref; diff --git a/libSyntax/ast_basic.cpp b/libSyntax/ast_basic.cpp index dce1a98..cf39feb 100644 --- a/libSyntax/ast_basic.cpp +++ b/libSyntax/ast_basic.cpp @@ -4,65 +4,71 @@ using namespace ast_basic; using namespace lib_token; using namespace lib_syntax; -TokenNodeImpl::TokenNodeImpl(std::shared_ptr word) : word_store(word) {} +ExpressionElement::ExpressionElement(std::shared_ptr bind) : _expr_rule(bind) {} -QString TokenNodeImpl::filePath() const +std::shared_ptr 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>& list) { + this->tokens_bind = list; +} + +void ast_basic::ExpressionElement::addToken(std::shared_ptr token_inst) { + this->tokens_bind.append(token_inst); +} + +QList> ast_basic::ExpressionElement::children() const { + return this->children_store; +} + +void ast_basic::ExpressionElement::addChild(std::shared_ptr inst) { + this->children_store.append(inst); +} + +QList> ExpressionElement::tokens() const { + return this->tokens_bind; +} + +std::shared_ptr 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> TokenNodeImpl::tokens() const { return QList>() << word_store; } - -std::shared_ptr TokenNodeImpl::filledWith(const QList>& tokens) const { - Q_UNUSED(tokens); - throw new lib_syntax::SyntaxException(u8"InternalError[0x0001]不能对TokenNode调用filledWith"); -} - -ExprNodeImpl::ExprNodeImpl(std::shared_ptr bind) : _expr_rule(bind) {} - -QString ExprNodeImpl::filePath() const +void ast_basic::ExpressionContext::pushInst(std::shared_ptr 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 ExprNodeImpl::defined() const { return this->_expr_rule; } - -QList> ExprNodeImpl::exprNodes() const { - QList> listret; - for (auto& it : children_store) - if (!it->isLeaf()) - listret.append(std::dynamic_pointer_cast(it)); - return listret; -} - -QList > ExprNodeImpl::childTokensMid(int index, int length) const +std::shared_ptr ast_basic::ExpressionContext::popInst() { - if (index >= 0 && length > 0 && index + length <= children_store.size()) - return children_store.mid(index, length); - - return QList>(); + auto lastx = expression_stack.takeLast(); + return lastx; } -QList> ExprNodeImpl::tokens() const { - QList> retlist; - for (auto& it : children_store) - retlist.append(it->tokens()); - return retlist; +std::shared_ptr ast_basic::ExpressionContext::currentExpressionRule() const { + if(rule_stack.size()) + return rule_stack.last(); + return nullptr; } -std::shared_ptr ExprNodeImpl::filledWith(const QList>& child_nodes) const { - auto vinst = std::make_shared(this->_expr_rule); - vinst->children_store.append(child_nodes); - return vinst; +void ast_basic::ExpressionContext::pushExpressionRule(std::shared_ptr inst) { + if(!rule_stack.size() || rule_stack.last() != inst) + rule_stack.append(inst); +} + +std::shared_ptr ast_basic::ExpressionContext::popExpressionRule() +{ + return rule_stack.takeLast(); } diff --git a/libSyntax/ast_basic.h b/libSyntax/ast_basic.h index a39dd9b..4146b2b 100644 --- a/libSyntax/ast_basic.h +++ b/libSyntax/ast_basic.h @@ -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> tokens() const = 0; - /** - * @brief 重置节点内子节点 - * @param tokens - * @return - */ - virtual std::shared_ptr filledWith(const QList>& child_nodes) const = 0; - }; - /** * @brief 抽象语法树集合节点/表达式节点 */ - class ExprNode : public TokenNode { + class Expression { public: + virtual ~Expression() = default; /** - * @brief 表达式定义规则 + * @brief 获取表达式的解析规则 * @return */ - virtual std::shared_ptr defined() const = 0; - /** - * @brief 直接子表达式集合 - * @return - */ - virtual QList> exprNodes() const = 0; + virtual std::shared_ptr definedRule() const = 0; + //===================================================== /** - * @brief 获取TokenNode,以直接子元素计算 - * @param index 起始元素索引 0起始 - * @param length 长度 + * 获取语法节点的源码文件路径. + * + * \return 文件路径 + */ + virtual QString filePath() const = 0; + /** + * 获取语法节点关联token序列. + * + * \return token序列 + */ + virtual QList> tokens() const = 0; + virtual void tokensReset(const QList> &list) = 0; + /** + * 解析过程中,向表达式内部添加token实例. + * + * \param token_inst 实例 + */ + virtual void addToken(std::shared_ptr token_inst) = 0; + + //===================================================== + /** + * @brief 子表达式集合 * @return */ - virtual QList> childTokensMid(int index, int length = 1) const = 0; + virtual QList> children() const = 0; + /** + * @brief 添加子表达式. + * + * \param inst 子表达式实例 + */ + virtual void addChild(std::shared_ptr inst) = 0; }; // 基础语法树构成 ========================================================================================== - - /** - * @brief 词法定义节点 - */ - class LIBSYNTAX_EXPORT TokenNodeImpl : public ast_basic::TokenNode { - private: - std::shared_ptr word_store; - - public: - TokenNodeImpl(std::shared_ptr word); - - // TokenNode interface - public: - virtual QString filePath() const override; - virtual bool isLeaf() const override; - virtual QList> tokens() const override; - virtual std::shared_ptr filledWith(const QList >& 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 { private: - std::shared_ptr _expr_rule; - QList> children_store; + std::shared_ptr _expr_rule; + QList> children_store; + QList> tokens_bind; public: - ExprNodeImpl(std::shared_ptr bind); + ExpressionElement(std::shared_ptr bind); - // TokenNode interface - public: - virtual QString filePath() const override; - virtual bool isLeaf() const override; - virtual QList> tokens() const override; - virtual std::shared_ptr filledWith(const QList >& child_nodes) const override; + // 通过 Expression 继承 + std::shared_ptr definedRule() const override; + + QString filePath() const override; + + QList> tokens() const override; + + void tokensReset(const QList>& list) override; + + void addToken(std::shared_ptr token_inst) override; + + QList> children() const override; + + void addChild(std::shared_ptr inst) override; + }; + + class LIBSYNTAX_EXPORT ExpressionContext : public lib_syntax::ParseContext, public std::enable_shared_from_this { + private: + QList> rule_stack; + QList> expression_stack; - // ExprNode interface public: - virtual std::shared_ptr defined() const override; - virtual QList> exprNodes() const override; - virtual QList > childTokensMid(int index, int length) const override; + ExpressionContext(){} + + + // 通过 ParseContext 继承 + std::shared_ptr currentInst() const override; + void pushInst(std::shared_ptr current_inst) override; + std::shared_ptr popInst() override; + + std::shared_ptr currentExpressionRule() const override; + void pushExpressionRule(std::shared_ptr inst) override; + std::shared_ptr popExpressionRule() override; + }; } \ No newline at end of file diff --git a/libSyntax/ast_gen.cpp b/libSyntax/ast_gen.cpp index dd429e2..66e82db 100644 --- a/libSyntax/ast_gen.cpp +++ b/libSyntax/ast_gen.cpp @@ -2,105 +2,27 @@ using namespace ast_gen; -ExprTreeParser::ExprTreeParser(std::shared_ptr vistor) : visitor_store(vistor) {} +GlobalElement* GlobalElement::UniquePtr = nullptr; -typedef std::shared_ptr E; -typedef QList> Es; -typedef std::shared_ptr Expr; - -QList> ExprTreeParser::parse(const QString& name, - const QList>& forest) const { - std::function visit_loop = [&](Expr n, E p) -> Es { - QList> 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> temp_list; - auto root = std::make_shared(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 ExprTreeParser::tidy(const QList>& nodes) const { - auto temp = nodes.first(); - while (temp->parent()) { - temp = temp->parent(); - } - - auto core_cache = std::static_pointer_cast(std::const_pointer_cast(temp)); - core_cache->clearCache(); - for (auto& it : nodes) { - if (!it->isAnonymous()) { - core_cache->appendToCache(it); - } - } - - auto root = std::make_shared(temp); - for (auto& node : nodes) - tidy_branch(root, node); - - return root; -} - -void ExprTreeParser::tidy_branch(std::shared_ptr root, std::shared_ptr node) const { - QList> link; - while (node) { - link.prepend(node); - node = node->parent(); - } - - std::function pnode, QList>)> merge = - [&](std::shared_ptr pnode, QList> 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(c_a), remains.mid(1)); - return; - } - } - - auto new_branch = std::make_shared(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 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").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").arg(named_node->signature()).arg(named_node->typeMark())); + node_cache[mixed_key] = named_node; } std::shared_ptr 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").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").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 GlobalElement::parent() const { return nullptr; } +void ast_gen::GlobalElement::setParent(std::shared_ptr inst) {} + QList> GlobalElement::selfTokens() const { return QList>(); } +std::shared_ptr ast_gen::GlobalElement::bindExpression() const +{ + return bind_exprs; +} + +void GlobalElement::addChild(std::shared_ptr citem) { + auto convx = std::dynamic_pointer_cast(citem); + bind_exprs->addChild(convx); +} + ElementAccess::ElementAccess(std::shared_ptr point) { peers = point; } std::shared_ptr ElementAccess::element() const { return peers; } -QList> ElementAccess::children() const { return children_store; } +QList> ElementAccess::children() const { + auto expression_inst = element()->bindExpression(); + auto children = expression_inst->children(); -void ElementAccess::appendChild(std::shared_ptr inst) { children_store.append(inst); } + QList> retvalues; + for (auto item : children) { + auto elem_inst = std::dynamic_pointer_cast(item); + retvalues.append(std::make_shared(elem_inst)); + } + return retvalues; +} QList> ElementAccess::tokens() const { - QList> 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 elm_inst, std::shared_ptr token_inst) - : element_bind(elm_inst), token_store(token_inst) {} + : element_bind(elm_inst), token_store(token_inst) {} std::shared_ptr TokenAccess::bind() const { return element_bind; } diff --git a/libSyntax/ast_gen.h b/libSyntax/ast_gen.h index d002c3e..933707d 100644 --- a/libSyntax/ast_gen.h +++ b/libSyntax/ast_gen.h @@ -15,6 +15,14 @@ namespace ast_gen */ class SyntaxElement { public: + virtual ~SyntaxElement() = default; + /** + * 绑定表达式实体. + * + * \return 表达式实例 + */ + virtual std::shared_ptr bindExpression() const = 0; + /** * @brief 类型标记 * @return @@ -42,9 +50,10 @@ namespace ast_gen /** * @brief 获取父元素 - * @return + * @return 未设置parent,返回nullptr */ virtual std::shared_ptr parent() const = 0; + virtual void setParent(std::shared_ptr inst) = 0; /** * @brief 定义元素自身的Token集合 @@ -59,7 +68,6 @@ namespace ast_gen class LIBSYNTAX_EXPORT ElementAccess { private: std::shared_ptr peers; - QList> children_store; public: ElementAccess(std::shared_ptr point); @@ -67,8 +75,6 @@ namespace ast_gen std::shared_ptr element() const; QList> children() const; - void appendChild(std::shared_ptr 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> children_store; QString names_store; QHash> node_cache; + std::shared_ptr bind_exprs = std::make_shared(nullptr); + public: + static GlobalElement* UniquePtr; GlobalElement(const QString& name); virtual void clearCache(); @@ -110,6 +118,8 @@ namespace ast_gen */ virtual std::shared_ptr getNamedNodeBy(int type, const QString& signature) const; + virtual void addChild(std::shared_ptr 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 parent() const override; + virtual void setParent(std::shared_ptr inst) override; virtual QList> selfTokens() const override; - }; - /** - * @brief 语法树节点访问器 - */ - class ExprVisitor { - public: - /** - * @brief 解析表达式节点,转换成语法元素实体 - * @param expr 表达式节点 - * @param pnode 父节点 - * @return 该节点转换成的语法元素节点 - */ - virtual std::shared_ptr visit(std::shared_ptr expr, std::shared_ptr pnode) const = 0; - }; - - /** - * @brief 抽象语法树解析器 - */ - class LIBSYNTAX_EXPORT ExprTreeParser { - private: - std::shared_ptr visitor_store; - void tidy_branch(std::shared_ptr root, std::shared_ptr node) const; - - public: - ExprTreeParser(std::shared_ptr vistor); - - /** - * @brief 解析语法内容,生成倒立语法树 - * @param name 生成产物名称 - * @param forest 表达式森林,全部的表达式树 - * @return 语法树的所有叶子节点 - */ - QList> parse(const QString& name, const QList>& forest) const; - - /** - * @brief 整理语法树节点,生成语法元素访问树 - * @param nodes - * @return - */ - std::shared_ptr tidy(const QList>& nodes) const; + // 通过 SyntaxElement 继承 + std::shared_ptr bindExpression() const override; }; } \ No newline at end of file diff --git a/libSyntax/ast_novel.cpp b/libSyntax/ast_novel.cpp index cda39c3..6b3dd2a 100644 --- a/libSyntax/ast_novel.cpp +++ b/libSyntax/ast_novel.cpp @@ -3,245 +3,151 @@ using namespace example_novel; -TextSection::TextSection(const QString& text, const QString path, std::shared_ptr parent) - : content_store(text), file_path(path), pnode_store(parent) {} +TextSection::TextSection(std::shared_ptr 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 TextSection::parent() const { return pnode_store; } +FragmentRefers::FragmentRefers(std::shared_ptr rule_bind) + : AbstractImpl(rule_bind) {} -QList > 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 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 FragmentRefers::parent() const { return pnode_store; } +FragmentDefine::FragmentDefine(std::shared_ptr rule_bind) + : AbstractImpl(rule_bind) {} -QList > FragmentRefers::selfTokens() const { - return TokenSL::selfTokens(); -} - -FragmentDefine::FragmentDefine(const QString& name, const QString& path, std::shared_ptr 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 FragmentDefine::parent() const { return pnode_store; } +StoryDefine::StoryDefine(std::shared_ptr rule_bind) + : AbstractImpl(rule_bind) {} -QList > 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 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 StoryDefine::parent() const { return pnode_store; } - -QList > StoryDefine::selfTokens() const { - return TokenSL::selfTokens(); -} +QString StoryDefine::signature() const { return name(); } #include "syntax_novel.h" -std::shared_ptr NovelExprsVisitor::visit(std::shared_ptr expr, std::shared_ptr pnode) const -{ - auto tidy_tokens = [&](std::shared_ptr 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(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(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(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(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(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(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(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 pnode) - : path_store(path), pnode_store(pnode) {} +Document::Document(std::shared_ptr 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 Document::parent() const { return pnode_store; } +example_novel::AbstractImpl::AbstractImpl(std::shared_ptr rule_bind) + : ExpressionElement(rule_bind) {} -QList > Document::selfTokens() const +QList > AbstractImpl::selfTokens() const { + auto tokensx = ast_basic::ExpressionElement::tokens(); + QList> values; + for (auto xit : tokensx) { + values.append(std::make_shared(std::dynamic_pointer_cast(shared_from_this()), xit)); + } + + return values; +} + +std::shared_ptr example_novel::AbstractImpl::parent() const { - return QList>(); + return this->parent_store; } -void TokenSL::appendDefinedTokens(std::shared_ptr elm, QList> tokens) { - QList> access; - for (auto& t : tokens) - this->tokens_store << std::make_shared(elm, t); +void example_novel::AbstractImpl::setParent(std::shared_ptr inst) +{ + this->parent_store = inst; } -QList > TokenSL::selfTokens() const { - return tokens_store; + +// 通过 SyntaxElement 继承 +std::shared_ptr example_novel::AbstractImpl::bindExpression() const { + return shared_from_this(); } -VolumeDefine::VolumeDefine(const QString& name, const QString& path, std::shared_ptr 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 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 VolumeDefine::parent() const { return pnode_store; } +ArticleDefine::ArticleDefine(std::shared_ptr rule_bind) + : AbstractImpl(rule_bind) {} -QList > VolumeDefine::selfTokens() const { - return TokenSL::selfTokens(); -} - -ArticleDefine::ArticleDefine(const QString& name, const QString& path, std::shared_ptr 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 ArticleDefine::parent() const { return pnode_store; } - -QList > ArticleDefine::selfTokens() const { - return TokenSL::selfTokens(); -} - diff --git a/libSyntax/ast_novel.h b/libSyntax/ast_novel.h index 5fdaddb..201085d 100644 --- a/libSyntax/ast_novel.h +++ b/libSyntax/ast_novel.h @@ -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> tokens_store; + std::shared_ptr parent_store = nullptr; public: - virtual void appendDefinedTokens(std::shared_ptr elm, QList > tokens); - virtual QList> selfTokens() const; + explicit AbstractImpl(std::shared_ptr rule_bind); + + // 通过 SyntaxElement 继承 + virtual std::shared_ptr bindExpression() const override; + QString path() const override; + virtual std::shared_ptr parent() const override; + virtual void setParent(std::shared_ptr inst) override; + virtual QList> selfTokens() const override; }; - class LIBSYNTAX_EXPORT TextSection : public ast_gen::SyntaxElement, public TokenSL { - private: - QString content_store; - QString file_path; - std::shared_ptr pnode_store; - + class LIBSYNTAX_EXPORT TextSection : public AbstractImpl { public: - TextSection(const QString& text, const QString path, std::shared_ptr parent); + TextSection(std::shared_ptr 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 parent() const override; - virtual QList > 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 pnode_store; - + class LIBSYNTAX_EXPORT FragmentRefers : public AbstractImpl { public: - FragmentRefers(const QString& story, const QString& fragment, const QString& path, std::shared_ptr parent); + FragmentRefers(std::shared_ptr 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 parent() const override; - virtual QList > selfTokens() const override; }; - class LIBSYNTAX_EXPORT FragmentDefine : public ast_gen::SyntaxElement, public TokenSL { - private: - QString name_store; - QString path_store; - std::shared_ptr pnode_store; - + class LIBSYNTAX_EXPORT FragmentDefine : public AbstractImpl { public: - FragmentDefine(const QString& name, const QString& path, std::shared_ptr parent); + FragmentDefine(std::shared_ptr 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 parent() const override; - virtual QList > selfTokens() const override; }; - class LIBSYNTAX_EXPORT ArticleDefine : public ast_gen::SyntaxElement, public TokenSL { - private: - QString name_store; - QString path_store; - std::shared_ptr pnode_store; - + class LIBSYNTAX_EXPORT ArticleDefine : public AbstractImpl{ public: - ArticleDefine(const QString& name, const QString& path, std::shared_ptr parent); + ArticleDefine(std::shared_ptr 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 parent() const override; - virtual QList > selfTokens() const override; }; - class LIBSYNTAX_EXPORT VolumeDefine : public ast_gen::SyntaxElement, public TokenSL { - private: - QString name_store; - QString path_store; - std::shared_ptr pnode_store; - + class LIBSYNTAX_EXPORT VolumeDefine : public AbstractImpl { public: - VolumeDefine(const QString& name, const QString& path, std::shared_ptr parent); + VolumeDefine(std::shared_ptr 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 parent() const override; - virtual QList > 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 pnode_store; - + class LIBSYNTAX_EXPORT StoryDefine : public AbstractImpl { public: - StoryDefine(const QString name, int sort, const QString path, std::shared_ptr parent); + StoryDefine(std::shared_ptr 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 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 parent() const override; - virtual QList > selfTokens() const override; - }; - - class LIBSYNTAX_EXPORT Document : public ast_gen::SyntaxElement { - private: - QString path_store; - std::shared_ptr pnode_store; - - public: - Document(const QString& path, std::shared_ptr 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 parent() const override; - virtual QList> selfTokens() const override; - }; - - class LIBSYNTAX_EXPORT NovelExprsVisitor : public ast_gen::ExprVisitor { - - // ExprVisitor interface - public: - virtual std::shared_ptr visit(std::shared_ptr expr, std::shared_ptr pnode) const override; }; } diff --git a/libSyntax/libsyntax.cpp b/libSyntax/libsyntax.cpp index 14f0915..561a0f9 100644 --- a/libSyntax/libsyntax.cpp +++ b/libSyntax/libsyntax.cpp @@ -19,20 +19,21 @@ std::tuple TokenMatch::match(const QList> TokenMatch::parse(const QList>& stream) const { +std::shared_ptr TokenMatch::parse(std::shared_ptr rt_inst, const QList>& stream) const { if (stream.size()) { auto current = stream.first(); - if (current->define()->name() == define_peer->name()) - return QList>() << std::make_shared(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 Rept::match(const QList> Rept::parse(const QList>& stream) const { - QList> list_retvs; - +std::shared_ptr Rept::parse(std::shared_ptr rt_inst, const QList>& 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> Rept::parse(const QList(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 Seqs::match(const QList> Seqs::parse(const QList>& stream) const { - QList> list_retv; - +std::shared_ptr Seqs::parse(std::shared_ptr rt_inst,const QList>& 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 Any::match(const QList(item), std::get<1>(item)); } -QList> Any::parse(const QList>& stream) const { +std::shared_ptr Any::parse(std::shared_ptr rt_inst, const QList>& 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 ExprRule::reloadRule(std::function filter, std::shared_ptr rule) { - auto ninst = std::make_shared(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> ExprRule::children() const { return QList>() << this->child_store; } - -std::tuple ExprRule::match(const QList>& stream) const { - return child_store->match(stream); -} - -QList> ExprRule::parse(const QList>& stream) const { - auto primary_tokens = child_store->parse(stream); - auto remains_tokens = this->filter_proc(primary_tokens); - return QList>() << 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 parse_tree) : syntax_tree_root(parse_tree) {} - -QList> ExprsChecker::parseFrom(const QList>& all_tokens) { - if (!all_tokens.size()) - return QList>(); - - 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 lib_syntax::ExpressionRule::reloadRule(std::function filter, std::shared_ptr 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> lib_syntax::ExpressionRule::children() const { + return QList>() << this->child_store; +} + +std::tuple lib_syntax::ExpressionRule::match(const QList>& stream) const { + return child_store->match(stream); +} + +std::shared_ptr lib_syntax::ExpressionRule::parse(std::shared_ptr rt_inst, const QList>& stream) const { + std::shared_ptr 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()); } diff --git a/libSyntax/libsyntax.h b/libSyntax/libsyntax.h index e880298..1ffb109 100644 --- a/libSyntax/libsyntax.h +++ b/libSyntax/libsyntax.h @@ -5,182 +5,215 @@ #include #include #include - 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> 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 match(const QList>& stream) const = 0; + /** + * \brief 当前表达式元素. + * + * \return 返回当前表达式 + */ + virtual std::shared_ptr currentInst() const = 0; + virtual void pushInst(std::shared_ptr current_inst) = 0; + virtual std::shared_ptr popInst() = 0; - /** - * @brief 解析 - * @param stream - * @return - */ - virtual QList> parse(const QList>& stream) const = 0; + virtual std::shared_ptr currentExpressionRule() const = 0; + virtual void pushExpressionRule(std::shared_ptr inst) = 0; + virtual std::shared_ptr popExpressionRule() = 0; + }; - /** - * 返回匹配语法规则的词法序列表达 - * - * \return 词法表达序列 - */ - virtual QString token_present() const = 0; - }; + /** + * @brief 基础语法匹配规则接口 + */ + class BaseRule { + public: + virtual ~BaseRule() = default; + /** + * @brief 子规则 + * @return + */ + virtual QList> children() const = 0; - /** - * @brief token匹配 - */ - class LIBSYNTAX_EXPORT TokenMatch : public BaseRule { - private: - std::shared_ptr define_peer; + /** + * @brief 匹配结果 + */ + enum class MatchResult { + Success, // 符合匹配条件 + Part, // 部分匹配 + Fail // 从第一个词起完全不匹配 + }; - public: - TokenMatch(std::shared_ptr define); + /** + * @brief token流匹配 + * @return 首部对齐,匹配token集合 + */ + virtual std::tuple match(const QList>& stream) const = 0; - // BaseRule interface - public: - virtual QList> children() const override; - virtual std::tuple match(const QList>& stream) const override; - virtual QList> parse(const QList>& stream) const override; - virtual QString token_present() const override; - }; + /** + * @brief 解析 + * @param stream + * @return + */ + virtual std::shared_ptr parse(std::shared_ptr rt_inst, const QList>& stream) const = 0; - /** - * @brief 语法规则或匹配 - */ - class LIBSYNTAX_EXPORT Any : public BaseRule { - private: - QList> mbrs_store; + /** + * 返回匹配语法规则的词法序列表达 + * + * \return 词法表达序列 + */ + virtual QString token_present() const = 0; + }; - std::tuple> rule_select(const QList>& stream) const; - public: - Any(const QList> mbrs); + /** + * @brief token匹配 + */ + class LIBSYNTAX_EXPORT TokenMatch : public BaseRule, public std::enable_shared_from_this { + private: + std::shared_ptr define_peer; - // BaseRule interface - public: - virtual QList> children() const override; - virtual std::tuple match(const QList>& stream) const override; - virtual QList> parse(const QList>& stream) const override; - virtual QString token_present() const override; - }; + public: + TokenMatch(std::shared_ptr define); - /** - * @brief 语法规则序列匹配 - */ - class LIBSYNTAX_EXPORT Seqs : public BaseRule { - private: - QList> mbrs_store; + // BaseRule interface + public: + virtual QList> children() const override; + virtual std::tuple match(const QList>& stream) const override; + virtual std::shared_ptr parse(std::shared_ptr rt_inst, const QList>& stream) const override; + virtual QString token_present() const override; + }; - public: - Seqs(const QList> mbrs); + /** + * @brief 语法规则或匹配 + */ + class LIBSYNTAX_EXPORT Any : public BaseRule, public std::enable_shared_from_this { + private: + QList> mbrs_store; - // BaseRule interface - public: - virtual QList> children() const override; - virtual std::tuple match(const QList>& stream) const override; - virtual QList> parse(const QList>& stream) const override; - virtual QString token_present() const override; - }; + std::tuple> rule_select(const QList>& stream) const; - /** - * @brief 语法规则重复匹配 - */ - class LIBSYNTAX_EXPORT Rept : public BaseRule { - private: - std::shared_ptr rule_peer; - int min_match, max_match; + public: + Any(const QList> mbrs); - public: - Rept(std::shared_ptr rule, int min, int max); + // BaseRule interface + public: + virtual QList> children() const override; + virtual std::tuple match(const QList>& stream) const override; + virtual std::shared_ptr parse(std::shared_ptr rt_inst, const QList>& stream) const override; + virtual QString token_present() const override; + }; - // BaseRule interface - public: - virtual QList> children() const override; - virtual std::tuple match(const QList>& stream) const override; - virtual QList> parse(const QList>& stream) const override; - virtual QString token_present() const override; - }; + /** + * @brief 语法规则序列匹配 + */ + class LIBSYNTAX_EXPORT Seqs : public BaseRule, public std::enable_shared_from_this { + private: + QList> mbrs_store; - // 组合语法实体解析 =================================================================================================== - /** - * @brief 对应语法表达式解析规则 - */ - class LIBSYNTAX_EXPORT ExprRule : public lib_syntax::BaseRule, public std::enable_shared_from_this { - private: - std::shared_ptr child_store; - QString name_store; - int mark_store; - std::function>(const QList>& primary)> filter_proc; + public: + Seqs(const QList> mbrs); - public: - typedef QList> TokenSeqs; - ExprRule(const QString& rule_name, int expr_mark); + // BaseRule interface + public: + virtual QList> children() const override; + virtual std::tuple match(const QList>& stream) const override; + virtual std::shared_ptr parse(std::shared_ptr rt_inst, const QList>& stream) const override; + virtual QString token_present() const override; + }; - virtual std::shared_ptr reloadRule(std::function filter, std::shared_ptr rule); - virtual QString name() const; - virtual int typeMark() const; + /** + * @brief 语法规则重复匹配 + */ + class LIBSYNTAX_EXPORT Rept : public BaseRule, public std::enable_shared_from_this { + private: + std::shared_ptr rule_peer; + int min_match, max_match; - // BaseRule interface - public: - virtual QList> children() const override; - virtual std::tuple match(const QList>& stream) const override; - virtual QList> parse(const QList>& stream) const override; - virtual QString token_present() const override; - }; + public: + Rept(std::shared_ptr rule, int min, int max); - /** - * @brief 语法检查核对工具 - */ - class LIBSYNTAX_EXPORT ExprsChecker { - public: - ExprsChecker(std::shared_ptr parse_tree); + // BaseRule interface + public: + virtual QList> children() const override; + virtual std::tuple match(const QList>& stream) const override; + virtual std::shared_ptr parse(std::shared_ptr rt_inst, const QList>& stream) const override; + virtual QString token_present() const override; + }; - QList> parseFrom(const QList>& all_tokens); + // 组合语法实体解析 =================================================================================================== + /** + * @brief 对应语法表达式解析规则 + */ + class LIBSYNTAX_EXPORT ExpressionRule : public lib_syntax::BaseRule, public std::enable_shared_from_this { + public: + typedef QList> TokenSeqs; + ExpressionRule(const QString& rule_name, int expr_mark); - private: - std::shared_ptr syntax_tree_root; - }; + virtual std::shared_ptr reloadRule(std::function filter, 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; + + // BaseRule interface + public: + virtual QList> children() const override; + virtual std::tuple match(const QList>& stream) const override; + virtual std::shared_ptr parse(std::shared_ptr rt_inst, const QList>& stream) const override; + virtual QString token_present() const override; + + private: + std::function filter_proc; + std::shared_ptr child_store; + QString name_store; + int mark_store; + }; + + /** + * 语法元素解析规则. + */ + template + class ElementRule : public ExpressionRule { + public: + ElementRule(const QString& rule_name, int expr_mark) + :ExpressionRule(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 \ No newline at end of file diff --git a/libSyntax/syntax_novel.cpp b/libSyntax/syntax_novel.cpp index 6d7b221..2c2e628 100644 --- a/libSyntax/syntax_novel.cpp +++ b/libSyntax/syntax_novel.cpp @@ -1,5 +1,6 @@ #include "syntax_novel.h" #include +#include "ast_novel.h" using namespace lib_syntax; using namespace example_novel; @@ -38,78 +39,93 @@ auto newl = std::make_shared(); QList> LinesMerge(const QList>& mbrs) { - QList> values_ret; - for (auto& item : mbrs) { - values_ret << item << OptMulT(newl); - } - return values_ret; + QList> values_ret; + for (auto& item : mbrs) { + values_ret << item << OptMulT(newl); + } + return values_ret; } QList> LinesMerge(std::shared_ptr item) { - return QList>() << item << OptMulT(newl); + return QList>() << 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(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(LinesMerge(MultiR(decl_comp)) +auto decl_comp = std::make_shared(Rules{ MR(numbers), MR(vtext), MR(name_text), MR(split_mark) }); +auto decl_expr = ElementRule(u8"decl_section", (int)NovelExprs::DESC_SECTION).reloadRule(remove_nl, + std::make_shared(LinesMerge(MultiR(decl_comp)) + )); + +auto fragment_decl = ElementRule(u8"fragment_define", (int)NovelExprs::FRAG_DEFINES).reloadRule(remove_nl, std::make_shared( + 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( - LinesMerge(Rules{MR(leftb), MR(frag_key), MR(name_text)}) << - OptMulR(decl_expr) << - LinesMerge(MR(rightb)) +auto fragment_refer = ElementRule(u8"fragment_refer", (int)NovelExprs::FRAG_REFERS).reloadRule(remove_nl, std::make_shared( + 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( - 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(Rules{fragment_decl, fragment_refer, decl_expr}); -auto story_define = ExprRule(u8"story_define", (int)NovelExprs::STORY_DEFINES).reloadRule(remove_nl, std::make_shared( - LinesMerge(Rules{MR(leftb), MR(story_key), MR(numbers), MR(name_text)}) << - OptMulR(fragment_comp) << - LinesMerge(MR(rightb)) +auto fragment_comp = std::make_shared(Rules{ fragment_decl, fragment_refer, decl_expr }); +auto story_define = ElementRule(u8"story_define", (int)NovelExprs::STORY_DEFINES).reloadRule(remove_nl, std::make_shared( + 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( - LinesMerge(Rules{MR(leftb), MR(article_key), MR(name_text)}) << - OptMulR(std::make_shared(Rules{ fragment_refer, decl_expr })) << - LinesMerge(MR(rightb)) +auto article_decl = ElementRule(u8"article_define", (int)NovelExprs::ARTICLE_DEFINE).reloadRule(remove_nl, std::make_shared( + LinesMerge(Rules{ MR(leftb), MR(article_key), MR(name_text) }) << + OptMulR(std::make_shared(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( - LinesMerge(Rules{MR(leftb), MR(volume_key), MR(name_text)}) << - OptMulR(std::make_shared(Rules{ decl_expr, article_decl })) << - LinesMerge(MR(rightb)) +auto volume_decl = ElementRule(u8"volume_define", (int)NovelExprs::VOLUME_DEFINE).reloadRule(remove_nl, std::make_shared( + LinesMerge(Rules{ MR(leftb), MR(volume_key), MR(name_text) }) << + OptMulR(std::make_shared(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( - Rules{ - OptMulT(newl), - MultiR(std::make_shared(Rules{story_define, volume_decl})) - } +auto document_define = ElementRule(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(remove_nl, std::make_shared( + Rules{ + OptMulT(newl), + MultiR(std::make_shared(Rules{story_define, volume_decl})) + } )); -std::shared_ptr NovalSyntax::getParseTree() { return document_define; } +std::shared_ptr NovalSyntax::getParseTree() { return document_define; } +std::shared_ptr example_novel::NovalSyntax::tidy(std::shared_ptr root, QList> children) +{ + for (auto& cinst : children) { + cinst->setParent(root); + if (!cinst->isAnonymous()) + ast_gen::GlobalElement::UniquePtr->appendToCache(cinst); + + QList> child_items; + for (auto& it : cinst->bindExpression()->children()) { + auto const_it = std::dynamic_pointer_cast(it); + child_items.append(std::const_pointer_cast(const_it)); + } + + tidy(cinst, child_items); + } + + return root; +} std::shared_ptr NovalSyntax::getLexReader() { - auto inst = std::make_shared(QList>() - << 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(QList>() + << leftb << rightb << refers << split_mark << story_key << frag_key << volume_key << article_key << numbers << name_text << vtext << newl); + return inst; } diff --git a/libSyntax/syntax_novel.h b/libSyntax/syntax_novel.h index 209f7a3..527aeea 100644 --- a/libSyntax/syntax_novel.h +++ b/libSyntax/syntax_novel.h @@ -1,6 +1,7 @@ #pragma once #include "ast_basic.h" +#include "ast_gen.h" #include "libsyntax.h" #include #include @@ -35,7 +36,9 @@ namespace example_novel { * @brief 获取novel语法解析树 * @return */ - static std::shared_ptr getParseTree(); + static std::shared_ptr getParseTree(); + + static std::shared_ptr tidy(std::shared_ptr root, QList> docs); }; } // namespace example_novel \ No newline at end of file