From 4e99a6f120a9ce5fb0c17bd2dc149ce9d0b1a4aa Mon Sep 17 00:00:00 2001 From: codeboss <2422523675@qq.com> Date: Thu, 20 Jun 2024 21:36:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=AD=E6=B3=95=E6=8C=87=E5=AF=BC=E7=9A=84?= =?UTF-8?q?=E6=BA=90=E4=BB=A3=E7=A0=81=E7=BF=BB=E8=AF=91=E5=99=A8=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsNovelParser/WsNovelParser.vcxproj.user | 2 +- WsNovelParser/novelparser.cpp | 8 +- libParse/parse_novel.cpp | 94 +++++++++++- libParse/parse_novel.h | 18 ++- libSyntax/ast_basic.cpp | 12 +- libSyntax/ast_basic.h | 33 +++-- libSyntax/ast_gen.cpp | 12 +- libSyntax/ast_gen.h | 15 +- libSyntax/ast_novel.cpp | 91 ++++++++---- libSyntax/ast_novel.h | 21 ++- libSyntax/libsyntax.cpp | 180 ++++++----------------- libSyntax/libsyntax.h | 56 +++---- libSyntax/syntax_novel.cpp | 31 ++-- libSyntax/syntax_novel.h | 8 - 14 files changed, 324 insertions(+), 257 deletions(-) diff --git a/WsNovelParser/WsNovelParser.vcxproj.user b/WsNovelParser/WsNovelParser.vcxproj.user index fe96f15..c94f467 100644 --- a/WsNovelParser/WsNovelParser.vcxproj.user +++ b/WsNovelParser/WsNovelParser.vcxproj.user @@ -3,7 +3,7 @@ $(SolutionDir)$(Platform)\$(Configuration)\ WindowsLocalDebugger - --path "D:\手作小说\科学+修仙+创造世界" + --path "D:\Projects\Cpp\WsNovelParser\x64\test_file" --path "D:\手作小说\科学+修仙+创造世界" diff --git a/WsNovelParser/novelparser.cpp b/WsNovelParser/novelparser.cpp index 8de0f6d..d252b68 100644 --- a/WsNovelParser/novelparser.cpp +++ b/WsNovelParser/novelparser.cpp @@ -12,6 +12,7 @@ NovelParser::NovelParser() { this->syntax_defines = example_novel::NovalSyntax::getParseTree(); checker_list << std::make_shared(); + checker_list << std::make_shared(); checker_list << std::make_shared(); analyzer_ref = std::make_shared(checker_list); @@ -24,13 +25,14 @@ QString NovelParser::version() const std::shared_ptr NovelParser::parse(const QFileInfoList source_list) const { QList> forst_root; - auto lex_reader = NovalSyntax::getLexReader(); + auto word_reader = std::make_shared(); auto context = std::make_shared(u8"С˵"); auto time_stamp = QTime::currentTime(); for (auto& file : source_list) { - auto tokens = lex_reader->tokensWithin(file.canonicalFilePath()); - auto exprs_result = this->syntax_defines->parse(context, tokens); + context->setCurrentFile(file.canonicalFilePath()); + auto words = word_reader->wordsFrom(file.canonicalFilePath()); + auto exprs_result = this->syntax_defines->parse(context, words); forst_root.append(std::get<0>(exprs_result)); } auto current_stamp = QTime::currentTime(); diff --git a/libParse/parse_novel.cpp b/libParse/parse_novel.cpp index b126154..42e1a42 100644 --- a/libParse/parse_novel.cpp +++ b/libParse/parse_novel.cpp @@ -4,6 +4,7 @@ #include #include +using namespace lib_parse; using namespace example_novel; using namespace ast_basic; using namespace ast_gen; @@ -15,7 +16,9 @@ void FragmentExistsCheck::exists_check(std::shared_ptr root if (target->element()->typeMark() == (int)NovelNode::FragmentRefer) { auto refer = std::dynamic_pointer_cast(target->element()); auto signature = refer->storyRefer() + u8"&" + refer->fragmentRefer(); - root->getNamedNodeBy((int)NovelNode::FragmentDefine, signature); + if(!root->getNamedNodeBy((int)NovelNode::FragmentDefine, signature)) + throw new SyntaxException(QString(u8"CheckError[0x0005]ϵͳвָǩĽڵ㣺%1{%3:(%4)}") + .arg(signature).arg((int)NovelNode::FragmentDefine).arg(refer->signature()).arg(refer->filePath())); } for (auto& xit : target->children()) { @@ -28,7 +31,7 @@ void FragmentExistsCheck::validCheck(std::shared_ptr root) } QString FragmentExistsCheck::name() const { - return u8"FragmentExistsCheck"; + return u8"ЧԼ"; } QList> FragmentGraphCheck::refers_cycle_check( @@ -188,19 +191,19 @@ void FragmentGraphCheck::validCheck(std::shared_ptr root) c for (auto node : elements_store.values()) { auto cycle_link = refers_cycle_check(node); - QString error_msg = u8"Parse[0x0006]ͼڻνṹ\n"; + QString error_msg = u8"CheckError[0x0006]ôڻνṹ\n"; for (auto n : cycle_link) { error_msg += QString(u8"%1->").arg(n->nodePeer()->signature()); } if (cycle_link.size()) - throw new lib_parse::CheckException(error_msg); + throw new CheckException(error_msg); } } } QString FragmentGraphCheck::name() const { - return u8"FragmentGraphCheck"; + return u8"ЧԼ"; } FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr node) : node_peer(node) {} @@ -223,3 +226,84 @@ uint& FragmentGraphHelper::inDegree() { return this->indegree; } + +QList> StoryOrderCheck::valid_docs_peak(std::shared_ptr pnode) const { + QList> values; + auto type_code = pnode->element()->typeMark(); + + switch ((NovelNode)type_code) { + case NovelNode::GlobalElement:{ + auto children = pnode->children(); + for(auto &cinst : children){ + values.append(valid_docs_peak(cinst)); + } + }break; + + case NovelNode::Document: { + auto storys_collection = pnode->children(); + + bool story_exists = false; + for (auto& syntax_elm : storys_collection) { + if (syntax_elm->element()->typeMark() == (int)NovelNode::StoryDefine) { + story_exists = true; + break; + } + } + + if (story_exists) { + auto first_elm = storys_collection.at(0); + values.append(pnode); + + if(first_elm->element()->typeMark() != (int)NovelNode::RankDeclaration) + throw new CheckException(QString(u8"CheckError[0x0007]й½ڵĵڵһָ%1").arg(pnode->element()->path())); + } + }break; + + default: + break; + } + + return values; +} + +QString StoryOrderCheck::name() const +{ + return u8"ЧԼ"; +} + +void StoryOrderCheck::validCheck(std::shared_ptr root) const +{ + const_cast(this)->sort_index = 1; + + auto story_docs = valid_docs_peak(root); + std::sort(story_docs.begin(), story_docs.end(), [](std::shared_ptr adoc, std::shared_ptr bdoc){ + auto elm_xa = std::dynamic_pointer_cast(adoc->children().first()->element()); + auto elm_xb = std::dynamic_pointer_cast(bdoc->children().first()->element()); + return elm_xa->rankNumber() < elm_xb->rankNumber(); + }); + + // page_rank valid + int page_rank = 0; + for (auto& item : story_docs) { + auto elm_xa = std::dynamic_pointer_cast(item->children().first()->element()); + if (page_rank >= elm_xa->rankNumber()) { + throw new CheckException(QString(u8"CheckError[0x0009]ĵֱ0ͬĵظ{%1}").arg(elm_xa->path())); + } + } + + // ½ڵ + auto story_node_sort = [](std::shared_ptr doc_node, int start_index) -> int{ + auto childs = doc_node->children(); + for (auto &inst : childs) { + if (inst->element()->typeMark() == (int)NovelNode::StoryDefine) { + auto cast_inst = std::dynamic_pointer_cast(inst->element()); + std::const_pointer_cast(cast_inst)->setSort(start_index++); + } + } + return start_index; + }; + + int ranks_number = 1; + for(auto &story : story_docs) + ranks_number = story_node_sort(story, ranks_number); +} diff --git a/libParse/parse_novel.h b/libParse/parse_novel.h index 65c4963..17de0c9 100644 --- a/libParse/parse_novel.h +++ b/libParse/parse_novel.h @@ -4,7 +4,6 @@ #include namespace example_novel { - class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider { private: void exists_check(std::shared_ptr root, std::shared_ptr target) const; @@ -15,6 +14,7 @@ namespace example_novel { virtual QString name() const override; }; + class FragmentGraphHelper; class LIBPARSE_EXPORT FragmentGraphCheck : public std::enable_shared_from_this, public lib_parse::CheckProvider { private: @@ -54,4 +54,20 @@ namespace example_novel { }; + class LIBPARSE_EXPORT StoryOrderCheck : public lib_parse::CheckProvider { + private: + uint sort_index = 1; + /** + * ȡʵĵڵ. + * + * \param pnode + * \return + */ + QList> valid_docs_peak(std::shared_ptr pnode) const; + + public: + // ͨ CheckProvider ̳ + QString name() const override; + void validCheck(std::shared_ptr root) const override; + }; } // namespace example_novel diff --git a/libSyntax/ast_basic.cpp b/libSyntax/ast_basic.cpp index 18b19ec..f695f70 100644 --- a/libSyntax/ast_basic.cpp +++ b/libSyntax/ast_basic.cpp @@ -18,11 +18,11 @@ QString ast_basic::ExpressionElement::filePath() const { return tokens_bind.first()->file(); } -void ast_basic::ExpressionElement::tokensReset(const QList>& list) { +void ast_basic::ExpressionElement::tokensReset(const QList>& list) { this->tokens_bind = list; } -void ast_basic::ExpressionElement::addToken(std::shared_ptr token_inst) { +void ast_basic::ExpressionElement::addToken(std::shared_ptr token_inst) { this->tokens_bind.append(token_inst); } @@ -34,10 +34,16 @@ void ast_basic::ExpressionElement::addChild(std::shared_ptr in this->children_store.append(inst); } -QList> ExpressionElement::tokens() const { +QList> ExpressionElement::tokens() const { return this->tokens_bind; } +ast_basic::ExpressionContext::ExpressionContext() {} + +void ast_basic::ExpressionContext::setCurrentFile(const QString& path) { this->current_file_path = path; } + +QString ast_basic::ExpressionContext::currentFile() const { return this->current_file_path; } + std::shared_ptr ast_basic::ExpressionContext::currentInst() const { if(expression_stack.size()) diff --git a/libSyntax/ast_basic.h b/libSyntax/ast_basic.h index 4146b2b..d5f5110 100644 --- a/libSyntax/ast_basic.h +++ b/libSyntax/ast_basic.h @@ -19,7 +19,6 @@ namespace ast_basic { * @return */ virtual std::shared_ptr definedRule() const = 0; - //===================================================== /** * ȡ﷨ڵԴļ·. @@ -32,15 +31,19 @@ namespace ast_basic { * * \return token */ - virtual QList> tokens() const = 0; - virtual void tokensReset(const QList> &list) = 0; + virtual QList> tokens() const = 0; + /** + * ﷨Token. + * + * \param list + */ + virtual void tokensReset(const QList> &list) = 0; /** * Уʽڲtokenʵ. * * \param token_inst ʵ */ - virtual void addToken(std::shared_ptr token_inst) = 0; - + virtual void addToken(std::shared_ptr token_inst) = 0; //===================================================== /** * @brief ӱʽ @@ -60,29 +63,24 @@ namespace ast_basic { /** * @brief ʽڵ */ - class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression, - public std::enable_shared_from_this { + class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression, public std::enable_shared_from_this { private: std::shared_ptr _expr_rule; QList> children_store; - QList> tokens_bind; + QList> tokens_bind; public: ExpressionElement(std::shared_ptr bind); // ͨ 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> 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; }; @@ -90,10 +88,13 @@ namespace ast_basic { private: QList> rule_stack; QList> expression_stack; + QString current_file_path; public: - ExpressionContext(){} + ExpressionContext(); + virtual void setCurrentFile(const QString& path); + virtual QString currentFile() const; // ͨ ParseContext ̳ std::shared_ptr currentInst() const override; diff --git a/libSyntax/ast_gen.cpp b/libSyntax/ast_gen.cpp index e406c07..1e3a521 100644 --- a/libSyntax/ast_gen.cpp +++ b/libSyntax/ast_gen.cpp @@ -10,18 +10,18 @@ GlobalElement::GlobalElement(const QString& name) :names_store(name) { void GlobalElement::clearCache() { node_cache.clear(); } -void GlobalElement::appendToCache(std::shared_ptr named_node) { +std::shared_ptr 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())); + return node_cache[mixed_key]; node_cache[mixed_key] = named_node; + return nullptr; } 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 nullptr; return node_cache[mixed_key]; } @@ -73,10 +73,10 @@ QList> ElementAccess::tokens() const { return element()->selfTokens(); } -TokenAccess::TokenAccess(std::shared_ptr elm_inst, std::shared_ptr token_inst) +TokenAccess::TokenAccess(std::shared_ptr elm_inst, std::shared_ptr token_inst) : element_bind(elm_inst), token_store(token_inst) {} std::shared_ptr TokenAccess::bind() const { return element_bind; } -std::shared_ptr TokenAccess::token() const { return token_store; } +std::shared_ptr TokenAccess::token() const { return token_store; } diff --git a/libSyntax/ast_gen.h b/libSyntax/ast_gen.h index 7bf8bf6..d748556 100644 --- a/libSyntax/ast_gen.h +++ b/libSyntax/ast_gen.h @@ -53,6 +53,11 @@ namespace ast_gen * @return δparentnullptr */ virtual std::shared_ptr parent() const = 0; + /** + * @brief øָ. + * + * \param inst + */ virtual void setParent(std::shared_ptr inst) = 0; /** @@ -74,7 +79,6 @@ namespace ast_gen ElementAccess(std::shared_ptr point); std::shared_ptr element() const; - QList> children() const; /** @@ -87,12 +91,12 @@ namespace ast_gen class LIBSYNTAX_EXPORT TokenAccess { private: std::shared_ptr element_bind; - std::shared_ptr token_store; + std::shared_ptr token_store; public: - TokenAccess(std::shared_ptr elm_inst, std::shared_ptr token_inst); + TokenAccess(std::shared_ptr elm_inst, std::shared_ptr token_inst); virtual std::shared_ptr bind() const; - virtual std::shared_ptr token() const; + virtual std::shared_ptr token() const; }; /** @@ -110,7 +114,7 @@ namespace ast_gen GlobalElement(const QString& name); virtual void clearCache(); - virtual void appendToCache(std::shared_ptr named_node); + virtual std::shared_ptr appendToCache(std::shared_ptr named_node); /** * @brief ͨڵǩȡڵ * @param signature ȫǩ @@ -118,7 +122,6 @@ namespace ast_gen * @throws ûָڵ׳쳣 */ virtual std::shared_ptr getNamedNodeBy(int type, const QString& signature) const; - virtual void addChild(std::shared_ptr citem); // ParseElement interface diff --git a/libSyntax/ast_novel.cpp b/libSyntax/ast_novel.cpp index 737b532..25a9e78 100644 --- a/libSyntax/ast_novel.cpp +++ b/libSyntax/ast_novel.cpp @@ -2,25 +2,26 @@ using namespace example_novel; +using namespace lib_syntax; -TextSection::TextSection(std::shared_ptr rule_bind) +TextSection::TextSection(std::shared_ptr rule_bind) : AbstractImpl(rule_bind) {} -QString example_novel::TextSection::content() const +QString TextSection::content() const { return context_store; } int TextSection::typeMark() const { return (int)NovelNode::TextSection; } -bool example_novel::TextSection::isAnonymous() const +bool TextSection::isAnonymous() const { return true; } QString TextSection::signature() const { return u8"::section"; } -void example_novel::TextSection::cacheLoad() +void TextSection::cacheLoad() { QString text; for (auto& t : selfTokens()) { @@ -29,14 +30,14 @@ void example_novel::TextSection::cacheLoad() context_store = text; } -FragmentRefers::FragmentRefers(std::shared_ptr rule_bind) +FragmentRefers::FragmentRefers(std::shared_ptr rule_bind) : AbstractImpl(rule_bind) {} QString FragmentRefers::storyRefer() const { return story_refs; } QString FragmentRefers::fragmentRefer() const { return fragment_ref; } -void example_novel::FragmentRefers::cacheLoad() +void FragmentRefers::cacheLoad() { this->story_refs = selfTokens()[5]->token()->content(); this->fragment_ref = selfTokens()[3]->token()->content(); @@ -47,7 +48,7 @@ QString FragmentRefers::referSignature() const { int FragmentRefers::typeMark() const { return (int)NovelNode::FragmentRefer; } -bool example_novel::FragmentRefers::isAnonymous() const +bool FragmentRefers::isAnonymous() const { return true; } @@ -58,18 +59,18 @@ QString FragmentRefers::signature() const { } -FragmentDefine::FragmentDefine(std::shared_ptr rule_bind) +FragmentDefine::FragmentDefine(std::shared_ptr rule_bind) : AbstractImpl(rule_bind) {} QString FragmentDefine::name() const { return name_store; } -void example_novel::FragmentDefine::cacheLoad() +void FragmentDefine::cacheLoad() { name_store = selfTokens()[2]->token()->content(); } int FragmentDefine::typeMark() const { return (int)NovelNode::FragmentDefine; } -bool example_novel::FragmentDefine::isAnonymous() const +bool FragmentDefine::isAnonymous() const { return false; } @@ -77,14 +78,18 @@ bool example_novel::FragmentDefine::isAnonymous() const QString FragmentDefine::signature() const { return parent()->signature() + u8"&" + name(); } -StoryDefine::StoryDefine(std::shared_ptr rule_bind) - : AbstractImpl(rule_bind) {} +StoryDefine::StoryDefine(std::shared_ptr rule_bind) + : AbstractImpl(rule_bind), sort_index(0) {} QString StoryDefine::name() const { return name_store; } +void example_novel::StoryDefine::setSort(int value){ + sort_index = value; +} + int StoryDefine::sort() const { return sort_index; } -void example_novel::StoryDefine::cacheLoad() +void StoryDefine::cacheLoad() { name_store = selfTokens()[3]->token()->content(); sort_index = selfTokens()[2]->token()->content().toInt(); @@ -92,7 +97,7 @@ void example_novel::StoryDefine::cacheLoad() int StoryDefine::typeMark() const { return (int)NovelNode::StoryDefine; } -bool example_novel::StoryDefine::isAnonymous() const +bool StoryDefine::isAnonymous() const { return false; } @@ -100,23 +105,23 @@ bool example_novel::StoryDefine::isAnonymous() const QString StoryDefine::signature() const { return name(); } #include "syntax_novel.h" -Document::Document(std::shared_ptr rule_bind) +Document::Document(std::shared_ptr rule_bind) : AbstractImpl(rule_bind) {} int Document::typeMark() const { return (int)NovelNode::Document; } -bool example_novel::Document::isAnonymous() const +bool Document::isAnonymous() const { return true; } QString Document::signature() const { return QString(u8"::document<%1>").arg(path()); } -void example_novel::Document::cacheLoad() +void Document::cacheLoad() { } -example_novel::AbstractImpl::AbstractImpl(std::shared_ptr rule_bind) +AbstractImpl::AbstractImpl(std::shared_ptr rule_bind) : ExpressionElement(rule_bind) { parent_store.reset(); } QList > AbstractImpl::selfTokens() const { @@ -129,61 +134,91 @@ QList > AbstractImpl::selfTokens() c return values; } -std::shared_ptr example_novel::AbstractImpl::parent() const +std::shared_ptr AbstractImpl::parent() const { return this->parent_store.lock(); } -void example_novel::AbstractImpl::setParent(std::shared_ptr inst) +void AbstractImpl::setParent(std::shared_ptr inst) { this->parent_store = inst; } // ͨ SyntaxElement ̳ -std::shared_ptr example_novel::AbstractImpl::bindExpression() const { +std::shared_ptr AbstractImpl::bindExpression() const { return shared_from_this(); } -QString example_novel::AbstractImpl::path() const +QString AbstractImpl::path() const { return ast_basic::ExpressionElement::filePath(); } -VolumeDefine::VolumeDefine(std::shared_ptr rule_bind) +VolumeDefine::VolumeDefine(std::shared_ptr rule_bind) : AbstractImpl(rule_bind) {} QString VolumeDefine::name() const { return name_store; } -void example_novel::VolumeDefine::cacheLoad() +void VolumeDefine::cacheLoad() { name_store = selfTokens()[2]->token()->content(); } int VolumeDefine::typeMark() const { return (int)NovelNode::VolumeDefine; } -bool example_novel::VolumeDefine::isAnonymous() const +bool VolumeDefine::isAnonymous() const { return false; } QString VolumeDefine::signature() const { return name(); } -ArticleDefine::ArticleDefine(std::shared_ptr rule_bind) +ArticleDefine::ArticleDefine(std::shared_ptr rule_bind) : AbstractImpl(rule_bind) {} QString ArticleDefine::name() const { return name_store; } -void example_novel::ArticleDefine::cacheLoad() +void ArticleDefine::cacheLoad() { name_store = selfTokens()[2]->token()->content(); } int ArticleDefine::typeMark() const { return (int)NovelNode::ArticleDefine; } -bool example_novel::ArticleDefine::isAnonymous() const +bool ArticleDefine::isAnonymous() const { return false; } QString ArticleDefine::signature() const { return parent()->signature() + u8"&" + name(); } + +RankDeclare::RankDeclare(std::shared_ptr rule) +: AbstractImpl(rule) +{ +} + +int example_novel::RankDeclare::rankNumber() const +{ + return page_rank; +} + +int RankDeclare::typeMark() const +{ + return (int)NovelNode::RankDeclaration; +} + +bool RankDeclare::isAnonymous() const +{ + return true; +} + +QString RankDeclare::signature() const +{ + return u8"::rank"; +} + +void RankDeclare::cacheLoad() +{ + page_rank = selfTokens()[2]->token()->content().toInt(); +} diff --git a/libSyntax/ast_novel.h b/libSyntax/ast_novel.h index 9fc4859..47c10ea 100644 --- a/libSyntax/ast_novel.h +++ b/libSyntax/ast_novel.h @@ -5,6 +5,7 @@ namespace example_novel { enum class NovelNode { + GlobalElement = 0, TextSection = 1, FragmentRefer = 2, FragmentDefine = 3, @@ -12,10 +13,10 @@ namespace example_novel Document = 5, ArticleDefine = 6, VolumeDefine = 7, + RankDeclaration = 8, }; - class LIBSYNTAX_EXPORT AbstractImpl : - public ast_basic::ExpressionElement, public ast_gen::SyntaxElement { + class LIBSYNTAX_EXPORT AbstractImpl : public ast_basic::ExpressionElement, public ast_gen::SyntaxElement { private: std::weak_ptr parent_store; @@ -123,6 +124,7 @@ namespace example_novel StoryDefine(std::shared_ptr rule_bind); QString name() const; + void setSort(int value); int sort() const; // SyntaxElement interface @@ -148,4 +150,19 @@ namespace example_novel virtual QString signature() const override; virtual void cacheLoad() override; }; + + class LIBSYNTAX_EXPORT RankDeclare : public AbstractImpl { + private: + int page_rank = 0; + public: + RankDeclare(std::shared_ptr rule); + + int rankNumber() const; + + // ͨ AbstractImpl ̳ + int typeMark() const override; + bool isAnonymous() const override; + QString signature() const override; + void cacheLoad() override; + }; } diff --git a/libSyntax/libsyntax.cpp b/libSyntax/libsyntax.cpp index 146aae7..5649b00 100644 --- a/libSyntax/libsyntax.cpp +++ b/libSyntax/libsyntax.cpp @@ -6,30 +6,28 @@ using namespace std; using namespace lib_token; using namespace ast_basic; -TokenMatch::TokenMatch(shared_ptr define) : define_peer(define) {} +TokenMatch::TokenMatch(shared_ptr define) : define_peer(define) {} QList> TokenMatch::children() const { return QList>(); } -std::tuple> TokenMatch::match(std::shared_ptr remains_head) const { - QString token_seqs = this->token_present(); - if (remains_head && remains_head->define()->typeMark() == define_peer->typeMark()) - return std::make_tuple(MatchResult::Success, 1, remains_head->nextToken()); - - return std::make_tuple(MatchResult::Fail, 0, nullptr); - // auto mis_match = define_peer->name(); - // auto real_match = stream.first()->define()->name(); -} -// std::tuple, std::shared_ptr> -std::tuple, std::shared_ptr> TokenMatch::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { +std::tuple, std::shared_ptr> TokenMatch::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { if (!head) - throw std::make_shared(); + throw new InputTerminal(rt_inst->currentFile()); - if (head->define()->typeMark() == define_peer->typeMark()) { - rt_inst->currentInst()->addToken(head); - return std::make_tuple(nullptr, head->nextToken()); + auto match_result = define_peer->analysis(head); + if (std::get<0>(match_result)) { + rt_inst->currentInst()->addToken(std::get<0>(match_result)); + } + else { + throw new MismatchException(head); } - throw std::make_shared(head); + if (std::get<1>(match_result)) { + return std::make_tuple(nullptr, std::make_shared(std::get<1>(match_result), head->nextWord())); + } + else { + return std::make_tuple(nullptr, head->nextWord()); + } } QString TokenMatch::token_present() const { @@ -40,41 +38,7 @@ Rept::Rept(std::shared_ptr rule, int min, int max) : rule_peer(r QList> Rept::children() const { return QList>() << rule_peer; } -std::tuple> Rept::match(std::shared_ptr list_head) const { - auto token_offset = 0; - QString token_seqs = this->token_present(); - auto temp_head = list_head; - - // min-match - for (auto idx = 0; idx < min_match; ++idx) { - auto result = rule_peer->match(temp_head); - token_offset += std::get<1>(result); - temp_head = std::get<2>(result); - - if (std::get<0>(result) != MatchResult::Success) { - return std::make_tuple(token_offset ? MatchResult::Part : MatchResult::Fail, token_offset, temp_head); - } - } - - // max-match - for (auto idx = min_match; idx < max_match; ++idx) { - auto result = rule_peer->match(temp_head); - - switch (std::get<0>(result)) { - case MatchResult::Fail: - case MatchResult::Part: - return std::make_tuple(MatchResult::Success, token_offset, temp_head); - default: - temp_head = std::get<2>(result); - token_offset += std::get<1>(result); - break; - } - } - - return std::make_tuple(MatchResult::Success, token_offset, temp_head); -} - -std::tuple, std::shared_ptr> Rept::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { +std::tuple, std::shared_ptr> Rept::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { auto temp_head = head; // min-match @@ -95,10 +59,8 @@ std::tuple, std::shared_ptr> Rept temp_head = std::get<1>(result_gen); } - catch (std::shared_ptr ex) { - return std::make_tuple(nullptr, temp_head); - } - catch (std::shared_ptr ex) { + catch (SyntaxException* ex) { + delete ex; return std::make_tuple(nullptr, temp_head); } } @@ -115,30 +77,7 @@ Seqs::Seqs(const QList> mbrs) : mbrs_store(mbrs) QList> Seqs::children() const { return mbrs_store; } -std::tuple> Seqs::match(std::shared_ptr list_head) const { - auto token_offset = 0; - QString token_seqs = this->token_present(); - auto temp_head = list_head; - - for (auto& r : mbrs_store) { - auto v_token_seqs = r->token_present(); - auto result = r->match(list_head); - token_offset += std::get<1>(result); - temp_head = std::get<2>(result); - - switch (std::get<0>(result)) { - case MatchResult::Fail: - case MatchResult::Part: - return std::make_tuple(token_offset ? MatchResult::Part : MatchResult::Fail, token_offset, temp_head); - default: - break; - } - } - - return std::make_tuple(MatchResult::Success, token_offset, temp_head); -} - -std::tuple, std::shared_ptr> Seqs::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { +std::tuple, std::shared_ptr> Seqs::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { auto temp_head = head; for (auto& r : mbrs_store) { @@ -160,53 +99,30 @@ QString Seqs::token_present() const return QString(u8"(%1)").arg(content); } -std::tuple, std::shared_ptr> -Any::rule_select(std::shared_ptr head) const { - QString token_seqs = this->token_present(); - std::tuple, std::shared_ptr> temp = std::make_tuple(MatchResult::Fail, 0, nullptr, nullptr); - - for (auto& r : mbrs_store) { - auto mbr_seqs = r->token_present(); - auto result = r->match(head); - if (std::get<0>(result) == MatchResult::Success) - return std::make_tuple(std::get<0>(result), std::get<1>(result), r, std::get<2>(result)); - - else if (std::get<0>(result) == MatchResult::Part) { - if (std::get<0>(temp) == MatchResult::Fail || std::get<1>(result) > std::get<1>(temp)) - temp = std::make_tuple(MatchResult::Part, std::get<1>(result), r, std::get<2>(result)); - else - temp = std::make_tuple(MatchResult::Part, std::get<1>(temp), std::get<2>(temp), std::get<3>(temp)); - } - - else if (std::get<0>(temp) == MatchResult::Fail) { - if (!std::get<2>(temp) || std::get<1>(result) > std::get<1>(temp)) - temp = std::make_tuple(MatchResult::Fail, std::get<1>(result), r, std::get<2>(result)); - else - temp = std::make_tuple(MatchResult::Fail, std::get<1>(temp), std::get<2>(temp), std::get<3>(temp)); - } - } - - return temp; -} - +//std::tuple, std::shared_ptr> Any::Any(const QList> mbrs) : mbrs_store(mbrs) {} QList> Any::children() const { return mbrs_store; } -std::tuple> Any::match(std::shared_ptr list_head) const { - auto item = rule_select(list_head); - return std::make_tuple(std::get<0>(item), std::get<1>(item), std::get<3>(item)); -} - -std::tuple, std::shared_ptr> Any::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { - std::function, std::shared_ptr)> measure_span = - [&](std::shared_ptr anchor, std::shared_ptr head)->int { - if (anchor == head) - return 1; - return measure_span(anchor, head->nextToken()) + 1; +class words_span { +public: + int row_span, column_span; + words_span(int rspan, int cspan):row_span(rspan), column_span(cspan){} + bool operator>(const words_span& other) { + if(row_span > other.row_span) + return true; + if(row_span == other.row_span) + return column_span > other.column_span; + return false; + } +}; +std::tuple, std::shared_ptr> Any::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { + std::function, std::shared_ptr)> measure_span = + [&](std::shared_ptr anchor, std::shared_ptr head)->words_span { + return words_span(anchor->row() - head->row(), anchor->column() - head->column()); }; - std::tuple, int> temp_result = std::make_tuple(mbrs_store.first(), 0); + std::tuple, words_span> temp_result = std::make_tuple(mbrs_store.first(), words_span(0,0)); for (auto& fork : mbrs_store) { try { auto gen = fork->parse(rt_inst, head); @@ -217,11 +133,13 @@ std::tuple, std::shared_ptr> Any: return std::make_tuple(nullptr, std::get<1>(gen)); } // ﷨ĻбȽ - catch (std::shared_ptr ex) { - auto current_span = measure_span(ex->targetToken(), head); + catch (MismatchException* ex) { + auto current_span = measure_span(ex->targetWord(), head); if (current_span > std::get<1>(temp_result)) temp_result = std::make_tuple(fork, current_span); + + delete ex; } } @@ -263,11 +181,7 @@ QList> ExpressionRule::children() const { return QList>() << this->child_store; } -std::tuple> ExpressionRule::match(std::shared_ptr list_head) const { - return child_store->match(list_head); -} - -std::tuple, std::shared_ptr> ExpressionRule::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { +std::tuple, std::shared_ptr> ExpressionRule::parse(std::shared_ptr rt_inst, std::shared_ptr head) const { std::shared_ptr elm_ast = this->newEmptyInstance(); rt_inst->pushExpressionRule(this->shared_from_this()); @@ -294,11 +208,13 @@ QString ExpressionRule::token_present() const { return QString(u8"(%1)").arg(child_store->token_present()); } -MismatchException::MismatchException(std::shared_ptr inst) :SyntaxException( - QString(u8"Syntax[0x00001]﷨ƥ󣬲ʶtoken%1<%2,%3>").arg(inst->content()).arg(inst->row()).arg(inst->column())), target(inst) {} +MismatchException::MismatchException(std::shared_ptr inst) :SyntaxException( + QString(u8"Syntax[0x00001]﷨ƥ󣬲ʶtoken%1<%2,%3>(%4)") + .arg(inst->content()).arg(inst->row()).arg(inst->column()).arg(inst->file())), target(inst) {} -std::shared_ptrMismatchException::targetToken() const { +std::shared_ptrMismatchException::targetWord() const { return this->target; } -InputTerminal::InputTerminal() :SyntaxException(u8"Syntax[0x0000]tokenǰֹ") {} \ No newline at end of file +InputTerminal::InputTerminal(const QString& file_path) + :SyntaxException(QString(u8"Syntax[0x0000]token%1ǰֹ").arg(file_path)) {} diff --git a/libSyntax/libsyntax.h b/libSyntax/libsyntax.h index 27e91c6..56da438 100644 --- a/libSyntax/libsyntax.h +++ b/libSyntax/libsyntax.h @@ -16,7 +16,7 @@ namespace lib_syntax { /** * @brief ﷨쳣 */ - class SyntaxException { + class LIBSYNTAX_EXPORT SyntaxException { private: QString msg_store; @@ -35,6 +35,9 @@ namespace lib_syntax { public: virtual ~ParseContext() = default; + virtual void setCurrentFile(const QString &path) = 0; + virtual QString currentFile() const = 0; + /** * \brief ǰʽԪ. * @@ -70,20 +73,14 @@ namespace lib_syntax { Fail // ӵһȫƥ }; - /** - * @brief tokenƥ - * @return ײ룬ƥtoken<ƥƥ䳤ȣʣбͷָ> - */ - virtual std::tuple> match(std::shared_ptr remains_head) const = 0; - /** * @brief * @param rt_inst * @param head бͷ * @return ؽ<ƥбͷ,ƥ䳤> */ - virtual std::tuple, std::shared_ptr> - parse(std::shared_ptr rt_inst, std::shared_ptr head) const = 0; + virtual std::tuple, std::shared_ptr> + parse(std::shared_ptr rt_inst, std::shared_ptr head) const = 0; /** * ƥ﷨Ĵʷб @@ -99,17 +96,16 @@ namespace lib_syntax { */ class LIBSYNTAX_EXPORT TokenMatch : public BaseRule, public std::enable_shared_from_this { private: - std::shared_ptr define_peer; + std::shared_ptr define_peer; public: - TokenMatch(std::shared_ptr define); + TokenMatch(std::shared_ptr define); // BaseRule interface public: virtual QList> children() const override; - virtual std::tuple> match(std::shared_ptr head) const override; - virtual std::tuple, std::shared_ptr> - parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; + virtual std::tuple, std::shared_ptr> + parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; }; @@ -120,7 +116,7 @@ namespace lib_syntax { private: QList> mbrs_store; - std::tuple, std::shared_ptr> rule_select(std::shared_ptr head) const; + std::tuple, std::shared_ptr> rule_select(std::shared_ptr head) const; public: Any(const QList> mbrs); @@ -128,9 +124,8 @@ namespace lib_syntax { // BaseRule interface public: virtual QList> children() const override; - virtual std::tuple> match(std::shared_ptr list_head) const override; - virtual std::tuple, std::shared_ptr> - parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; + virtual std::tuple, std::shared_ptr> + parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; }; @@ -147,9 +142,8 @@ namespace lib_syntax { // BaseRule interface public: virtual QList> children() const override; - virtual std::tuple> match(std::shared_ptr list_head) const override; - virtual std::tuple, std::shared_ptr> - parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; + virtual std::tuple, std::shared_ptr> + parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; }; @@ -167,9 +161,8 @@ namespace lib_syntax { // BaseRule interface public: virtual QList> children() const override; - virtual std::tuple> match(std::shared_ptr list_head) const override; - virtual std::tuple, std::shared_ptr> - parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; + virtual std::tuple, std::shared_ptr> + parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; }; @@ -179,7 +172,7 @@ namespace lib_syntax { */ class LIBSYNTAX_EXPORT ExpressionRule : public lib_syntax::BaseRule, public std::enable_shared_from_this { public: - typedef QList> TokenSeqs; + typedef QList> TokenSeqs; ExpressionRule(const QString& rule_name, int expr_mark); virtual std::shared_ptr reloadRule(std::function filter, std::shared_ptr rule); @@ -192,9 +185,8 @@ namespace lib_syntax { // BaseRule interface public: virtual QList> children() const override; - virtual std::tuple> match(std::shared_ptr remains_head) const override; - virtual std::tuple, std::shared_ptr> - parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; + virtual std::tuple, std::shared_ptr> + parse(std::shared_ptr rt_inst, std::shared_ptr head) const override; virtual QString token_present() const override; private: @@ -226,17 +218,17 @@ namespace lib_syntax { class MismatchException : public SyntaxException { private: - std::shared_ptr target; + std::shared_ptr target; public: - MismatchException(std::shared_ptr inst); + MismatchException(std::shared_ptr inst); virtual ~MismatchException() = default; - virtual std::shared_ptr targetToken() const; + virtual std::shared_ptr targetWord() const; }; class InputTerminal : public SyntaxException { public: - InputTerminal(); + InputTerminal(const QString &file_path); }; } // namespace lib_syntax \ No newline at end of file diff --git a/libSyntax/syntax_novel.cpp b/libSyntax/syntax_novel.cpp index 242ab2c..2ea1395 100644 --- a/libSyntax/syntax_novel.cpp +++ b/libSyntax/syntax_novel.cpp @@ -11,7 +11,9 @@ using namespace ast_basic; auto leftb = std::make_shared(); // { auto rightb = std::make_shared(); // } auto refers = std::make_shared(); // @ +auto declare = std::make_shared(); // # +auto rank_key = std::make_shared(u8"", u8"rank-symbol", 0xAEu); // auto story_key = std::make_shared(u8"", u8"story-mark", 0xAAu); // auto numbers = std::make_shared(); // [0-9]+ auto frag_key = std::make_shared(u8"", u8"fragment-mark", 0xABu); // @@ -96,21 +98,25 @@ auto volume_decl = ElementRule(u8"volume_define", (int)NovelExprs: LinesMerge(MR(rightb)) )); +auto rank_define = ElementRule(u8"rank_define", (int)NovelNode::RankDeclaration).reloadRule(remove_nl, std::make_shared( + Rules{ MR(declare), MR(rank_key), MR(numbers), OptMulT(newl)} +)); + auto document_define = ElementRule(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(remove_nl, std::make_shared( Rules{ - OptMulT(newl), + std::make_shared(rank_define, 0, 1), MultiR(std::make_shared(Rules{story_define, volume_decl})) } )); std::shared_ptr NovalSyntax::getParseTree() { return document_define; } -std::shared_ptr example_novel::NovalSyntax::tidy(std::shared_ptr root, QList> children) +std::shared_ptr NovalSyntax::tidy(std::shared_ptr root, QList> children) { cache_load(root, children); node_register(root, children); return root; } -void example_novel::NovalSyntax::cache_load(std::shared_ptr root, QList> children) +void NovalSyntax::cache_load(std::shared_ptr root, QList> children) { root->cacheLoad(); for (auto& cinst : children) { @@ -125,11 +131,15 @@ void example_novel::NovalSyntax::cache_load(std::shared_ptr root, QList> children) +void NovalSyntax::node_register(std::shared_ptr root, QList> children) { for (auto& child : children) { - if (!child->isAnonymous()) - ast_gen::GlobalElement::UniquePtr->appendToCache(child); + if (!child->isAnonymous()) { + auto check_result = ast_gen::GlobalElement::UniquePtr->appendToCache(child); + if(check_result) + throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0004]ϵͳаͬڵ㣺%1(%3,%4)") + .arg(child->signature()).arg(child->typeMark()).arg(child->path()).arg(check_result->path())); + } QList> next_child_items; for (auto& it : child->bindExpression()->children()) { @@ -139,11 +149,4 @@ void example_novel::NovalSyntax::node_register(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; -} - +} \ No newline at end of file diff --git a/libSyntax/syntax_novel.h b/libSyntax/syntax_novel.h index 68c9f0d..f46271c 100644 --- a/libSyntax/syntax_novel.h +++ b/libSyntax/syntax_novel.h @@ -24,14 +24,6 @@ namespace example_novel { class LIBSYNTAX_EXPORT NovalSyntax { public: - /** - * @brief ȡnovelʷ - * @param path ļ· - * @param name ļ - * @return - */ - static std::shared_ptr getLexReader(); - /** * @brief ȡnovel﷨ * @return