WsParser_VS/libSyntax/syntax_novel.cpp

134 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "syntax_novel.h"
#include <tokens_novel.h>
#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<LeftBracket>(); // {
auto rightb = std::make_shared<RightBracket>(); // }
auto refers = std::make_shared<ReferMark>(); // @
auto declare = std::make_shared<DeclareSymbo>(); // #
auto rank_key = std::make_shared<Keywords>(u8"排序", 0xAEu); // 排序
auto story_key = std::make_shared<Keywords>(u8"故事", 0xAAu); // 故事
auto numbers = std::make_shared<Numbers>(); // [0-9]+
auto frag_key = std::make_shared<Keywords>(u8"情节", 0xABu); // 情节
auto volume_key = std::make_shared<Keywords>(u8"分卷", 0xACu); // 分卷
auto article_key = std::make_shared<Keywords>(u8"章节", 0xADu); // 章节
auto split_mark = std::make_shared<Split>(); // &
auto vtext = std::make_shared<VTextSection>(); // ^([^\\{\\}\\n@&]+)
auto name_text = std::make_shared<NameSection>(); // ^([^:\\{\\}\\n@&][^\\{\\}\\n@&]*)
// rule-parts ===============================================================================
// MatchRule
#define MR(x) std::make_shared<const TokenMatch>(x)
// Buffer
#define Rules QList<std::shared_ptr<const IBasicRule>>
// Option
#define OptMulT(token) std::make_shared<const Rept>(MR(token), 0, INT_MAX)
#define OptMulR(rule) std::make_shared<const Rept>(rule, 0, INT_MAX)
// multi+
#define MultiR(rule) std::make_shared<const Rept>(rule, 1, INT_MAX)
auto decl_comp = std::make_shared<const Any>(Rules{ MR(numbers), MR(vtext), MR(name_text), MR(split_mark) });
auto decl_expr = ElementRule<TextSection>(u8"decl_section", (int)NovelExprs::DESC_SECTION).reloadRule(
MultiR(decl_comp));
auto fragment_decl = ElementRule<FragmentDefine>(u8"fragment_define", (int)NovelExprs::FRAG_DEFINES).reloadRule(
std::make_shared<const Seqs>(
Rules{ MR(leftb), MR(frag_key), MR(name_text) } <<
OptMulR(decl_expr) <<
MR(rightb)
));
auto fragment_refer = ElementRule<FragmentRefers>(u8"fragment_refer", (int)NovelExprs::FRAG_REFERS).reloadRule(
std::make_shared<const Seqs>(
Rules{ MR(leftb), MR(refers), MR(frag_key), MR(name_text), MR(split_mark), MR(name_text) } <<
OptMulR(decl_expr) <<
MR(rightb)
));
auto fragment_comp = std::make_shared<const Any>(Rules{ fragment_decl, fragment_refer, decl_expr });
auto story_define = ElementRule<StoryDefine>(u8"story_define", (int)NovelExprs::STORY_DEFINES).reloadRule(
std::make_shared<const Seqs>(
Rules{ MR(leftb), MR(story_key), MR(name_text) } <<
OptMulR(fragment_comp) <<
MR(rightb)
));
// ===================================================================
auto article_decl = ElementRule<ArticleDefine>(u8"article_define", (int)NovelExprs::ARTICLE_DEFINE).reloadRule(
std::make_shared<const Seqs>(
Rules{ MR(leftb), MR(article_key), MR(name_text) } <<
OptMulR(std::make_shared<const Any>(Rules{ fragment_refer, decl_expr })) <<
MR(rightb)
));
auto volume_decl = ElementRule<VolumeDefine>(u8"volume_define", (int)NovelExprs::VOLUME_DEFINE).reloadRule(
std::make_shared<const Seqs>(
Rules{ MR(leftb), MR(volume_key), MR(name_text) } <<
OptMulR(std::make_shared<const Any>(Rules{ decl_expr, article_decl })) <<
MR(rightb)
));
auto rank_define = ElementRule<RankDeclare>(u8"rank_define", (int)NovelNode::RankDeclaration).reloadRule(
std::make_shared<const Seqs>(
Rules{ MR(declare), MR(rank_key), MR(numbers) }
));
auto document_define = ElementRule<Document>(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(
std::make_shared<const Seqs>(
Rules{
std::make_shared<const Rept>(rank_define, 0, 1),
MultiR(std::make_shared<const Any>(Rules{story_define, volume_decl}))
}
));
std::shared_ptr<const ExprRule> NovalSyntax::getParseTree() { return document_define; }
std::shared_ptr<const ast_gen::SyntaxElement> NovalSyntax::tidy(std::shared_ptr<ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
{
cache_load(root, children);
node_register(root, children);
return root;
}
void NovalSyntax::cache_load(std::shared_ptr<ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
{
root->cacheLoad();
for (auto& cinst : children) {
cinst->setParent(root);
QList<std::shared_ptr<ast_gen::SyntaxElement>> child_items;
for (auto& it : cinst->bindExpression()->children()) {
auto const_it = std::dynamic_pointer_cast<const ast_gen::SyntaxElement>(it);
child_items.append(std::const_pointer_cast<ast_gen::SyntaxElement>(const_it));
}
cache_load(cinst, child_items);
}
}
void NovalSyntax::node_register(std::shared_ptr<const ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
{
for (auto& child : children) {
if (!child->isAnonymous()) {
auto check_result = ast_gen::GlobalElement::UniquePtr->appendToCache(child);
if (check_result)
throw new lib_syntax::SyntaxException(QString(u8"SyntaxError[0x0004]系统中包含同类型重名命名节点:%1<type%2>(%3,%4)")
.arg(child->signature()).arg(child->typeMark()).arg(child->path()).arg(check_result->path()));
}
QList<std::shared_ptr<ast_gen::SyntaxElement>> next_child_items;
for (auto& it : child->bindExpression()->children()) {
auto const_it = std::dynamic_pointer_cast<const ast_gen::SyntaxElement>(it);
next_child_items.append(std::const_pointer_cast<ast_gen::SyntaxElement>(const_it));
}
node_register(child, next_child_items);
}
}