语法指导的源代码翻译器完成
This commit is contained in:
parent
dba8c71f84
commit
4e99a6f120
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommandArguments>--path "D:\手作小说\科学+修仙+创造世界"</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>--path "D:\Projects\Cpp\WsNovelParser\x64\test_file"</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerCommandArguments>--path "D:\手作小说\科学+修仙+创造世界"</LocalDebuggerCommandArguments>
|
||||
|
|
|
@ -12,6 +12,7 @@ NovelParser::NovelParser()
|
|||
{
|
||||
this->syntax_defines = example_novel::NovalSyntax::getParseTree();
|
||||
checker_list << std::make_shared<example_novel::FragmentExistsCheck>();
|
||||
checker_list << std::make_shared<example_novel::StoryOrderCheck>();
|
||||
checker_list << std::make_shared<example_novel::FragmentGraphCheck>();
|
||||
|
||||
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 {
|
||||
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 time_stamp = QTime::currentTime();
|
||||
for (auto& file : source_list) {
|
||||
auto tokens = lex_reader->tokensWithin(file.canonicalFilePath());
|
||||
auto exprs_result = this->syntax_defines->parse(context, tokens);
|
||||
context->setCurrentFile(file.canonicalFilePath());
|
||||
auto words = word_reader->wordsFrom(file.canonicalFilePath());
|
||||
auto exprs_result = this->syntax_defines->parse(context, words);
|
||||
forst_root.append(std::get<0>(exprs_result));
|
||||
}
|
||||
auto current_stamp = QTime::currentTime();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <iterator>
|
||||
#include <QTime>
|
||||
|
||||
using namespace lib_parse;
|
||||
using namespace example_novel;
|
||||
using namespace ast_basic;
|
||||
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) {
|
||||
auto refer = std::dynamic_pointer_cast<const FragmentRefers>(target->element());
|
||||
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()) {
|
||||
|
@ -28,7 +31,7 @@ void FragmentExistsCheck::validCheck(std::shared_ptr<const ElementAccess> root)
|
|||
}
|
||||
|
||||
QString FragmentExistsCheck::name() const {
|
||||
return u8"FragmentExistsCheck";
|
||||
return u8"情节引用有效性检查器";
|
||||
}
|
||||
|
||||
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()) {
|
||||
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) {
|
||||
error_msg += QString(u8"%1->").arg(n->nodePeer()->signature());
|
||||
}
|
||||
|
||||
if (cycle_link.size())
|
||||
throw new lib_parse::CheckException(error_msg);
|
||||
throw new CheckException(error_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString FragmentGraphCheck::name() const {
|
||||
return u8"FragmentGraphCheck";
|
||||
return u8"情节网络有效性检查器";
|
||||
}
|
||||
|
||||
FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr<const FragmentDefine> node) : node_peer(node) {}
|
||||
|
@ -223,3 +226,84 @@ uint& FragmentGraphHelper::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);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <ast_novel.h>
|
||||
|
||||
namespace example_novel {
|
||||
|
||||
class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider {
|
||||
private:
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
class FragmentGraphHelper;
|
||||
class LIBPARSE_EXPORT FragmentGraphCheck : public std::enable_shared_from_this<FragmentGraphCheck>, public lib_parse::CheckProvider {
|
||||
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
|
||||
|
|
|
@ -18,11 +18,11 @@ QString ast_basic::ExpressionElement::filePath() const {
|
|||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -34,10 +34,16 @@ void ast_basic::ExpressionElement::addChild(std::shared_ptr<const Expression> in
|
|||
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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if(expression_stack.size())
|
||||
|
|
|
@ -19,7 +19,6 @@ namespace ast_basic {
|
|||
* @return
|
||||
*/
|
||||
virtual std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const = 0;
|
||||
|
||||
//=====================================================
|
||||
/**
|
||||
* 获取语法节点的源码文件路径.
|
||||
|
@ -32,15 +31,19 @@ namespace ast_basic {
|
|||
*
|
||||
* \return token序列
|
||||
*/
|
||||
virtual QList<std::shared_ptr<const lib_token::Token>> tokens() const = 0;
|
||||
virtual void tokensReset(const QList<std::shared_ptr<const lib_token::Token>> &list) = 0;
|
||||
virtual QList<std::shared_ptr<const lib_token::IToken>> tokens() const = 0;
|
||||
/**
|
||||
* ÖØÖÃÓï·¨Token¼¯.
|
||||
*
|
||||
* \param list
|
||||
*/
|
||||
virtual void tokensReset(const QList<std::shared_ptr<const lib_token::IToken>> &list) = 0;
|
||||
/**
|
||||
* 解析过程中,向表达式内部添加token实例.
|
||||
*
|
||||
* \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 子表达式集合
|
||||
|
@ -60,29 +63,24 @@ namespace ast_basic {
|
|||
/**
|
||||
* @brief 表达式节点
|
||||
*/
|
||||
class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression,
|
||||
public std::enable_shared_from_this<ExpressionElement> {
|
||||
class LIBSYNTAX_EXPORT ExpressionElement : public ast_basic::Expression, public std::enable_shared_from_this<ExpressionElement> {
|
||||
private:
|
||||
std::shared_ptr<const lib_syntax::ExpressionRule> _expr_rule;
|
||||
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:
|
||||
ExpressionElement(std::shared_ptr<const lib_syntax::ExpressionRule> bind);
|
||||
|
||||
// 通过 Expression 继承
|
||||
std::shared_ptr<const lib_syntax::ExpressionRule> definedRule() const override;
|
||||
|
||||
QString filePath() const override;
|
||||
|
||||
QList<std::shared_ptr<const lib_token::Token>> tokens() const override;
|
||||
|
||||
void tokensReset(const QList<std::shared_ptr<const lib_token::Token>>& list) override;
|
||||
|
||||
void addToken(std::shared_ptr<const lib_token::Token> token_inst) 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 addToken(std::shared_ptr<const lib_token::IToken> token_inst) override;
|
||||
|
||||
QList<std::shared_ptr<const Expression>> children() const override;
|
||||
|
||||
void addChild(std::shared_ptr<const Expression> inst) override;
|
||||
};
|
||||
|
||||
|
@ -90,10 +88,13 @@ namespace ast_basic {
|
|||
private:
|
||||
QList<std::shared_ptr<const lib_syntax::BaseRule>> rule_stack;
|
||||
QList<std::shared_ptr<Expression>> expression_stack;
|
||||
QString current_file_path;
|
||||
|
||||
public:
|
||||
ExpressionContext(){}
|
||||
ExpressionContext();
|
||||
|
||||
virtual void setCurrentFile(const QString& path);
|
||||
virtual QString currentFile() const;
|
||||
|
||||
// 通过 ParseContext 继承
|
||||
std::shared_ptr<ast_basic::Expression> currentInst() const override;
|
||||
|
|
|
@ -10,18 +10,18 @@ GlobalElement::GlobalElement(const QString& name) :names_store(name) {
|
|||
|
||||
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());
|
||||
if (node_cache.contains(mixed_key))
|
||||
throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0004]系统中包含同类型重名命名节点:%1<type:%2>")
|
||||
.arg(named_node->signature()).arg(named_node->typeMark()));
|
||||
return node_cache[mixed_key];
|
||||
node_cache[mixed_key] = named_node;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const SyntaxElement> GlobalElement::getNamedNodeBy(int type, const QString& signature) const {
|
||||
auto mixed_key = QString(u8"%1<%2>").arg(signature).arg(type);
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -73,10 +73,10 @@ QList<std::shared_ptr<const TokenAccess>> ElementAccess::tokens() const {
|
|||
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) {}
|
||||
|
||||
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; }
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@ namespace ast_gen
|
|||
* @return 未设置parent,返回nullptr
|
||||
*/
|
||||
virtual std::shared_ptr<const SyntaxElement> parent() const = 0;
|
||||
/**
|
||||
* @brief ÖØÖø¸Ö¸Õë.
|
||||
*
|
||||
* \param inst
|
||||
*/
|
||||
virtual void setParent(std::shared_ptr<const SyntaxElement> inst) = 0;
|
||||
|
||||
/**
|
||||
|
@ -74,7 +79,6 @@ namespace ast_gen
|
|||
ElementAccess(std::shared_ptr<const SyntaxElement> point);
|
||||
|
||||
std::shared_ptr<const SyntaxElement> element() const;
|
||||
|
||||
QList<std::shared_ptr<const ElementAccess>> children() const;
|
||||
|
||||
/**
|
||||
|
@ -87,12 +91,12 @@ namespace ast_gen
|
|||
class LIBSYNTAX_EXPORT TokenAccess {
|
||||
private:
|
||||
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:
|
||||
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 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);
|
||||
|
||||
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 通过节点签名获取定义节点
|
||||
* @param signature 完全签名
|
||||
|
@ -118,7 +122,6 @@ namespace ast_gen
|
|||
* @throws 没有指定节点抛出异常
|
||||
*/
|
||||
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);
|
||||
|
||||
// ParseElement interface
|
||||
|
|
|
@ -2,25 +2,26 @@
|
|||
|
||||
|
||||
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) {}
|
||||
|
||||
QString example_novel::TextSection::content() const
|
||||
QString TextSection::content() const
|
||||
{
|
||||
return context_store;
|
||||
}
|
||||
|
||||
int TextSection::typeMark() const { return (int)NovelNode::TextSection; }
|
||||
|
||||
bool example_novel::TextSection::isAnonymous() const
|
||||
bool TextSection::isAnonymous() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QString TextSection::signature() const { return u8"::section"; }
|
||||
|
||||
void example_novel::TextSection::cacheLoad()
|
||||
void TextSection::cacheLoad()
|
||||
{
|
||||
QString text;
|
||||
for (auto& t : selfTokens()) {
|
||||
|
@ -29,14 +30,14 @@ void example_novel::TextSection::cacheLoad()
|
|||
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) {}
|
||||
|
||||
QString FragmentRefers::storyRefer() const { return story_refs; }
|
||||
|
||||
QString FragmentRefers::fragmentRefer() const { return fragment_ref; }
|
||||
|
||||
void example_novel::FragmentRefers::cacheLoad()
|
||||
void FragmentRefers::cacheLoad()
|
||||
{
|
||||
this->story_refs = selfTokens()[5]->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; }
|
||||
|
||||
bool example_novel::FragmentRefers::isAnonymous() const
|
||||
bool FragmentRefers::isAnonymous() const
|
||||
{
|
||||
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) {}
|
||||
|
||||
QString FragmentDefine::name() const { return name_store; }
|
||||
|
||||
void example_novel::FragmentDefine::cacheLoad()
|
||||
void FragmentDefine::cacheLoad()
|
||||
{
|
||||
name_store = selfTokens()[2]->token()->content();
|
||||
}
|
||||
int FragmentDefine::typeMark() const { return (int)NovelNode::FragmentDefine; }
|
||||
|
||||
bool example_novel::FragmentDefine::isAnonymous() const
|
||||
bool FragmentDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -77,14 +78,18 @@ bool example_novel::FragmentDefine::isAnonymous() const
|
|||
QString FragmentDefine::signature() const { return parent()->signature() + u8"&" + name(); }
|
||||
|
||||
|
||||
StoryDefine::StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind) {}
|
||||
StoryDefine::StoryDefine(std::shared_ptr<const ExpressionRule> rule_bind)
|
||||
: AbstractImpl(rule_bind), sort_index(0) {}
|
||||
|
||||
QString StoryDefine::name() const { return name_store; }
|
||||
|
||||
void example_novel::StoryDefine::setSort(int value){
|
||||
sort_index = value;
|
||||
}
|
||||
|
||||
int StoryDefine::sort() const { return sort_index; }
|
||||
|
||||
void example_novel::StoryDefine::cacheLoad()
|
||||
void StoryDefine::cacheLoad()
|
||||
{
|
||||
name_store = selfTokens()[3]->token()->content();
|
||||
sort_index = selfTokens()[2]->token()->content().toInt();
|
||||
|
@ -92,7 +97,7 @@ void example_novel::StoryDefine::cacheLoad()
|
|||
|
||||
int StoryDefine::typeMark() const { return (int)NovelNode::StoryDefine; }
|
||||
|
||||
bool example_novel::StoryDefine::isAnonymous() const
|
||||
bool StoryDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -100,23 +105,23 @@ bool example_novel::StoryDefine::isAnonymous() const
|
|||
QString StoryDefine::signature() const { return name(); }
|
||||
|
||||
#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) {}
|
||||
|
||||
int Document::typeMark() const { return (int)NovelNode::Document; }
|
||||
|
||||
bool example_novel::Document::isAnonymous() const
|
||||
bool Document::isAnonymous() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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(); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// ͨ¹ý 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();
|
||||
}
|
||||
|
||||
QString example_novel::AbstractImpl::path() const
|
||||
QString AbstractImpl::path() const
|
||||
{
|
||||
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) {}
|
||||
|
||||
QString VolumeDefine::name() const { return name_store; }
|
||||
|
||||
void example_novel::VolumeDefine::cacheLoad()
|
||||
void VolumeDefine::cacheLoad()
|
||||
{
|
||||
name_store = selfTokens()[2]->token()->content();
|
||||
}
|
||||
|
||||
int VolumeDefine::typeMark() const { return (int)NovelNode::VolumeDefine; }
|
||||
|
||||
bool example_novel::VolumeDefine::isAnonymous() const
|
||||
bool VolumeDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {}
|
||||
|
||||
QString ArticleDefine::name() const { return name_store; }
|
||||
|
||||
void example_novel::ArticleDefine::cacheLoad()
|
||||
void ArticleDefine::cacheLoad()
|
||||
{
|
||||
name_store = selfTokens()[2]->token()->content();
|
||||
}
|
||||
|
||||
int ArticleDefine::typeMark() const { return (int)NovelNode::ArticleDefine; }
|
||||
|
||||
bool example_novel::ArticleDefine::isAnonymous() const
|
||||
bool ArticleDefine::isAnonymous() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
namespace example_novel
|
||||
{
|
||||
enum class NovelNode {
|
||||
GlobalElement = 0,
|
||||
TextSection = 1,
|
||||
FragmentRefer = 2,
|
||||
FragmentDefine = 3,
|
||||
|
@ -12,10 +13,10 @@ namespace example_novel
|
|||
Document = 5,
|
||||
ArticleDefine = 6,
|
||||
VolumeDefine = 7,
|
||||
RankDeclaration = 8,
|
||||
};
|
||||
|
||||
class LIBSYNTAX_EXPORT AbstractImpl :
|
||||
public ast_basic::ExpressionElement, public ast_gen::SyntaxElement {
|
||||
class LIBSYNTAX_EXPORT AbstractImpl : public ast_basic::ExpressionElement, public ast_gen::SyntaxElement {
|
||||
private:
|
||||
std::weak_ptr<const SyntaxElement> parent_store;
|
||||
|
||||
|
@ -123,6 +124,7 @@ namespace example_novel
|
|||
StoryDefine(std::shared_ptr<const lib_syntax::ExpressionRule> rule_bind);
|
||||
|
||||
QString name() const;
|
||||
void setSort(int value);
|
||||
int sort() const;
|
||||
|
||||
// SyntaxElement interface
|
||||
|
@ -148,4 +150,19 @@ namespace example_novel
|
|||
virtual QString signature() const 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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,30 +6,28 @@ using namespace std;
|
|||
using namespace lib_token;
|
||||
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>>(); }
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> TokenMatch::match(std::shared_ptr<const Token> remains_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 {
|
||||
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 {
|
||||
if (!head)
|
||||
throw std::make_shared<InputTerminal>();
|
||||
throw new InputTerminal(rt_inst->currentFile());
|
||||
|
||||
if (head->define()->typeMark() == define_peer->typeMark()) {
|
||||
rt_inst->currentInst()->addToken(head);
|
||||
return std::make_tuple(nullptr, head->nextToken());
|
||||
auto match_result = define_peer->analysis(head);
|
||||
if (std::get<0>(match_result)) {
|
||||
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 {
|
||||
|
@ -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; }
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> Rept::match(std::shared_ptr<const Token> list_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 {
|
||||
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 temp_head = head;
|
||||
|
||||
// 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);
|
||||
}
|
||||
catch (std::shared_ptr<MismatchException> ex) {
|
||||
return std::make_tuple(nullptr, temp_head);
|
||||
}
|
||||
catch (std::shared_ptr<InputTerminal> ex) {
|
||||
catch (SyntaxException* ex) {
|
||||
delete ex;
|
||||
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; }
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> Seqs::match(std::shared_ptr<const Token> list_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 {
|
||||
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 temp_head = head;
|
||||
|
||||
for (auto& r : mbrs_store) {
|
||||
|
@ -160,53 +99,30 @@ QString Seqs::token_present() const
|
|||
return QString(u8"(%1)").arg(content);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const BaseRule>, std::shared_ptr<const Token>>
|
||||
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; }
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> Any::match(std::shared_ptr<const Token> list_head) const {
|
||||
auto item = rule_select(list_head);
|
||||
return std::make_tuple(std::get<0>(item), std::get<1>(item), std::get<3>(item));
|
||||
}
|
||||
|
||||
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::function<int(std::shared_ptr<const Token>, std::shared_ptr<const Token>)> measure_span =
|
||||
[&](std::shared_ptr<const Token> anchor, std::shared_ptr<const Token> head)->int {
|
||||
if (anchor == head)
|
||||
return 1;
|
||||
return measure_span(anchor, head->nextToken()) + 1;
|
||||
class words_span {
|
||||
public:
|
||||
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 IWordBase>> Any::parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const IWordBase> head) const {
|
||||
std::function<words_span(std::shared_ptr<const IWordBase>, std::shared_ptr<const IWordBase>)> measure_span =
|
||||
[&](std::shared_ptr<const IWordBase> anchor, std::shared_ptr<const IWordBase> head)->words_span {
|
||||
return words_span(anchor->row() - head->row(), anchor->column() - head->column());
|
||||
};
|
||||
|
||||
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) {
|
||||
try {
|
||||
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));
|
||||
}
|
||||
// Óï·¨´íÎóµÄ»á½øÐбȽÏ
|
||||
catch (std::shared_ptr<MismatchException> ex) {
|
||||
auto current_span = measure_span(ex->targetToken(), head);
|
||||
catch (MismatchException* ex) {
|
||||
auto current_span = measure_span(ex->targetWord(), head);
|
||||
|
||||
if (current_span > std::get<1>(temp_result))
|
||||
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;
|
||||
}
|
||||
|
||||
std::tuple<BaseRule::MatchResult, uint, std::shared_ptr<const Token>> ExpressionRule::match(std::shared_ptr<const Token> list_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::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 {
|
||||
std::shared_ptr<Expression> elm_ast = this->newEmptyInstance();
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
MismatchException::MismatchException(std::shared_ptr<const lib_token::Token> inst) :SyntaxException(
|
||||
QString(u8"Syntax[0x00001]语法匹配错误,不能识别token:%1<%2,%3>").arg(inst->content()).arg(inst->row()).arg(inst->column())), target(inst) {}
|
||||
MismatchException::MismatchException(std::shared_ptr<const lib_token::IWordBase> inst) :SyntaxException(
|
||||
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;
|
||||
}
|
||||
|
||||
InputTerminal::InputTerminal() :SyntaxException(u8"Syntax[0x0000]token流提前终止") {}
|
||||
InputTerminal::InputTerminal(const QString& file_path)
|
||||
:SyntaxException(QString(u8"Syntax[0x0000]token流(%1)提前终止").arg(file_path)) {}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace lib_syntax {
|
|||
/**
|
||||
* @brief 语法异常
|
||||
*/
|
||||
class SyntaxException {
|
||||
class LIBSYNTAX_EXPORT SyntaxException {
|
||||
private:
|
||||
QString msg_store;
|
||||
|
||||
|
@ -35,6 +35,9 @@ namespace lib_syntax {
|
|||
public:
|
||||
virtual ~ParseContext() = default;
|
||||
|
||||
virtual void setCurrentFile(const QString &path) = 0;
|
||||
virtual QString currentFile() const = 0;
|
||||
|
||||
/**
|
||||
* \brief 当前表达式元素.
|
||||
*
|
||||
|
@ -70,20 +73,14 @@ namespace lib_syntax {
|
|||
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 解析
|
||||
* @param rt_inst 解析上下文
|
||||
* @param head 列表头
|
||||
* @return 返回结果<匹配完成新列表头,匹配长度>
|
||||
*/
|
||||
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::Token> head) const = 0;
|
||||
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::IWordBase> head) const = 0;
|
||||
|
||||
/**
|
||||
* 返回匹配语法规则的词法序列表达
|
||||
|
@ -99,17 +96,16 @@ namespace lib_syntax {
|
|||
*/
|
||||
class LIBSYNTAX_EXPORT TokenMatch : public BaseRule, public std::enable_shared_from_this<TokenMatch> {
|
||||
private:
|
||||
std::shared_ptr<const lib_token::TokenDefine> define_peer;
|
||||
std::shared_ptr<const lib_token::ITokenDefine> define_peer;
|
||||
|
||||
public:
|
||||
TokenMatch(std::shared_ptr<const lib_token::TokenDefine> define);
|
||||
TokenMatch(std::shared_ptr<const lib_token::ITokenDefine> define);
|
||||
|
||||
// BaseRule interface
|
||||
public:
|
||||
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::Token>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, 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>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
|
@ -120,7 +116,7 @@ namespace lib_syntax {
|
|||
private:
|
||||
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:
|
||||
Any(const QList<std::shared_ptr<const BaseRule>> mbrs);
|
||||
|
@ -128,9 +124,8 @@ namespace lib_syntax {
|
|||
// BaseRule interface
|
||||
public:
|
||||
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::Token>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, 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>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
|
@ -147,9 +142,8 @@ namespace lib_syntax {
|
|||
// BaseRule interface
|
||||
public:
|
||||
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::Token>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, 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>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
|
||||
virtual QString token_present() const override;
|
||||
};
|
||||
|
||||
|
@ -167,9 +161,8 @@ namespace lib_syntax {
|
|||
// BaseRule interface
|
||||
public:
|
||||
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::Token>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, 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>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) 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> {
|
||||
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);
|
||||
|
||||
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
|
||||
public:
|
||||
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::Token>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, 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>>
|
||||
parse(std::shared_ptr<ParseContext> rt_inst, std::shared_ptr<const lib_token::IWordBase> head) const override;
|
||||
virtual QString token_present() const override;
|
||||
|
||||
private:
|
||||
|
@ -226,17 +218,17 @@ namespace lib_syntax {
|
|||
|
||||
class MismatchException : public SyntaxException {
|
||||
private:
|
||||
std::shared_ptr<const lib_token::Token> target;
|
||||
std::shared_ptr<const lib_token::IWordBase> target;
|
||||
|
||||
public:
|
||||
MismatchException(std::shared_ptr<const lib_token::Token> inst);
|
||||
MismatchException(std::shared_ptr<const lib_token::IWordBase> inst);
|
||||
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 {
|
||||
public:
|
||||
InputTerminal();
|
||||
InputTerminal(const QString &file_path);
|
||||
};
|
||||
} // namespace lib_syntax
|
|
@ -11,7 +11,9 @@ using namespace ast_basic;
|
|||
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"排序", u8"rank-symbol", 0xAEu); // 排序
|
||||
auto story_key = std::make_shared<Keywords>(u8"¹ÊÊÂ", u8"story-mark", 0xAAu); // ¹ÊÊÂ
|
||||
auto numbers = std::make_shared<Numbers>(); // [0-9]+
|
||||
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))
|
||||
));
|
||||
|
||||
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>(
|
||||
Rules{
|
||||
OptMulT(newl),
|
||||
std::make_shared<const Rept>(rank_define, 0, 1),
|
||||
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 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);
|
||||
node_register(root, children);
|
||||
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();
|
||||
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);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (!child->isAnonymous())
|
||||
ast_gen::GlobalElement::UniquePtr->appendToCache(child);
|
||||
if (!child->isAnonymous()) {
|
||||
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;
|
||||
for (auto& it : child->bindExpression()->children()) {
|
||||
|
@ -139,11 +149,4 @@ void example_novel::NovalSyntax::node_register(std::shared_ptr<const ast_gen::Sy
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -24,14 +24,6 @@ namespace example_novel {
|
|||
|
||||
class LIBSYNTAX_EXPORT NovalSyntax {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取novel词法解析器
|
||||
* @param path 文件路径
|
||||
* @param name 文件名称
|
||||
* @return
|
||||
*/
|
||||
static std::shared_ptr<const lib_token::TokenReader> getLexReader();
|
||||
|
||||
/**
|
||||
* @brief 获取novel语法解析树
|
||||
* @return
|
||||
|
|
Loading…
Reference in New Issue