WsParser_VS/libSyntax/syntax_novel.cpp

135 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 split_mark = std::make_shared<Split>(); // &
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 vtext = std::make_shared<VTextSection>(); // ^([^\\{\\}\@&]+)
auto name_text = std::make_shared<NameSection>(); // ^([^\\{\\}@&]+)
// 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)
// opt?
#define OptR(rule) std::make_shared<const Rept>(rule, 0, 1)
auto decl_expr = ElementRule<TextSection>(u8"decl_section", (int)NovelExprs::DESC_SECTION).reloadRule(
MultiR(std::make_shared<const Any>(Rules{ MR(numbers), MR(vtext), MR(refers), MR(split_mark)}))
);
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) } <<
OptR(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) } <<
OptR(decl_expr) <<
MR(rightb)
));
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(std::make_shared<const Any>(Rules{ fragment_decl, fragment_refer, decl_expr })) <<
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);
}
}