WsParser_VS/libSyntax/syntax_novel.cpp

159 lines
7.2 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(E, x) std::make_shared<const TokenMatch<E>>(x)
#define MER(E, xproc, t) std::make_shared<const TokenMatch<E, xproc>>(t)
// 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(TextSection, numbers), MR(TextSection, vtext), MR(TextSection, refers), MR(TextSection, split_mark)
}))
);
void frags_nmset(std::shared_ptr<FragmentDefine> inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setName(token->content());
}
auto fragment_decl = ElementRule<FragmentDefine>(u8"fragment_define", (int)NovelExprs::FRAG_DEFINES).reloadRule(
std::make_shared<const Seqs>(Rules{
MR(FragmentDefine, leftb), MR(FragmentDefine, frag_key), MER(FragmentDefine, frags_nmset, name_text) } <<
OptR(decl_expr) <<
MR(FragmentDefine, rightb)
));
void frags_snm_set(std::shared_ptr<PointRefers> inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setStoryRefer(token->content());
}
void frags_fnm_set(std::shared_ptr<PointRefers> inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setFragmentRefer(token->content());
}
auto fragment_refer = ElementRule<PointRefers>(u8"fragment_refer", (int)NovelExprs::FRAG_REFERS).reloadRule(
std::make_shared<const Seqs>(Rules{
MR(PointRefers, leftb), MR(PointRefers, refers), MR(PointRefers, frag_key),
MER(PointRefers, frags_fnm_set, name_text), MR(PointRefers, split_mark), MER(PointRefers, frags_snm_set, name_text) } <<
OptR(decl_expr) <<
MR(PointRefers, rightb)
));
void story_nmset(std::shared_ptr<StoryDefine> inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setName(token->content());
}
auto story_define = ElementRule<StoryDefine>(u8"story_define", (int)NovelExprs::STORY_DEFINES).reloadRule(
std::make_shared<const Seqs>(Rules{
MR(StoryDefine, leftb), MR(StoryDefine, story_key), MER(StoryDefine, story_nmset, name_text) } <<
OptMulR(std::make_shared<const Any>(Rules{ fragment_decl, fragment_refer, decl_expr })) <<
MR(StoryDefine, rightb)
));
// ===================================================================
void article_nset(std::shared_ptr<ArticleDefine>inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setName(token->content());
}
auto article_decl = ElementRule<ArticleDefine>(u8"article_define", (int)NovelExprs::ARTICLE_DEFINE).reloadRule(
std::make_shared<const Seqs>(Rules{
MR(ArticleDefine, leftb), MR(ArticleDefine, article_key), MER(ArticleDefine, article_nset, name_text) } <<
OptMulR(std::make_shared<const Any>(Rules{ fragment_refer, decl_expr })) <<
MR(ArticleDefine, rightb)
));
void volume_nset(std::shared_ptr<VolumeDefine> inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setName(token->content());
}
auto volume_decl = ElementRule<VolumeDefine>(u8"volume_define", (int)NovelExprs::VOLUME_DEFINE).reloadRule(
std::make_shared<const Seqs>(Rules{
MR(VolumeDefine, leftb), MR(VolumeDefine, volume_key), MER(VolumeDefine, volume_nset, name_text) } <<
OptMulR(std::make_shared<const Any>(Rules{ decl_expr, article_decl })) <<
MR(VolumeDefine, rightb)
));
void rank_set(std::shared_ptr<RankDeclare> inst, std::shared_ptr<const lib_token::IToken> token) {
inst->setRank(token->content().toInt());
}
auto rank_define = ElementRule<RankDeclare>(u8"rank_define", (int)NovelNode::RankDeclaration).reloadRule(
std::make_shared<const Seqs>(Rules{
MR(RankDeclare, declare), MR(RankDeclare, rank_key), MER(RankDeclare, rank_set, 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)
{
build_objecttree(root, children);
node_register(root, children);
return root;
}
void NovalSyntax::build_objecttree(std::shared_ptr<ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
{
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));
}
build_objecttree(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);
}
}