语法指导的源代码翻译器完成

This commit is contained in:
codeboss 2024-06-20 21:36:46 +08:00
parent dba8c71f84
commit 4e99a6f120
14 changed files with 324 additions and 257 deletions

View File

@ -3,7 +3,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>--path "D:\手作小说\科学+修仙+创造世界"</LocalDebuggerCommandArguments> <LocalDebuggerCommandArguments>--path "D:\Projects\Cpp\WsNovelParser\x64\test_file"</LocalDebuggerCommandArguments>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>--path "D:\手作小说\科学+修仙+创造世界"</LocalDebuggerCommandArguments> <LocalDebuggerCommandArguments>--path "D:\手作小说\科学+修仙+创造世界"</LocalDebuggerCommandArguments>

View File

@ -12,6 +12,7 @@ NovelParser::NovelParser()
{ {
this->syntax_defines = example_novel::NovalSyntax::getParseTree(); this->syntax_defines = example_novel::NovalSyntax::getParseTree();
checker_list << std::make_shared<example_novel::FragmentExistsCheck>(); checker_list << std::make_shared<example_novel::FragmentExistsCheck>();
checker_list << std::make_shared<example_novel::StoryOrderCheck>();
checker_list << std::make_shared<example_novel::FragmentGraphCheck>(); checker_list << std::make_shared<example_novel::FragmentGraphCheck>();
analyzer_ref = std::make_shared<lib_parse::Analyzer>(checker_list); analyzer_ref = std::make_shared<lib_parse::Analyzer>(checker_list);
@ -24,13 +25,14 @@ QString NovelParser::version() const
std::shared_ptr<const ast_gen::ElementAccess> NovelParser::parse(const QFileInfoList source_list) const { std::shared_ptr<const ast_gen::ElementAccess> NovelParser::parse(const QFileInfoList source_list) const {
QList<std::shared_ptr<const ast_basic::Expression>> forst_root; QList<std::shared_ptr<const ast_basic::Expression>> forst_root;
auto lex_reader = NovalSyntax::getLexReader(); auto word_reader = std::make_shared<lib_token::WordReader>();
auto context = std::make_shared<ast_gen::GlobalElement>(u8"С˵"); auto context = std::make_shared<ast_gen::GlobalElement>(u8"С˵");
auto time_stamp = QTime::currentTime(); auto time_stamp = QTime::currentTime();
for (auto& file : source_list) { for (auto& file : source_list) {
auto tokens = lex_reader->tokensWithin(file.canonicalFilePath()); context->setCurrentFile(file.canonicalFilePath());
auto exprs_result = this->syntax_defines->parse(context, tokens); auto words = word_reader->wordsFrom(file.canonicalFilePath());
auto exprs_result = this->syntax_defines->parse(context, words);
forst_root.append(std::get<0>(exprs_result)); forst_root.append(std::get<0>(exprs_result));
} }
auto current_stamp = QTime::currentTime(); auto current_stamp = QTime::currentTime();

View File

@ -4,6 +4,7 @@
#include <iterator> #include <iterator>
#include <QTime> #include <QTime>
using namespace lib_parse;
using namespace example_novel; using namespace example_novel;
using namespace ast_basic; using namespace ast_basic;
using namespace ast_gen; using namespace ast_gen;
@ -15,7 +16,9 @@ void FragmentExistsCheck::exists_check(std::shared_ptr<const GlobalElement> root
if (target->element()->typeMark() == (int)NovelNode::FragmentRefer) { if (target->element()->typeMark() == (int)NovelNode::FragmentRefer) {
auto refer = std::dynamic_pointer_cast<const FragmentRefers>(target->element()); auto refer = std::dynamic_pointer_cast<const FragmentRefers>(target->element());
auto signature = refer->storyRefer() + u8"&" + refer->fragmentRefer(); 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<type%2>{%3:(%4)}")
.arg(signature).arg((int)NovelNode::FragmentDefine).arg(refer->signature()).arg(refer->filePath()));
} }
for (auto& xit : target->children()) { for (auto& xit : target->children()) {
@ -28,7 +31,7 @@ void FragmentExistsCheck::validCheck(std::shared_ptr<const ElementAccess> root)
} }
QString FragmentExistsCheck::name() const { QString FragmentExistsCheck::name() const {
return u8"FragmentExistsCheck"; return u8"情节引用有效性检查器";
} }
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::refers_cycle_check( QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::refers_cycle_check(
@ -188,19 +191,19 @@ void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) c
for (auto node : elements_store.values()) { for (auto node : elements_store.values()) {
auto cycle_link = refers_cycle_check(node); 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) { for (auto n : cycle_link) {
error_msg += QString(u8"%1->").arg(n->nodePeer()->signature()); error_msg += QString(u8"%1->").arg(n->nodePeer()->signature());
} }
if (cycle_link.size()) if (cycle_link.size())
throw new lib_parse::CheckException(error_msg); throw new CheckException(error_msg);
} }
} }
} }
QString FragmentGraphCheck::name() const { QString FragmentGraphCheck::name() const {
return u8"FragmentGraphCheck"; return u8"情节网络有效性检查器";
} }
FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr<const FragmentDefine> node) : node_peer(node) {} FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr<const FragmentDefine> node) : node_peer(node) {}
@ -223,3 +226,84 @@ uint& FragmentGraphHelper::inDegree()
{ {
return this->indegree; return this->indegree;
} }
QList<std::shared_ptr<const ElementAccess>> StoryOrderCheck::valid_docs_peak(std::shared_ptr<const ElementAccess> pnode) const {
QList<std::shared_ptr<const ElementAccess>> 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<const ElementAccess> root) const
{
const_cast<StoryOrderCheck*>(this)->sort_index = 1;
auto story_docs = valid_docs_peak(root);
std::sort(story_docs.begin(), story_docs.end(), [](std::shared_ptr<const ElementAccess> adoc, std::shared_ptr<const ElementAccess> bdoc){
auto elm_xa = std::dynamic_pointer_cast<const RankDeclare>(adoc->children().first()->element());
auto elm_xb = std::dynamic_pointer_cast<const RankDeclare>(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<const RankDeclare>(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<const ElementAccess> 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<const StoryDefine>(inst->element());
std::const_pointer_cast<StoryDefine>(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);
}

View File

@ -4,7 +4,6 @@
#include <ast_novel.h> #include <ast_novel.h>
namespace example_novel { namespace example_novel {
class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider { class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider {
private: private:
void exists_check(std::shared_ptr<const ast_gen::GlobalElement> root, std::shared_ptr<const ast_gen::ElementAccess> target) const; void exists_check(std::shared_ptr<const ast_gen::GlobalElement> root, std::shared_ptr<const ast_gen::ElementAccess> target) const;
@ -15,6 +14,7 @@ namespace example_novel {
virtual QString name() const override; virtual QString name() const override;
}; };
class FragmentGraphHelper; class FragmentGraphHelper;
class LIBPARSE_EXPORT FragmentGraphCheck : public std::enable_shared_from_this<FragmentGraphCheck>, public lib_parse::CheckProvider { class LIBPARSE_EXPORT FragmentGraphCheck : public std::enable_shared_from_this<FragmentGraphCheck>, public lib_parse::CheckProvider {
private: 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<std::shared_ptr<const ast_gen::ElementAccess>> valid_docs_peak(std::shared_ptr<const ast_gen::ElementAccess> pnode) const;
public:
// 通过 CheckProvider 继承
QString name() const override;
void validCheck(std::shared_ptr<const ast_gen::ElementAccess> root) const override;
};
} // namespace example_novel } // namespace example_novel

View File

@ -18,11 +18,11 @@ QString ast_basic::ExpressionElement::filePath() const {
return tokens_bind.first()->file(); return tokens_bind.first()->file();
} }
void ast_basic::ExpressionElement::tokensReset(const QList<std::shared_ptr<const lib_token::Token>>& list) { void ast_basic::ExpressionElement::tokensReset(const QList<std::shared_ptr<const IToken>>& list) {
this->tokens_bind = list; this->tokens_bind = list;
} }
void ast_basic::ExpressionElement::addToken(std::shared_ptr<const lib_token::Token> token_inst) { void ast_basic::ExpressionElement::addToken(std::shared_ptr<const IToken> token_inst) {
this->tokens_bind.append(token_inst); this->tokens_bind.append(token_inst);
} }
@ -34,10 +34,16 @@ void ast_basic::ExpressionElement::addChild(std::shared_ptr<const Expression> in
this->children_store.append(inst); this->children_store.append(inst);
} }
QList<std::shared_ptr<const Token>> ExpressionElement::tokens() const { QList<std::shared_ptr<const IToken>> ExpressionElement::tokens() const {
return this->tokens_bind; 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::Expression> ast_basic::ExpressionContext::currentInst() const std::shared_ptr<ast_basic::Expression> ast_basic::ExpressionContext::currentInst() const
{ {
if(expression_stack.size()) if(expression_stack.size())

View File

@ -19,7 +19,6 @@ namespace ast_basic {
* @return * @return
*/ */
virtual std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const = 0; virtual std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const = 0;
//===================================================== //=====================================================
/** /**
* . * .
@ -32,15 +31,19 @@ namespace ast_basic {
* *
* \return token序列 * \return token序列
*/ */
virtual QList<std::shared_ptr<const lib_token::Token>> tokens() const = 0; virtual QList<std::shared_ptr<const lib_token::IToken>> tokens() const = 0;
virtual void tokensReset(const QList<std::shared_ptr<const lib_token::Token>> &list) = 0; /**
* ÖØÖÃÓï·¨Token¼¯.
*
* \param list
*/
virtual void tokensReset(const QList<std::shared_ptr<const lib_token::IToken>> &list) = 0;
/** /**
* token实例. * token实例.
* *
* \param token_inst * \param token_inst
*/ */
virtual void addToken(std::shared_ptr<const lib_token::Token> token_inst) = 0; virtual void addToken(std::shared_ptr<const lib_token::IToken> token_inst) = 0;
//===================================================== //=====================================================
/** /**
* @brief * @brief
@ -60,29 +63,24 @@ namespace ast_basic {
/** /**
* @brief * @brief
*/ */
class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression, class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression, public std::enable_shared_from_this<ExpressionElement> {
public std::enable_shared_from_this<ExpressionElement> {
private: private:
std::shared_ptr<const lib_syntax::ExpressionRule> _expr_rule; std::shared_ptr<const lib_syntax::ExpressionRule> _expr_rule;
QList<std::shared_ptr<const Expression>> children_store; QList<std::shared_ptr<const Expression>> children_store;
QList<std::shared_ptr<const lib_token::Token>> tokens_bind; QList<std::shared_ptr<const lib_token::IToken>> tokens_bind;
public: public:
ExpressionElement(std::shared_ptr<const lib_syntax::ExpressionRule> bind); ExpressionElement(std::shared_ptr<const lib_syntax::ExpressionRule> bind);
// 通过 Expression 继承 // 通过 Expression 继承
std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const override; std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const override;
QString filePath() const override; QString filePath() const override;
QList<std::shared_ptr<const lib_token::Token>> tokens() const override; QList<std::shared_ptr<const lib_token::IToken>> tokens() const override;
void tokensReset(const QList<std::shared_ptr<const lib_token::IToken>>& list) override;
void tokensReset(const QList<std::shared_ptr<const lib_token::Token>>& list) override; void addToken(std::shared_ptr<const lib_token::IToken> token_inst) override;
void addToken(std::shared_ptr<const lib_token::Token> token_inst) override;
QList<std::shared_ptr<const Expression>> children() const override; QList<std::shared_ptr<const Expression>> children() const override;
void addChild(std::shared_ptr<const Expression> inst) override; void addChild(std::shared_ptr<const Expression> inst) override;
}; };
@ -90,10 +88,13 @@ namespace ast_basic {
private: private:
QList<std::shared_ptr<const lib_syntax::BaseRule>> rule_stack; QList<std::shared_ptr<const lib_syntax::BaseRule>> rule_stack;
QList<std::shared_ptr<Expression>> expression_stack; QList<std::shared_ptr<Expression>> expression_stack;
QString current_file_path;
public: public:
ExpressionContext(){} ExpressionContext();
virtual void setCurrentFile(const QString& path);
virtual QString currentFile() const;
// 通过 ParseContext 继承 // 通过 ParseContext 继承
std::shared_ptr<ast_basic::Expression> currentInst() const override; std::shared_ptr<ast_basic::Expression> currentInst() const override;

View File

@ -10,18 +10,18 @@ GlobalElement::GlobalElement(const QString& name) :names_store(name) {
void GlobalElement::clearCache() { node_cache.clear(); } void GlobalElement::clearCache() { node_cache.clear(); }
void GlobalElement::appendToCache(std::shared_ptr<const SyntaxElement> named_node) { std::shared_ptr<const SyntaxElement> GlobalElement::appendToCache(std::shared_ptr<const SyntaxElement> named_node) {
auto mixed_key = QString(u8"%1<%2>").arg(named_node->signature()).arg(named_node->typeMark()); auto mixed_key = QString(u8"%1<%2>").arg(named_node->signature()).arg(named_node->typeMark());
if (node_cache.contains(mixed_key)) if (node_cache.contains(mixed_key))
throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0004]系统中包含同类型重名命名节点:%1<type%2>") return node_cache[mixed_key];
.arg(named_node->signature()).arg(named_node->typeMark()));
node_cache[mixed_key] = named_node; node_cache[mixed_key] = named_node;
return nullptr;
} }
std::shared_ptr<const SyntaxElement> GlobalElement::getNamedNodeBy(int type, const QString& signature) const { std::shared_ptr<const SyntaxElement> GlobalElement::getNamedNodeBy(int type, const QString& signature) const {
auto mixed_key = QString(u8"%1<%2>").arg(signature).arg(type); auto mixed_key = QString(u8"%1<%2>").arg(signature).arg(type);
if (!node_cache.contains(mixed_key)) if (!node_cache.contains(mixed_key))
throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0005]系统中不包含指定签名的节点:%1<type%2>").arg(signature).arg(type)); return nullptr;
return node_cache[mixed_key]; return node_cache[mixed_key];
} }
@ -73,10 +73,10 @@ QList<std::shared_ptr<const TokenAccess>> ElementAccess::tokens() const {
return element()->selfTokens(); return element()->selfTokens();
} }
TokenAccess::TokenAccess(std::shared_ptr<const SyntaxElement> elm_inst, std::shared_ptr<const lib_token::Token> token_inst) TokenAccess::TokenAccess(std::shared_ptr<const SyntaxElement> elm_inst, std::shared_ptr<const lib_token::IToken> token_inst)
: element_bind(elm_inst), token_store(token_inst) {} : element_bind(elm_inst), token_store(token_inst) {}
std::shared_ptr<const SyntaxElement> TokenAccess::bind() const { return element_bind; } std::shared_ptr<const SyntaxElement> TokenAccess::bind() const { return element_bind; }
std::shared_ptr<const lib_token::Token> TokenAccess::token() const { return token_store; } std::shared_ptr<const lib_token::IToken> TokenAccess::token() const { return token_store; }

View File

@ -53,6 +53,11 @@ namespace ast_gen
* @return parentnullptr * @return parentnullptr
*/ */
virtual std::shared_ptr<const SyntaxElement> parent() const = 0; virtual std::shared_ptr<const SyntaxElement> parent() const = 0;
/**
* @brief ÖØÖø¸Ö¸Õë.
*
* \param inst
*/
virtual void setParent(std::shared_ptr<const SyntaxElement> inst) = 0; virtual void setParent(std::shared_ptr<const SyntaxElement> inst) = 0;
/** /**
@ -74,7 +79,6 @@ namespace ast_gen
ElementAccess(std::shared_ptr<const SyntaxElement> point); ElementAccess(std::shared_ptr<const SyntaxElement> point);
std::shared_ptr<const SyntaxElement> element() const; std::shared_ptr<const SyntaxElement> element() const;
QList<std::shared_ptr<const ElementAccess>> children() const; QList<std::shared_ptr<const ElementAccess>> children() const;
/** /**
@ -87,12 +91,12 @@ namespace ast_gen
class LIBSYNTAX_EXPORT TokenAccess { class LIBSYNTAX_EXPORT TokenAccess {
private: private:
std::shared_ptr<const ast_gen::SyntaxElement> element_bind; std::shared_ptr<const ast_gen::SyntaxElement> element_bind;
std::shared_ptr<const lib_token::Token> token_store; std::shared_ptr<const lib_token::IToken> token_store;
public: public:
TokenAccess(std::shared_ptr<const ast_gen::SyntaxElement> elm_inst, std::shared_ptr<const lib_token::Token> token_inst); TokenAccess(std::shared_ptr<const ast_gen::SyntaxElement> elm_inst, std::shared_ptr<const lib_token::IToken> token_inst);
virtual std::shared_ptr<const ast_gen::SyntaxElement> bind() const; virtual std::shared_ptr<const ast_gen::SyntaxElement> bind() const;
virtual std::shared_ptr<const lib_token::Token> token() const; virtual std::shared_ptr<const lib_token::IToken> token() const;
}; };
/** /**
@ -110,7 +114,7 @@ namespace ast_gen
GlobalElement(const QString& name); GlobalElement(const QString& name);
virtual void clearCache(); virtual void clearCache();
virtual void appendToCache(std::shared_ptr<const ast_gen::SyntaxElement> named_node); virtual std::shared_ptr<const ast_gen::SyntaxElement> appendToCache(std::shared_ptr<const ast_gen::SyntaxElement> named_node);
/** /**
* @brief * @brief
* @param signature * @param signature
@ -118,7 +122,6 @@ namespace ast_gen
* @throws * @throws
*/ */
virtual std::shared_ptr<const ast_gen::SyntaxElement> getNamedNodeBy(int type, const QString& signature) const; virtual std::shared_ptr<const ast_gen::SyntaxElement> getNamedNodeBy(int type, const QString& signature) const;
virtual void addChild(std::shared_ptr<ast_gen::SyntaxElement> citem); virtual void addChild(std::shared_ptr<ast_gen::SyntaxElement> citem);
// ParseElement interface // ParseElement interface

View File

@ -2,25 +2,26 @@
using namespace example_novel; using namespace example_novel;
using namespace lib_syntax;
TextSection::TextSection(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) TextSection::TextSection(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind) {}
QString example_novel::TextSection::content() const QString TextSection::content() const
{ {
return context_store; return context_store;
} }
int TextSection::typeMark() const { return (int)NovelNode::TextSection; } int TextSection::typeMark() const { return (int)NovelNode::TextSection; }
bool example_novel::TextSection::isAnonymous() const bool TextSection::isAnonymous() const
{ {
return true; return true;
} }
QString TextSection::signature() const { return u8"::section"; } QString TextSection::signature() const { return u8"::section"; }
void example_novel::TextSection::cacheLoad() void TextSection::cacheLoad()
{ {
QString text; QString text;
for (auto& t : selfTokens()) { for (auto& t : selfTokens()) {
@ -29,14 +30,14 @@ void example_novel::TextSection::cacheLoad()
context_store = text; context_store = text;
} }
FragmentRefers::FragmentRefers(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) FragmentRefers::FragmentRefers(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind) {}
QString FragmentRefers::storyRefer() const { return story_refs; } QString FragmentRefers::storyRefer() const { return story_refs; }
QString FragmentRefers::fragmentRefer() const { return fragment_ref; } QString FragmentRefers::fragmentRefer() const { return fragment_ref; }
void example_novel::FragmentRefers::cacheLoad() void FragmentRefers::cacheLoad()
{ {
this->story_refs = selfTokens()[5]->token()->content(); this->story_refs = selfTokens()[5]->token()->content();
this->fragment_ref = selfTokens()[3]->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; } int FragmentRefers::typeMark() const { return (int)NovelNode::FragmentRefer; }
bool example_novel::FragmentRefers::isAnonymous() const bool FragmentRefers::isAnonymous() const
{ {
return true; return true;
} }
@ -58,18 +59,18 @@ QString FragmentRefers::signature() const {
} }
FragmentDefine::FragmentDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) FragmentDefine::FragmentDefine(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind) {}
QString FragmentDefine::name() const { return name_store; } QString FragmentDefine::name() const { return name_store; }
void example_novel::FragmentDefine::cacheLoad() void FragmentDefine::cacheLoad()
{ {
name_store = selfTokens()[2]->token()->content(); name_store = selfTokens()[2]->token()->content();
} }
int FragmentDefine::typeMark() const { return (int)NovelNode::FragmentDefine; } int FragmentDefine::typeMark() const { return (int)NovelNode::FragmentDefine; }
bool example_novel::FragmentDefine::isAnonymous() const bool FragmentDefine::isAnonymous() const
{ {
return false; return false;
} }
@ -77,14 +78,18 @@ bool example_novel::FragmentDefine::isAnonymous() const
QString FragmentDefine::signature() const { return parent()->signature() + u8"&" + name(); } QString FragmentDefine::signature() const { return parent()->signature() + u8"&" + name(); }
StoryDefine::StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) StoryDefine::StoryDefine(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind), sort_index(0) {}
QString StoryDefine::name() const { return name_store; } QString StoryDefine::name() const { return name_store; }
void example_novel::StoryDefine::setSort(int value){
sort_index = value;
}
int StoryDefine::sort() const { return sort_index; } int StoryDefine::sort() const { return sort_index; }
void example_novel::StoryDefine::cacheLoad() void StoryDefine::cacheLoad()
{ {
name_store = selfTokens()[3]->token()->content(); name_store = selfTokens()[3]->token()->content();
sort_index = selfTokens()[2]->token()->content().toInt(); sort_index = selfTokens()[2]->token()->content().toInt();
@ -92,7 +97,7 @@ void example_novel::StoryDefine::cacheLoad()
int StoryDefine::typeMark() const { return (int)NovelNode::StoryDefine; } int StoryDefine::typeMark() const { return (int)NovelNode::StoryDefine; }
bool example_novel::StoryDefine::isAnonymous() const bool StoryDefine::isAnonymous() const
{ {
return false; return false;
} }
@ -100,23 +105,23 @@ bool example_novel::StoryDefine::isAnonymous() const
QString StoryDefine::signature() const { return name(); } QString StoryDefine::signature() const { return name(); }
#include "syntax_novel.h" #include "syntax_novel.h"
Document::Document(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) Document::Document(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind) {}
int Document::typeMark() const { return (int)NovelNode::Document; } int Document::typeMark() const { return (int)NovelNode::Document; }
bool example_novel::Document::isAnonymous() const bool Document::isAnonymous() const
{ {
return true; return true;
} }
QString Document::signature() const { return QString(u8"::document<%1>").arg(path()); } 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<const lib_syntax::ExpressionRule> rule_bind) AbstractImpl::AbstractImpl(std::shared_ptr<const ExpressionRule> rule_bind)
: ExpressionElement(rule_bind) { parent_store.reset(); } : ExpressionElement(rule_bind) { parent_store.reset(); }
QList<std::shared_ptr<const ast_gen::TokenAccess> > AbstractImpl::selfTokens() const { QList<std::shared_ptr<const ast_gen::TokenAccess> > AbstractImpl::selfTokens() const {
@ -129,61 +134,91 @@ QList<std::shared_ptr<const ast_gen::TokenAccess> > AbstractImpl::selfTokens() c
return values; return values;
} }
std::shared_ptr<const ast_gen::SyntaxElement> example_novel::AbstractImpl::parent() const std::shared_ptr<const ast_gen::SyntaxElement> AbstractImpl::parent() const
{ {
return this->parent_store.lock(); return this->parent_store.lock();
} }
void example_novel::AbstractImpl::setParent(std::shared_ptr<const ast_gen::SyntaxElement> inst) void AbstractImpl::setParent(std::shared_ptr<const ast_gen::SyntaxElement> inst)
{ {
this->parent_store = inst; this->parent_store = inst;
} }
// ͨ¹ý SyntaxElement ¼Ì³Ð // ͨ¹ý SyntaxElement ¼Ì³Ð
std::shared_ptr<const ast_basic::Expression> example_novel::AbstractImpl::bindExpression() const { std::shared_ptr<const ast_basic::Expression> AbstractImpl::bindExpression() const {
return shared_from_this(); return shared_from_this();
} }
QString example_novel::AbstractImpl::path() const QString AbstractImpl::path() const
{ {
return ast_basic::ExpressionElement::filePath(); return ast_basic::ExpressionElement::filePath();
} }
VolumeDefine::VolumeDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) VolumeDefine::VolumeDefine(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind) {}
QString VolumeDefine::name() const { return name_store; } QString VolumeDefine::name() const { return name_store; }
void example_novel::VolumeDefine::cacheLoad() void VolumeDefine::cacheLoad()
{ {
name_store = selfTokens()[2]->token()->content(); name_store = selfTokens()[2]->token()->content();
} }
int VolumeDefine::typeMark() const { return (int)NovelNode::VolumeDefine; } int VolumeDefine::typeMark() const { return (int)NovelNode::VolumeDefine; }
bool example_novel::VolumeDefine::isAnonymous() const bool VolumeDefine::isAnonymous() const
{ {
return false; return false;
} }
QString VolumeDefine::signature() const { return name(); } QString VolumeDefine::signature() const { return name(); }
ArticleDefine::ArticleDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind) ArticleDefine::ArticleDefine(std::shared_ptr<const ExpressionRule> rule_bind)
: AbstractImpl(rule_bind) {} : AbstractImpl(rule_bind) {}
QString ArticleDefine::name() const { return name_store; } QString ArticleDefine::name() const { return name_store; }
void example_novel::ArticleDefine::cacheLoad() void ArticleDefine::cacheLoad()
{ {
name_store = selfTokens()[2]->token()->content(); name_store = selfTokens()[2]->token()->content();
} }
int ArticleDefine::typeMark() const { return (int)NovelNode::ArticleDefine; } int ArticleDefine::typeMark() const { return (int)NovelNode::ArticleDefine; }
bool example_novel::ArticleDefine::isAnonymous() const bool ArticleDefine::isAnonymous() const
{ {
return false; return false;
} }
QString ArticleDefine::signature() const { return parent()->signature() + u8"&" + name(); } QString ArticleDefine::signature() const { return parent()->signature() + u8"&" + name(); }
RankDeclare::RankDeclare(std::shared_ptr<const ExpressionRule> 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();
}

View File

@ -5,6 +5,7 @@
namespace example_novel namespace example_novel
{ {
enum class NovelNode { enum class NovelNode {
GlobalElement = 0,
TextSection = 1, TextSection = 1,
FragmentRefer = 2, FragmentRefer = 2,
FragmentDefine = 3, FragmentDefine = 3,
@ -12,10 +13,10 @@ namespace example_novel
Document = 5, Document = 5,
ArticleDefine = 6, ArticleDefine = 6,
VolumeDefine = 7, VolumeDefine = 7,
RankDeclaration = 8,
}; };
class LIBSYNTAX_EXPORT AbstractImpl : class LIBSYNTAX_EXPORT AbstractImpl : public ast_basic::ExpressionElement, public ast_gen::SyntaxElement {
public ast_basic::ExpressionElement, public ast_gen::SyntaxElement {
private: private:
std::weak_ptr<const SyntaxElement> parent_store; std::weak_ptr<const SyntaxElement> parent_store;
@ -123,6 +124,7 @@ namespace example_novel
StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind); StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
QString name() const; QString name() const;
void setSort(int value);
int sort() const; int sort() const;
// SyntaxElement interface // SyntaxElement interface
@ -148,4 +150,19 @@ namespace example_novel
virtual QString signature() const override; virtual QString signature() const override;
virtual void cacheLoad() override; virtual void cacheLoad() override;
}; };
class LIBSYNTAX_EXPORT RankDeclare : public AbstractImpl {
private:
int page_rank = 0;
public:
RankDeclare(std::shared_ptr<const lib_syntax::ExpressionRule> rule);
int rankNumber() const;
// ͨ¹ý AbstractImpl ¼Ì³Ð
int typeMark() const override;
bool isAnonymous() const override;
QString signature() const override;
void cacheLoad() override;
};
} }

View File

@ -6,30 +6,28 @@ using namespace std;
using namespace lib_token; using namespace lib_token;
using namespace ast_basic; using namespace ast_basic;
TokenMatch::TokenMatch(shared_ptr<const TokenDefine> define) : define_peer(define) {} TokenMatch::TokenMatch(shared_ptr<const ITokenDefine> define) : define_peer(define) {}
QList<std::shared_ptr<const BaseRule>> TokenMatch::children() const { return QList<std::shared_ptr<const BaseRule>>(); } QList<std::shared_ptr<const BaseRule>> TokenMatch::children() const { return QList<std::shared_ptr<const BaseRule>>(); }
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> TokenMatch::match(std::shared_ptr<const Token> remains_head) const { std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> TokenMatch::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> 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<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>>
std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const Token>> TokenMatch::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const Token> head) const {
if (!head) if (!head)
throw std::make_shared<InputTerminal>(); throw new InputTerminal(rt_inst->currentFile());
if (head->define()->typeMark() == define_peer->typeMark()) { auto match_result = define_peer->analysis(head);
rt_inst->currentInst()->addToken(head); if (std::get<0>(match_result)) {
return std::make_tuple(nullptr, head->nextToken()); rt_inst->currentInst()->addToken(std::get<0>(match_result));
}
else {
throw new MismatchException(head);
} }
throw std::make_shared<MismatchException>(head); if (std::get<1>(match_result)) {
return std::make_tuple(nullptr, std::make_shared<WordImpl>(std::get<1>(match_result), head->nextWord()));
}
else {
return std::make_tuple(nullptr, head->nextWord());
}
} }
QString TokenMatch::token_present() const { QString TokenMatch::token_present() const {
@ -40,41 +38,7 @@ Rept::Rept(std::shared_ptr<const BaseRule> rule, int min, int max) : rule_peer(r
QList<std::shared_ptr<const BaseRule>> Rept::children() const { return QList<std::shared_ptr<const BaseRule>>() << rule_peer; } QList<std::shared_ptr<const BaseRule>> Rept::children() const { return QList<std::shared_ptr<const BaseRule>>() << rule_peer; }
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> Rept::match(std::shared_ptr<const Token> list_head) const { std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> Rept::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> 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<const Expression>, std::shared_ptr<const Token>> Rept::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const Token> head) const {
auto temp_head = head; auto temp_head = head;
// min-match // min-match
@ -95,10 +59,8 @@ std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const Token>> Rept
temp_head = std::get<1>(result_gen); temp_head = std::get<1>(result_gen);
} }
catch (std::shared_ptr<MismatchException> ex) { catch (SyntaxException* ex) {
return std::make_tuple(nullptr, temp_head); delete ex;
}
catch (std::shared_ptr<InputTerminal> ex) {
return std::make_tuple(nullptr, temp_head); return std::make_tuple(nullptr, temp_head);
} }
} }
@ -115,30 +77,7 @@ Seqs::Seqs(const QList<std::shared_ptr<const BaseRule>> mbrs) : mbrs_store(mbrs)
QList<std::shared_ptr<const BaseRule>> Seqs::children() const { return mbrs_store; } QList<std::shared_ptr<const BaseRule>> Seqs::children() const { return mbrs_store; }
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> Seqs::match(std::shared_ptr<const Token> list_head) const { std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> Seqs::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> 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<const Expression>, std::shared_ptr<const Token>> Seqs::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const Token> head) const {
auto temp_head = head; auto temp_head = head;
for (auto& r : mbrs_store) { for (auto& r : mbrs_store) {
@ -160,53 +99,30 @@ QString Seqs::token_present() const
return QString(u8"(%1)").arg(content); return QString(u8"(%1)").arg(content);
} }
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const Token>> //std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const Token>>
Any::rule_select(std::shared_ptr<const Token> head) const {
QString token_seqs = this->token_present();
std::tuple<MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const Token>> 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;
}
Any::Any(const QList<std::shared_ptr<const BaseRule>> mbrs) : mbrs_store(mbrs) {} Any::Any(const QList<std::shared_ptr<const BaseRule>> mbrs) : mbrs_store(mbrs) {}
QList<std::shared_ptr<const BaseRule>> Any::children() const { return mbrs_store; } QList<std::shared_ptr<const BaseRule>> Any::children() const { return mbrs_store; }
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> Any::match(std::shared_ptr<const Token> list_head) const { class words_span {
auto item = rule_select(list_head); public:
return std::make_tuple(std::get<0>(item), std::get<1>(item), std::get<3>(item)); 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<const Expression>, std::shared_ptr<const Token>> Any::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const Token> head) const { std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> Any::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
std::function<int(std::shared_ptr<const Token>, std::shared_ptr<const Token>)> measure_span = std::function<words_span(std::shared_ptr<const IWordBase>, std::shared_ptr<const IWordBase>)> measure_span =
[&](std::shared_ptr<const Token> anchor, std::shared_ptr<const Token> head)->int { [&](std::shared_ptr<const IWordBase> anchor, std::shared_ptr<const IWordBase> head)->words_span {
if (anchor == head) return words_span(anchor->row() - head->row(), anchor->column() - head->column());
return 1;
return measure_span(anchor, head->nextToken()) + 1;
}; };
std::tuple<std::shared_ptr<const BaseRule>, int> temp_result = std::make_tuple(mbrs_store.first(), 0); std::tuple<std::shared_ptr<const BaseRule>, words_span> temp_result = std::make_tuple(mbrs_store.first(), words_span(0,0));
for (auto& fork : mbrs_store) { for (auto& fork : mbrs_store) {
try { try {
auto gen = fork->parse(rt_inst, head); auto gen = fork->parse(rt_inst, head);
@ -217,11 +133,13 @@ std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const Token>> Any:
return std::make_tuple(nullptr, std::get<1>(gen)); return std::make_tuple(nullptr, std::get<1>(gen));
} }
// Óï·¨´íÎóµÄ»á½øÐÐ±È½Ï // Óï·¨´íÎóµÄ»á½øÐбȽÏ
catch (std::shared_ptr<MismatchException> ex) { catch (MismatchException* ex) {
auto current_span = measure_span(ex->targetToken(), head); auto current_span = measure_span(ex->targetWord(), head);
if (current_span > std::get<1>(temp_result)) if (current_span > std::get<1>(temp_result))
temp_result = std::make_tuple(fork, current_span); temp_result = std::make_tuple(fork, current_span);
delete ex;
} }
} }
@ -263,11 +181,7 @@ QList<std::shared_ptr<const BaseRule>> ExpressionRule::children() const {
return QList<std::shared_ptr<const BaseRule>>() << this->child_store; return QList<std::shared_ptr<const BaseRule>>() << this->child_store;
} }
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> ExpressionRule::match(std::shared_ptr<const Token> list_head) const { std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const IWordBase>> ExpressionRule::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
return child_store->match(list_head);
}
std::tuple<std::shared_ptr<const Expression>, std::shared_ptr<const Token>> ExpressionRule::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const Token> head) const {
std::shared_ptr<Expression> elm_ast = this->newEmptyInstance(); std::shared_ptr<Expression> elm_ast = this->newEmptyInstance();
rt_inst->pushExpressionRule(this->shared_from_this()); 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()); return QString(u8"(%1)").arg(child_store->token_present());
} }
MismatchException::MismatchException(std::shared_ptr<const lib_token::Token> inst) :SyntaxException( MismatchException::MismatchException(std::shared_ptr<const lib_token::IWordBase> inst) :SyntaxException(
QString(u8"Syntax[0x00001]语法匹配错误不能识别token%1<%2,%3>").arg(inst->content()).arg(inst->row()).arg(inst->column())), target(inst) {} 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_ptr<const Token>MismatchException::targetToken() const { std::shared_ptr<const IWordBase>MismatchException::targetWord() const {
return this->target; return this->target;
} }
InputTerminal::InputTerminal() :SyntaxException(u8"Syntax[0x0000]token流提前终止") {} InputTerminal::InputTerminal(const QString& file_path)
:SyntaxException(QString(u8"Syntax[0x0000]token流%1提前终止").arg(file_path)) {}

View File

@ -16,7 +16,7 @@ namespace lib_syntax {
/** /**
* @brief * @brief
*/ */
class SyntaxException { class LIBSYNTAX_EXPORT SyntaxException {
private: private:
QString msg_store; QString msg_store;
@ -35,6 +35,9 @@ namespace lib_syntax {
public: public:
virtual ~ParseContext() = default; virtual ~ParseContext() = default;
virtual void setCurrentFile(const QString &path) = 0;
virtual QString currentFile() const = 0;
/** /**
* \brief . * \brief .
* *
@ -70,20 +73,14 @@ namespace lib_syntax {
Fail // 从第一个词起完全不匹配 Fail // 从第一个词起完全不匹配
}; };
/**
* @brief token流匹配
* @return token集合<>
*/
virtual std::tuple<MatchResult, uint, std::shared_ptr<const lib_token::Token>> match(std::shared_ptr<const lib_token::Token> remains_head) const = 0;
/** /**
* @brief * @brief
* @param rt_inst * @param rt_inst
* @param head * @param head
* @return <,> * @return <,>
*/ */
virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>> virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::IWordBase>>
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::Token> head) const = 0; parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const = 0;
/** /**
* *
@ -99,17 +96,16 @@ namespace lib_syntax {
*/ */
class LIBSYNTAX_EXPORT TokenMatch : public BaseRule, public std::enable_shared_from_this<TokenMatch> { class LIBSYNTAX_EXPORT TokenMatch : public BaseRule, public std::enable_shared_from_this<TokenMatch> {
private: private:
std::shared_ptr<const lib_token::TokenDefine> define_peer; std::shared_ptr<const lib_token::ITokenDefine> define_peer;
public: public:
TokenMatch(std::shared_ptr<const lib_token::TokenDefine> define); TokenMatch(std::shared_ptr<const lib_token::ITokenDefine> define);
// BaseRule interface // BaseRule interface
public: public:
virtual QList<std::shared_ptr<const BaseRule>> children() const override; virtual QList<std::shared_ptr<const BaseRule>> children() const override;
virtual std::tuple<MatchResult, uint, std::shared_ptr<const lib_token::Token>> match(std::shared_ptr<const lib_token::Token> head) const override; virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::IWordBase>>
virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>> parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::Token> head) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -120,7 +116,7 @@ namespace lib_syntax {
private: private:
QList<std::shared_ptr<const BaseRule>> mbrs_store; QList<std::shared_ptr<const BaseRule>> mbrs_store;
std::tuple<MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const lib_token::Token>> rule_select(std::shared_ptr<const lib_token::Token> head) const; std::tuple<MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const lib_token::IWordBase>> rule_select(std::shared_ptr<const lib_token::IWordBase> head) const;
public: public:
Any(const QList<std::shared_ptr<const BaseRule>> mbrs); Any(const QList<std::shared_ptr<const BaseRule>> mbrs);
@ -128,9 +124,8 @@ namespace lib_syntax {
// BaseRule interface // BaseRule interface
public: public:
virtual QList<std::shared_ptr<const BaseRule>> children() const override; virtual QList<std::shared_ptr<const BaseRule>> children() const override;
virtual std::tuple<MatchResult, uint, std::shared_ptr<const lib_token::Token>> match(std::shared_ptr<const lib_token::Token> list_head) const override; virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::IWordBase>>
virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>> parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::Token> head) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -147,9 +142,8 @@ namespace lib_syntax {
// BaseRule interface // BaseRule interface
public: public:
virtual QList<std::shared_ptr<const BaseRule>> children() const override; virtual QList<std::shared_ptr<const BaseRule>> children() const override;
virtual std::tuple<MatchResult, uint, std::shared_ptr<const lib_token::Token>> match(std::shared_ptr<const lib_token::Token> list_head) const override; virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::IWordBase>>
virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>> parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::Token> head) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
}; };
@ -167,9 +161,8 @@ namespace lib_syntax {
// BaseRule interface // BaseRule interface
public: public:
virtual QList<std::shared_ptr<const BaseRule>> children() const override; virtual QList<std::shared_ptr<const BaseRule>> children() const override;
virtual std::tuple<MatchResult, uint, std::shared_ptr<const lib_token::Token>> match(std::shared_ptr<const lib_token::Token> list_head) const override; virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::IWordBase>>
virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>> parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::Token> head) const override;
virtual QString token_present() 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<ExpressionRule> { class LIBSYNTAX_EXPORT ExpressionRule : public lib_syntax::BaseRule, public std::enable_shared_from_this<ExpressionRule> {
public: public:
typedef QList<std::shared_ptr<const lib_token::Token>> TokenSeqs; typedef QList<std::shared_ptr<const lib_token::IToken>> TokenSeqs;
ExpressionRule(const QString& rule_name, int expr_mark); ExpressionRule(const QString& rule_name, int expr_mark);
virtual std::shared_ptr<const ExpressionRule> reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule); virtual std::shared_ptr<const ExpressionRule> reloadRule(std::function<TokenSeqs(const TokenSeqs&)> filter, std::shared_ptr<const BaseRule> rule);
@ -192,9 +185,8 @@ namespace lib_syntax {
// BaseRule interface // BaseRule interface
public: public:
virtual QList<std::shared_ptr<const lib_syntax::BaseRule>> children() const override; virtual QList<std::shared_ptr<const lib_syntax::BaseRule>> children() const override;
virtual std::tuple<MatchResult, uint, std::shared_ptr<const lib_token::Token>> match(std::shared_ptr<const lib_token::Token> remains_head) const override; virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::IWordBase>>
virtual std::tuple<std::shared_ptr<const ast_basic::Expression>, std::shared_ptr<const lib_token::Token>> parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::Token> head) const override;
virtual QString token_present() const override; virtual QString token_present() const override;
private: private:
@ -226,17 +218,17 @@ namespace lib_syntax {
class MismatchException : public SyntaxException { class MismatchException : public SyntaxException {
private: private:
std::shared_ptr<const lib_token::Token> target; std::shared_ptr<const lib_token::IWordBase> target;
public: public:
MismatchException(std::shared_ptr<const lib_token::Token> inst); MismatchException(std::shared_ptr<const lib_token::IWordBase> inst);
virtual ~MismatchException() = default; virtual ~MismatchException() = default;
virtual std::shared_ptr<const lib_token::Token> targetToken() const; virtual std::shared_ptr<const lib_token::IWordBase> targetWord() const;
}; };
class InputTerminal : public SyntaxException { class InputTerminal : public SyntaxException {
public: public:
InputTerminal(); InputTerminal(const QString &file_path);
}; };
} // namespace lib_syntax } // namespace lib_syntax

View File

@ -11,7 +11,9 @@ using namespace ast_basic;
auto leftb = std::make_shared<LeftBracket>(); // { auto leftb = std::make_shared<LeftBracket>(); // {
auto rightb = std::make_shared<RightBracket>(); // } auto rightb = std::make_shared<RightBracket>(); // }
auto refers = std::make_shared<ReferMark>(); // @ auto refers = std::make_shared<ReferMark>(); // @
auto declare = std::make_shared<DeclareSymbo>(); // #
auto rank_key = std::make_shared<Keywords>(u8"排序", u8"rank-symbol", 0xAEu); // 排序
auto story_key = std::make_shared<Keywords>(u8"¹ÊÊÂ", u8"story-mark", 0xAAu); // ¹ÊÊ auto story_key = std::make_shared<Keywords>(u8"¹ÊÊÂ", u8"story-mark", 0xAAu); // ¹ÊÊÂ
auto numbers = std::make_shared<Numbers>(); // [0-9]+ auto numbers = std::make_shared<Numbers>(); // [0-9]+
auto frag_key = std::make_shared<Keywords>(u8"Çé½Ú", u8"fragment-mark", 0xABu); // Çé½Ú auto frag_key = std::make_shared<Keywords>(u8"Çé½Ú", u8"fragment-mark", 0xABu); // Çé½Ú
@ -96,21 +98,25 @@ auto volume_decl = ElementRule<VolumeDefine>(u8"volume_define", (int)NovelExprs:
LinesMerge(MR(rightb)) LinesMerge(MR(rightb))
)); ));
auto rank_define = ElementRule<RankDeclare>(u8"rank_define", (int)NovelNode::RankDeclaration).reloadRule(remove_nl, std::make_shared<const Seqs>(
Rules{ MR(declare), MR(rank_key), MR(numbers), OptMulT(newl)}
));
auto document_define = ElementRule<Document>(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>( auto document_define = ElementRule<Document>(u8"decls-doc", (int)NovelExprs::DOC_DEFINES).reloadRule(remove_nl, std::make_shared<const Seqs>(
Rules{ Rules{
OptMulT(newl), std::make_shared<const Rept>(rank_define, 0, 1),
MultiR(std::make_shared<const Any>(Rules{story_define, volume_decl})) MultiR(std::make_shared<const Any>(Rules{story_define, volume_decl}))
} }
)); ));
std::shared_ptr<const ExpressionRule> NovalSyntax::getParseTree() { return document_define; } std::shared_ptr<const ExpressionRule> NovalSyntax::getParseTree() { return document_define; }
std::shared_ptr<const ast_gen::SyntaxElement> example_novel::NovalSyntax::tidy(std::shared_ptr<ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children) 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); cache_load(root, children);
node_register(root, children); node_register(root, children);
return root; return root;
} }
void example_novel::NovalSyntax::cache_load(std::shared_ptr<ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children) void NovalSyntax::cache_load(std::shared_ptr<ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
{ {
root->cacheLoad(); root->cacheLoad();
for (auto& cinst : children) { for (auto& cinst : children) {
@ -125,11 +131,15 @@ void example_novel::NovalSyntax::cache_load(std::shared_ptr<ast_gen::SyntaxEleme
cache_load(cinst, child_items); cache_load(cinst, child_items);
} }
} }
void example_novel::NovalSyntax::node_register(std::shared_ptr<const ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children) void NovalSyntax::node_register(std::shared_ptr<const ast_gen::SyntaxElement> root, QList<std::shared_ptr<ast_gen::SyntaxElement>> children)
{ {
for (auto& child : children) { for (auto& child : children) {
if (!child->isAnonymous()) if (!child->isAnonymous()) {
ast_gen::GlobalElement::UniquePtr->appendToCache(child); auto check_result = ast_gen::GlobalElement::UniquePtr->appendToCache(child);
if(check_result)
throw new lib_syntax::SyntaxException(QString(u8"Parse[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; QList<std::shared_ptr<ast_gen::SyntaxElement>> next_child_items;
for (auto& it : child->bindExpression()->children()) { for (auto& it : child->bindExpression()->children()) {
@ -140,10 +150,3 @@ void example_novel::NovalSyntax::node_register(std::shared_ptr<const ast_gen::Sy
node_register(child, next_child_items); node_register(child, next_child_items);
} }
} }
std::shared_ptr<const TokenReader> NovalSyntax::getLexReader()
{
auto inst = std::make_shared<lib_token::TokenReader>(QList<std::shared_ptr<const lib_token::TokenDefine>>()
<< leftb << rightb << refers << split_mark << story_key << frag_key << volume_key << article_key << numbers << name_text << vtext << newl);
return inst;
}

View File

@ -24,14 +24,6 @@ namespace example_novel {
class LIBSYNTAX_EXPORT NovalSyntax { class LIBSYNTAX_EXPORT NovalSyntax {
public: public:
/**
* @brief novel词法解析器
* @param path
* @param name
* @return
*/
static std::shared_ptr<const lib_token::TokenReader> getLexReader();
/** /**
* @brief novel语法解析树 * @brief novel语法解析树
* @return * @return