#include "syntax_novel.h" #include #include "ast_novel.h" using namespace lib_syntax; using namespace example_novel; using namespace lib_token; using namespace ast_basic; // token-avaliable ========================================================================== auto leftb = std::make_shared(); // { auto rightb = std::make_shared(); // } auto refers = std::make_shared(); // @ auto story_key = std::make_shared(u8"故事", u8"story-mark"); // 故事 auto numbers = std::make_shared(); // [0-9]+ auto frag_key = std::make_shared(u8"情节", u8"fragment-mark"); // 情节 auto volume_key = std::make_shared(u8"分卷", u8"volume-mark"); // 分卷 auto article_key = std::make_shared(u8"章节", u8"article-mark"); // 章节 auto split_mark = std::make_shared(); // & auto vtext = std::make_shared(); // ^([^\\{\\}\\n@&]+) auto name_text = std::make_shared(); // ^([^:\\{\\}\\n@&][^\\{\\}\\n@&]*) auto newl = std::make_shared(); // rule-parts =============================================================================== // MatchRule #define MR(x) std::make_shared(x) // Buffer #define Rules QList> // Option #define OptMulT(token) std::make_shared(MR(token), 0, INT_MAX) #define OptMulR(rule) std::make_shared(rule, 0, INT_MAX) // multi+ #define MultiR(rule) std::make_shared(rule, 1, INT_MAX) QList> LinesMerge(const QList>& mbrs) { 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); } // remove-return 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 = 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_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_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 = 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 = 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 = 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 example_novel::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) { std::const_pointer_cast(root)->cacheLoad(); for (auto& cinst : children) { cinst->setParent(root); 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)); } cache_load(cinst, child_items); } } void example_novel::NovalSyntax::node_register(std::shared_ptr root, QList> children) { for (auto& child : children) { if (!child->isAnonymous()) ast_gen::GlobalElement::UniquePtr->appendToCache(child); QList> next_child_items; for (auto& it : child->bindExpression()->children()) { auto const_it = std::dynamic_pointer_cast(it); next_child_items.append(std::const_pointer_cast(const_it)); } node_register(child, next_child_items); } } 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; }