接口类分离

This commit is contained in:
玉宇清音 2022-11-25 09:18:54 +08:00
parent 3ded30b981
commit 86197338e2
42 changed files with 759 additions and 89 deletions

View File

@ -26,6 +26,7 @@ HEADERS += \
DISTFILES += \
example.storyboard \
example.storychain \
example.storyconcept \
example.storyunit \
example.storyvolume

View File

@ -0,0 +1,5 @@
#概念 修炼功法{
#要点 资质{
ad浪费看啊;df
}
}

View File

@ -40,7 +40,7 @@ int main(int argc, char *argv[])
MakeTools::StoryTool tool(&core);
// auto path = "D:\\Projects\\Cpp\\QtNovelDesc\\DesParser\\example.storyvolume";
auto path = "D:\\测试文学项目\\contentfile_851382615.storyboard";
auto path = "D:\\Projects\\Cpp\\QtNovelDesc\\DesParser\\example.storyconcept";
tool.compile(QFileInfo(path), "后台编译");
auto doc = core.queryDocument(QFileInfo(path));

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.15.0, 2022-11-19T21:24:59. -->
<!-- Written by QtCreator 4.15.0, 2022-11-24T10:20:15. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@ -10,7 +10,7 @@ namespace ContentPresent {
/**
* @brief
*/
class ModeView : public Core::FileExtension
class ModeView : public Core::Extension
{
public:
virtual ~ModeView() = default;

View File

@ -59,7 +59,7 @@ void TextContentEdit::reload(QList<Config::Configration *> configs)
default_font.setFamily(font_family);
default_font.setPointSize(font_size.toInt());
this->edit_square->document()->setDefaultFont(default_font);
this->textDocument()->setDefaultFont(default_font);
this->rehighlighter();
}
@ -77,6 +77,16 @@ FormattedTextEdit::FormattedTextEdit()
});
}
void FormattedTextEdit::resetHighlighter(QSyntaxHighlighter *lighter)
{
lighter->setDocument(this->edit_square->document());
}
QTextDocument *FormattedTextEdit::textDocument() const
{
return edit_square->document();
}
QWidget *FormattedTextEdit::textView() const
{
@ -135,7 +145,7 @@ TextContentEditFactory::TextContentEditFactory()
}
FileExtension *TextContentEditFactory::newInstance(Core::AppCore *core)
Extension *TextContentEditFactory::newInstance(Core::AppCore *core)
{
return new TextContentEdit(this);
}

View File

@ -17,6 +17,8 @@ namespace Components {
FormattedTextEdit();
virtual ~FormattedTextEdit() = default;
void resetHighlighter(QSyntaxHighlighter *lighter);
QTextDocument *textDocument() const;
// VariedTextView interface
public:
@ -26,11 +28,9 @@ namespace Components {
protected:
QTextEdit *const edit_square;
QList<Config::Configration*> configrations_host;
virtual void rehighlighter() = 0;
QTextEdit *const edit_square;
};
class TextContentEditFactory : public Core::FileExtensionFactory
@ -41,7 +41,7 @@ namespace Components {
// PluginFactory interface
public:
virtual Core::FileExtension *newInstance(Core::AppCore *core) override;
virtual Core::Extension *newInstance(Core::AppCore *core) override;
virtual QList<Core::Scale> configs() const override;
virtual QWidget *getNewPanel(Config::Configration *config) override;
virtual QString extensionName() const override;

View File

@ -13,12 +13,14 @@ SOURCES += \
SensitiveCore.cpp \
SourceEditView.cpp \
appcore.cpp \
conceptview.cpp \
keywordshightlighter.cpp \
main.cpp \
mainwindow.cpp \
messagepresent.cpp \
projectview.cpp \
storyboardsourceedit.cpp \
storyboardspresent.cpp \
storychainsourceeditor.cpp \
storychainspresent.cpp \
storyunitsourceedit.cpp \
@ -30,11 +32,13 @@ HEADERS += \
SensitiveCore.h \
SourceEditView.h \
appcore.h \
conceptview.h \
keywordshightlighter.h \
mainwindow.h \
messagepresent.h \
projectview.h \
storyboardsourceedit.h \
storyboardspresent.h \
storychainsourceeditor.h \
storychainspresent.h \
storyunitsourceedit.h \

View File

@ -117,7 +117,7 @@ void AppCore::openTextDocument(const QString &src, const QString &name)
tview->setSource(this, QFileInfo(src), name, views);
framework->addPerceptionList(tview);
dynamic_cast<Core::FileExtension*>(tview)->reload(this->getConfigs(QList<Scale>() << Scale::Global << Scale::Project));
dynamic_cast<Core::Extension*>(tview)->reload(this->getConfigs(QList<Scale>() << Scale::Global << Scale::Project));
QFile fin(src);
if(!fin.open(QIODevice::ReadOnly | QIODevice::Text)){

View File

@ -14,7 +14,7 @@ namespace MakeTools {
}
namespace Core {
class FileExtensionFactory;
class Extension;
class AppCore;
enum class Scale
@ -24,36 +24,16 @@ namespace Core {
File,
};
class FileExtension
{
class ExtensionFactory{
public:
virtual ~FileExtension() = default;
/**
* @brief
* @return
*/
virtual FileExtensionFactory* factory() const = 0;
/**
* @brief
* @param configs
*/
virtual void reload(QList<Config::Configration*> configs) = 0;
};
class FileExtensionFactory
{
public:
virtual ~FileExtensionFactory() = default;
virtual ~ExtensionFactory() = default;
/**
* @brief
* @param core
* @return
*/
virtual FileExtension* newInstance(AppCore *core) = 0;
virtual Extension* newInstance(AppCore *core) = 0;
/**
* @brief
@ -69,6 +49,32 @@ namespace Core {
virtual QWidget* getNewPanel(Config::Configration* config) = 0;
virtual QString extensionName() const = 0;
};
class Extension
{
public:
virtual ~Extension() = default;
/**
* @brief
* @return
*/
virtual ExtensionFactory* factory() const = 0;
/**
* @brief
* @param configs
*/
virtual void reload(QList<Config::Configration*> configs) = 0;
};
class FileExtensionFactory : public ExtensionFactory
{
public:
virtual ~FileExtensionFactory() = default;
/**
* @brief

103
WordsIDE/conceptview.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "conceptview.h"
#include "SensitiveCore.h"
#include <QSplitter>
#include <QVBoxLayout>
using namespace Components;
using namespace Core;
using namespace Parse::Result;
ConceptView::ConceptView(Core::AppCore *core, QWidget *parent)
: QWidget(parent), core_ins(core),
tree_view(new QTreeView(this)),
model_base(new QStandardItemModel(this)),
details_view(new QTextBrowser(this))
{
tree_view->setHeaderHidden(true);
auto layout = new QVBoxLayout(this);
layout->setMargin(0);
auto splitter = new QSplitter(Qt::Vertical, this);
layout->addWidget(splitter);
splitter->addWidget(tree_view);
splitter->addWidget(details_view);
tree_view->setModel(model_base);
details_view->setReadOnly(true);
connect(tree_view, &QTreeView::clicked, this, &ConceptView::show_node_description);
connect(tree_view, &QTreeView::doubleClicked, this, &ConceptView::click_to);
}
void ConceptView::refresh()
{
model_base->clear();
auto units = core_ins->parseCore()->allStoryConcept();
for(auto &unit : units){
auto unit_node = new QStandardItem(static_cast<NamedNode*>(unit)->name()[0]);
unit_node->setEditable(false);
model_base->appendRow(unit_node);
auto children = unit->children();
for(auto &frag : children){
if(frag->typeValue() == NODE_STORYSTRONGPOINT){
auto frag_node = new QStandardItem(static_cast<NamedNode*>(frag)->name()[0]);
frag_node->setEditable(false);
unit_node->appendRow(frag_node);
}
}
}
}
void ConceptView::show_node_description(const QModelIndex &curr)
{
if(!curr.isValid())
return;
details_view->clear();
auto item = model_base->itemFromIndex(curr);
if(item->parent() == nullptr){
auto node = core_ins->parseCore()->queryStoryConcept(item->text());
auto children = node.first()->children();
for(auto &it : children){
if(it->typeValue() != NODE_STORYSTRONGPOINT){
details_view->append(it->toString());
}
}
}
else{
auto node = core_ins->parseCore()->queryStoryConcept(item->parent()->text());
auto point = core_ins->parseCore()->queryStoryStrongPoint(node.first(), item->text());
auto children = point.first()->children();
for(auto &it : children){
details_view->append(it->toString());
}
}
}
void ConceptView::click_to(const QModelIndex &curr)
{
if(!curr.isValid())
return;
auto pnode = this->model_base->itemFromIndex(curr);
QList<QString> path;
while (pnode) {
path.insert(0, pnode->text());
pnode = pnode->parent();
}
auto unit_ins = this->core_ins->parseCore()->queryStoryConcept(path[0]).first();
auto chain_doc = unit_ins->doc();
this->core_ins->openTextDocument(chain_doc->filePath(), chain_doc->docName());
auto present = this->core_ins->getFramework()->queryTextComponent(QFileInfo(chain_doc->filePath()));
if(path.size()){
present->jumpTo(path);
}
}

31
WordsIDE/conceptview.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef CONCEPTVIEW_H
#define CONCEPTVIEW_H
#include "appcore.h"
#include <QObject>
#include <QTextBrowser>
#include <QTreeView>
#include <QWidget>
namespace Components {
class ConceptView : public QWidget
{
public:
ConceptView(Core::AppCore *core, QWidget *parent=nullptr);
virtual void refresh();
private:
Core::AppCore *const core_ins;
QTreeView *const tree_view;
QStandardItemModel *const model_base;
QTextBrowser *const details_view;
void show_node_description(const QModelIndex &curr);
void click_to(const QModelIndex &curr);
};
}
#endif // CONCEPTVIEW_H

View File

@ -42,7 +42,9 @@ MainWindow::MainWindow(QWidget *parent)
project_structure(new ProjectView(app_core, project_manager, this)),
chains_view(new StoryChainsPresent(app_core, this)),
units_view(new StoryUnitsPresent(app_core, this)),
errors_present(new MessagePresent(app_core->getMake_tool(), this))
errors_present(new MessagePresent(app_core->getMake_tool(), this)),
boards_view(new StoryBoardsPresent(app_core, this)),
concept_view(new ConceptView(app_core, this))
{
QApplication::instance()->installEventFilter(this);
this->app_core->setCurrentProject(project_manager);
@ -53,6 +55,8 @@ MainWindow::MainWindow(QWidget *parent)
chains_view->setVisible(false);
units_view->setVisible(false);
errors_present->setVisible(false);
boards_view->setVisible(false);
concept_view->setVisible(false);
project_structure->setVisible(false);
left_funcs->setVisible(false);
right_funcs->setVisible(false);
@ -254,6 +258,24 @@ MainWindow::MainWindow(QWidget *parent)
sync_kernel->registerAutoRun([this]()->bool{return right_funcs->indexOf(units_view)!=-1;},
[unit_v](bool v){if(v != unit_v->isChecked()) unit_v->setChecked(v);});
}
// 故事统计
{
auto board_v = func->addAction("故事统计", [this](bool v){
toggle_widget_visible(v, right_funcs, boards_view, "故事统计");
});
board_v->setCheckable(true);
sync_kernel->registerAutoRun([this]()->bool{return right_funcs->indexOf(boards_view)!=-1;},
[board_v](bool v){if(v!=board_v->isChecked()) board_v->setChecked(v);});
}
// 概念统计
{
auto concept_v = func->addAction("概念统计", [this](bool v){
toggle_widget_visible(v, right_funcs, concept_view, "概念统计");
});
concept_v->setCheckable(true);
sync_kernel->registerAutoRun([this]()->bool{return right_funcs->indexOf(concept_view)!=-1;},
[concept_v](bool v){if(v != concept_v->isChecked()) concept_v->setChecked(v);});
}
// 工具菜单
auto tool = mbar->addMenu("工具");
@ -325,6 +347,7 @@ MainWindow::MainWindow(QWidget *parent)
this->chains_view->refresh();
this->units_view->refresh();
this->errors_present->refresh();
this->boards_view->refresh();
});
@ -381,9 +404,15 @@ void MainWindow::build_internal(bool all_from_disk)
for(auto &it : volumes)
app_core->getMake_tool()->compile(std::get<0>(it), std::get<1>(it));
auto concepts = project_manager->filesWithEnds("storyconcept");
for(auto &it : concepts)
app_core->getMake_tool()->compile(std::get<0>(it), std::get<1>(it));
errors_present->refresh();
chains_view->refresh();
units_view->refresh();
boards_view->refresh();
concept_view->refresh();
}
void MainWindow::toggle_widget_visible(bool visible, QTabWidget *con, QWidget *target, const QString &title)

View File

@ -14,6 +14,8 @@
#include "storyunitspresent.h"
#include "projectview.h"
#include "ContentPresent.h"
#include "storyboardspresent.h"
#include "conceptview.h"
class Run
@ -77,6 +79,8 @@ private:
Components::StoryChainsPresent *const chains_view;
Components::StoryUnitsPresent *const units_view;
Components::MessagePresent *const errors_present;
Components::StoryBoardsPresent *const boards_view;
Components::ConceptView *const concept_view;
// 内部逻辑 ===========================================
void build_internal(bool all_from_disk = false);

View File

@ -71,6 +71,7 @@ void Components::ProjectView::contexMenuPopup(const QPoint &pos)
newm->addAction("新建单元", [this, &idx_it](){ alloc_file(idx_it, "单元", "storyunit"); });
newm->addAction("新建故事", [this, &idx_it](){ alloc_file(idx_it, "故事", "storyboard"); });
newm->addAction("新建行文", [this, &idx_it](){ alloc_file(idx_it, "行文", "storyvolume"); });
newm->addAction("新建概念", [this, &idx_it](){ alloc_file(idx_it, "概念", "storyconcept"); });
popup.addSeparator();
popup.addAction("修改名称", [this, &idx_it](){
if(!idx_it.isValid())

View File

@ -14,7 +14,7 @@ using namespace Core;
StoryBoardSourceEdit::StoryBoardSourceEdit(FileExtensionFactory *factory)
: words_highlighter(new KeywordsHightlighter(this)), factory_ins(factory)
{
words_highlighter->setDocument(this->edit_square->document());
this->resetHighlighter(words_highlighter);
edit_square->setContextMenuPolicy(Qt::CustomContextMenu);
connect(edit_square, &QTextEdit::customContextMenuRequested, [this](const QPoint &pos){
@ -94,7 +94,7 @@ void StoryBoardSourceEdit::rehighlighter()
this->words_highlighter->rehighlight();
}
FileExtension *StoryBoardSourceEditFactory::newInstance(Core::AppCore *core)
Extension *StoryBoardSourceEditFactory::newInstance(Core::AppCore *core)
{
return new StoryBoardSourceEdit(this);
}

View File

@ -11,7 +11,7 @@ namespace Components {
// PluginFactory interface
public:
virtual Core::FileExtension *newInstance(Core::AppCore *core) override;
virtual Core::Extension *newInstance(Core::AppCore *core) override;
virtual QList<Core::Scale> configs() const override;
virtual QWidget *getNewPanel(Config::Configration *config) override;
virtual QString extensionName() const override;

View File

@ -0,0 +1,56 @@
#include "storyboardspresent.h"
#include <QSplitter>
#include <QVBoxLayout>
using namespace Components;
using namespace Parse::Result;
StoryBoardsPresent::StoryBoardsPresent(Core::AppCore *core, QWidget *parent)
: QWidget(parent), core_ins(core),
tree_view(new QTreeView(this)), details_view(new QTextEdit(this)),
model_base(new QStandardItemModel(this))
{
tree_view->setModel(model_base);
auto layout = new QVBoxLayout(this);
layout->setMargin(0);
auto splitter= new QSplitter(Qt::Vertical, this);
layout->addWidget(splitter);
splitter->addWidget(tree_view);
splitter->addWidget(details_view);
details_view->setReadOnly(true);
connect(tree_view, &QTreeView::expanded, [this](){
tree_view->resizeColumnToContents(0);
tree_view->resizeColumnToContents(1);
});
}
void StoryBoardsPresent::refresh()
{
model_base->clear();
model_base->setHorizontalHeaderLabels(QStringList() << "名称" << "单元");
auto storys = core_ins->parseCore()->allStoryBoards();
for(auto &b : storys){
auto item = new QStandardItem(static_cast<NamedNode*>(b)->name()[0]);
item->setEditable(false);
model_base->appendRow(item);
auto refers = b->children();
for(auto &ref : refers){
if(ref->typeValue() != NODE_FRAGMENTREFERENCE)
continue;
QList<QStandardItem*> row;
row << new QStandardItem("@"+static_cast<NamedNode*>(ref)->name()[0]);
row.last()->setEditable(false);
row << new QStandardItem(static_cast<NamedNode*>(ref)->name()[1]);
row.last()->setEditable(false);
item->appendRow(row);
}
}
}

View File

@ -0,0 +1,31 @@
#ifndef STORYBOARDSPRESENT_H
#define STORYBOARDSPRESENT_H
#include "appcore.h"
#include <QTextEdit>
#include <QTreeView>
#include <QWidget>
namespace Components {
class StoryBoardsPresent : public QWidget
{
public:
StoryBoardsPresent(Core::AppCore *core, QWidget *parent=nullptr);
void refresh();
private:
Core::AppCore *const core_ins;
QTreeView *const tree_view;
QTextEdit *const details_view;
QStandardItemModel *const model_base;
void show_current_details(const QModelIndex &idx);
void click_to(const QModelIndex &idx);
};
}
#endif // STORYBOARDSPRESENT_H

View File

@ -119,7 +119,7 @@ namespace __temp {
}
StoryChainSourceEditFactory::StoryChainSourceEditFactory(){}
Core::FileExtension *Components::StoryChainSourceEditFactory::newInstance(Core::AppCore *core)
Core::Extension *Components::StoryChainSourceEditFactory::newInstance(Core::AppCore *core)
{
return new StoryChainSourceEdit(this);
}

View File

@ -18,7 +18,7 @@ namespace Components {
// PluginFactory interface
public:
virtual Core::FileExtension *newInstance(Core::AppCore *core) override;
virtual Core::Extension *newInstance(Core::AppCore *core) override;
virtual QList<Core::Scale> configs() const override;
virtual QWidget *getNewPanel(Config::Configration *config) override;
virtual QString extensionName() const override;

View File

@ -32,14 +32,14 @@ void StoryChainsPresent::refresh()
model_base->clear();
auto list = core_ins->parseCore()->allStoryChains();
for(auto &chain : list){
auto chain_node = new QStandardItem(static_cast<NamedNode*>(chain)->name());
auto chain_node = new QStandardItem(static_cast<NamedNode*>(chain)->name()[0]);
chain_node->setEditable(false);
model_base->appendRow(chain_node);
auto children = chain->children();
for(auto &point : children){
if(point->typeValue() == NODE_STORYPOINT){
auto point_node = new QStandardItem(static_cast<NamedNode*>(point)->name());
auto point_node = new QStandardItem(static_cast<NamedNode*>(point)->name()[0]);
point_node->setEditable(false);
chain_node->appendRow(point_node);
}

View File

@ -109,7 +109,7 @@ void StoryUnitSourceEdit::jumpTo(const QList<QString> &path)
edit_square->setFocus();
}
FileExtension *StoryUnitSourceEditFactory::newInstance(Core::AppCore *core)
Extension *StoryUnitSourceEditFactory::newInstance(Core::AppCore *core)
{
return new StoryUnitSourceEdit(this);
}

View File

@ -10,7 +10,7 @@ namespace Components {
// PluginFactory interface
public:
virtual Core::FileExtension *newInstance(Core::AppCore *core) override;
virtual Core::Extension *newInstance(Core::AppCore *core) override;
virtual QList<Core::Scale> configs() const override;
virtual QWidget *getNewPanel(Config::Configration *config) override;
virtual QString extensionName() const override;

View File

@ -36,14 +36,14 @@ void StoryUnitsPresent::refresh()
model_ins->clear();
auto units = core_ins->parseCore()->allStoryUnits();
for(auto &unit : units){
auto unit_node = new QStandardItem(static_cast<NamedNode*>(unit)->name());
auto unit_node = new QStandardItem(static_cast<NamedNode*>(unit)->name()[0]);
unit_node->setEditable(false);
model_ins->appendRow(unit_node);
auto children = unit->children();
for(auto &frag : children){
if(frag->typeValue() == NODE_STORYFRAGMENT){
auto frag_node = new QStandardItem(static_cast<NamedNode*>(frag)->name());
auto frag_node = new QStandardItem(static_cast<NamedNode*>(frag)->name()[0]);
frag_node->setEditable(false);
unit_node->appendRow(frag_node);
}

View File

@ -84,7 +84,7 @@ void StoryVolumeSourceEdit::jumpTo(const QList<QString> &path)
}
FileExtension *StoryVolumeSourceEditFactory::newInstance(Core::AppCore *core)
Extension *StoryVolumeSourceEditFactory::newInstance(Core::AppCore *core)
{
return new StoryVolumeSourceEdit(this);
}

View File

@ -11,7 +11,7 @@ namespace Components {
// PluginFactory interface
public:
virtual Core::FileExtension *newInstance(Core::AppCore *core) override;
virtual Core::Extension *newInstance(Core::AppCore *core) override;
virtual QList<Core::Scale> configs() const override;
virtual QWidget *getNewPanel(Config::Configration *config) override;
virtual QString extensionName() const override;

View File

@ -20,9 +20,14 @@
#define NODE_STORYDEPICTION 11 // 卷宗叙述节点
#define NODE_STORYCONCEPT 20 // 故事概念
#define NODE_STORYSTRONGPOINT 21 // 故事要点
#define DOC_STORYBOARD 0xa0001 // 故事板
#define DOC_STORYUNIT 0xa0002 // 故事单元
#define DOC_STORYCHAIN 0xa0003 // 故事脉络
#define DOC_VOLUMEOUTLINE 0xa0004 // 卷宗大纲
#define DOC_STORYCONCEPT 0xa0005 // 故事概念

View File

@ -11,7 +11,8 @@ ParseFrame::ParseFrame() {}
QList<DesNode*> ParseFrame::analysis(DocCore*doc, const QString & path)
{
ExStream stream;
if (stream.initSource(path))
auto val = stream.initSource(path);
if (val)
return QList<DesNode*>();
LexFoundation token_s(this->token_seqs, this->unknown_token);

View File

@ -23,12 +23,12 @@ QString NodeStoryBoard::index() const
bool NodeStoryBoard::check(QList<ErrorMessage> &reasons) const
{
auto nodes = doc()->core()->queryStoryBoard(name());
auto nodes = doc()->core()->queryStoryBoard(name()[0]);
if(nodes.size() > 1){
ErrorMessage ins;
ins.Reason = "重复定义大纲";
ins.Text = name();
ins.Text = name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -40,7 +40,7 @@ bool NodeStoryBoard::check(QList<ErrorMessage> &reasons) const
QString NodeStoryBoard::toString() const
{
QString des = "#故事 "+name() + " " + index() +" {";
QString des = "#故事 "+name()[0] + " " + index() +" {";
for(auto n : children())
des += "\n" + n->toString();
des += "\n}";
@ -49,7 +49,7 @@ QString NodeStoryBoard::toString() const
}
NodeStoryFragmentRefer::NodeStoryFragmentRefer(NodeStoryBoard * const parent_node, const QString &name)
: Result::NamedNode(name, parent_node->doc(), NODE_STORYFRAGMENT, parent_node) { }
: Result::NamedNode(name, parent_node->doc(), NODE_FRAGMENTREFERENCE, parent_node) { fragment_name = name; }
void NodeStoryFragmentRefer::setUnit(const QString &name){
this->unit_name_store = name;
@ -73,11 +73,11 @@ bool NodeStoryFragmentRefer::check(QList<ErrorMessage> &reasons) const
return false;
}
auto fragment = doc()->core()->queryStoryFragment(unitx[0], name());
auto fragment = doc()->core()->queryStoryFragment(unitx[0], name()[0]);
if(!fragment.size()){
ErrorMessage ins;
ins.Reason = "指定的情节不存在";
ins.Text = unit() + "" + name();
ins.Text = unit() + "" + name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -89,13 +89,18 @@ bool NodeStoryFragmentRefer::check(QList<ErrorMessage> &reasons) const
QString NodeStoryFragmentRefer::toString() const
{
QString des = QString(depth(), ' ') + "@情节 " + name() + " " + unit() + " {";
QString des = QString(depth(), ' ') + "@情节 " + name()[0] + " " + unit() + " {";
for(auto &c : children())
des += "\n" + QString(depth(), ' ') + c->toString();
return des + "\n"+QString(depth(), ' ') + "}";
}
QList<QString> NodeStoryFragmentRefer::name() const
{
return QList<QString>() << fragment_name << unit_name_store;
}
NodeStoryBoardParser::NodeStoryBoardParser(Result::ParseCore *core)
:Syntax::XSyntaxBase("情节引用"), project_ins(core)
{

View File

@ -63,7 +63,10 @@ namespace Parse {
virtual bool check(QList<ErrorMessage> &reasons) const override;
virtual QString toString() const override;
virtual QList<QString> name() const override;
private:
QString fragment_name;
QString unit_name_store;
};

View File

@ -153,11 +153,11 @@ QString NodeStoryChain::srcPath() const
bool NodeStoryChain::check(QList<ErrorMessage> &reasons) const
{
auto nodes = doc()->core()->queryStoryChain(name());
auto nodes = doc()->core()->queryStoryChain(name()[0]);
if(nodes.size() > 1){
ErrorMessage ins;
ins.Reason = "重复定义脉络";
ins.Text = name();
ins.Text = name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -169,7 +169,7 @@ bool NodeStoryChain::check(QList<ErrorMessage> &reasons) const
QString NodeStoryChain::toString() const
{
auto desc_string = QString(depth(), ' ') + "#脉络 " + name() + " {";
auto desc_string = QString(depth(), ' ') + "#脉络 " + name()[0] + " {";
for (auto it : children())
desc_string += "\n"+ QString(depth(), ' ') + it->toString();
desc_string +="\n"+ QString(depth(), ' ') + "}";
@ -178,7 +178,7 @@ QString NodeStoryChain::toString() const
}
NodeStoryPoint::NodeStoryPoint(NodeStoryChain * chain, const QString & name)
: Result::NamedNode(name, chain->doc(), NODE_STORYPOINT, chain){}
: Result::NamedNode(name, chain->doc(), NODE_STORYPOINT, chain){ store_name = name; }
NodeStoryChain * NodeStoryPoint::storyChain() const
{
@ -188,11 +188,11 @@ NodeStoryChain * NodeStoryPoint::storyChain() const
bool NodeStoryPoint::check(QList<ErrorMessage> &reasons) const
{
auto chain = parent();
auto nodes = chain->doc()->core()->queryStoryPoint(chain, name());
auto nodes = chain->doc()->core()->queryStoryPoint(chain, name()[0]);
if(nodes.size() > 1){ ErrorMessage ins;
ins.Reason = "重复定义脉络节点";
ins.Text = static_cast<NamedNode*>(chain)->name() +""+ name();
ins.Text = static_cast<NamedNode*>(chain)->name()[0] +""+ name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -205,12 +205,17 @@ bool NodeStoryPoint::check(QList<ErrorMessage> &reasons) const
QString NodeStoryPoint::toString() const
{
QString desc_string = "";
desc_string += QString(depth(), ' ') + "#节点 " + name() + " {";
desc_string += QString(depth(), ' ') + "#节点 " + name()[0] + " {";
for (auto it : children())
desc_string += "\n" + QString(depth(), ' ') + it->toString();
desc_string += "\n"+QString(depth(), ' ') + "}";
return desc_string;
return desc_string;
}
QList<QString> NodeStoryPoint::name() const
{
return QList<QString>() << store_name << static_cast<NamedNode*>(parent())->name()[0];
}
NodeStoryDesGroup::NodeStoryDesGroup(DesNode * parent_refer)
@ -285,7 +290,7 @@ StoryChainDocumentParser::StoryChainDocumentParser(ParseCore * pjt)
{"{左界限}","\\{"},
{"{右界限}","\\}"},
{"{换行符}","\\n"},
{"{引用符}", "@"},
// {"{引用符}", "@"},
}, "{无法识别}");
auto chain_parser = new NodeStoryChainParser(pjt);

View File

@ -75,6 +75,11 @@ namespace Parse
// 通过 NamedNode 继承
virtual bool check(QList<ErrorMessage>& reasons) const override;
virtual QString toString() const override;
virtual QList<QString> name() const;
private:
QString store_name;
};
/**

View File

@ -77,11 +77,11 @@ NodeStoryDepiction::NodeStoryDepiction(Result::DocCore *doc, const QString &name
bool NodeStoryDepiction::check(QList<ErrorMessage> &reasons) const
{
auto nodes = doc()->core()->queryStoryDepiction(name());
auto nodes = doc()->core()->queryStoryDepiction(name()[0]);
if(nodes.size() > 1){ ErrorMessage ins;
ins.Reason = "重复定义叙述";
ins.Text = name();
ins.Text = name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -92,7 +92,7 @@ bool NodeStoryDepiction::check(QList<ErrorMessage> &reasons) const
QString NodeStoryDepiction::toString() const
{
QString des = "#叙述 " + name() + " {";
QString des = "#叙述 " + name()[0] + " {";
for(auto &c : children()){
des += "\n" + c->toString();
}

View File

@ -2,6 +2,7 @@
#include "StoryChainDocumentParser.h"
#include "StoryOutlineDocumentParser.h"
#include "StoryTool.h"
#include "storyconceptdocumentparser.h"
#include <StoryUnitDocumentParser.h>
@ -47,6 +48,12 @@ QList<QString> StoryTool::compile(const QFileInfo &file, const QString &doc_name
StoryOutlineDocumentParser parser(parse_core);
results.append(parser.analysis(doc_core, file.absoluteFilePath()));
}
else if(file.suffix() == "storyconcept"){
if(!doc_core)
doc_core = new DocCore(parse_core, DocType::STORYCONCEPTS, file.absoluteFilePath(), doc_name);
StoryConceptDocumentParser parser(parse_core);
results.append(parser.analysis(doc_core, file.absoluteFilePath()));
}
if(doc_core){
parse_core->registerDoc(doc_core);
@ -91,6 +98,12 @@ QList<QString> StoryTool::compileSource(const QFileInfo &_file, const QString &s
StoryOutlineDocumentParser parser(parse_core);
results.append(parser.analysisSource(doc_core, src));
}
else if(_file.suffix() == "storyconcept"){
if(!doc_core)
doc_core = new DocCore(parse_core, DocType::STORYCONCEPTS, _file.absoluteFilePath(), doc_name);
StoryConceptDocumentParser parser(parse_core);
results.append(parser.analysisSource(doc_core, src));
}
if(doc_core){
parse_core->registerDoc(doc_core);

View File

@ -11,12 +11,12 @@ NodeStoryUnit::NodeStoryUnit(DocCore * doc, const QString & name)
bool NodeStoryUnit::check(QList<ErrorMessage> &reasons) const
{
auto unit_nodes = doc()->core()->queryStoryUnit(name());
auto unit_nodes = doc()->core()->queryStoryUnit(name()[0]);
if(unit_nodes.size() > 1){
ErrorMessage ins;
ins.Reason = "重复定义单元";
ins.Text = name();
ins.Text = name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -27,7 +27,7 @@ bool NodeStoryUnit::check(QList<ErrorMessage> &reasons) const
QString NodeStoryUnit::toString() const
{
QString rets = "#单元 " + name() + "{";
QString rets = "#单元 " + name()[0] + "{";
for (auto &it : children())
rets += "\n" + it->toString();
rets += "\n}";
@ -36,15 +36,15 @@ QString NodeStoryUnit::toString() const
NodeStoryFragment::NodeStoryFragment(NodeStoryUnit * unit, const QString & name)
: Result::NamedNode(name, unit->doc(), NODE_STORYFRAGMENT, unit){}
: Result::NamedNode(name, unit->doc(), NODE_STORYFRAGMENT, unit){ store_name = name; }
bool NodeStoryFragment::check(QList<ErrorMessage> &reasons) const
{
auto nodes = doc()->core()->queryStoryFragment(parent(), name());
auto nodes = doc()->core()->queryStoryFragment(parent(), name()[0]);
if(nodes.size() > 1){
ErrorMessage ins;
ins.Reason = "重复定义情节";
ins.Text = name();
ins.Text = name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
@ -56,12 +56,19 @@ bool NodeStoryFragment::check(QList<ErrorMessage> &reasons) const
QString NodeStoryFragment::toString() const
{
QString rets = QString(depth(), ' ') + "#情节 " + name() + "{";
QString rets = QString(depth(), ' ') + "#情节 " + name()[0] + "{";
for (auto cin : children())
rets += "\n" + QString(depth(), ' ') + cin->toString();
return rets + "\n"+QString(depth(), ' ') + "}";
}
QList<QString> NodeStoryFragment::name() const
{
return QList<QString>()
<< store_name
<< static_cast<NamedNode*>(parent())->name()[0];
}
NodeStoryPointRefer::NodeStoryPointRefer(DesNode * parent, const QString & chain, const QString & point)
: Result::DesNode(parent->doc(), NODE_POINTREFERENCE, parent),

View File

@ -43,6 +43,11 @@ namespace Parse {
// 通过 NamedNode 继承
virtual bool check(QList<ErrorMessage>& reasons) const override;
virtual QString toString() const override;
virtual QList<QString> name() const override;
private:
QString store_name;
};
/**

View File

@ -32,9 +32,9 @@ namespace Parse {
NamedNode::NamedNode(const QString &name, DocCore *core, int type, DesNode *pnode)
: Result::DesNode(core, type, pnode), name_store(name){}
QString NamedNode::name() const
QList<QString> NamedNode::name() const
{
return name_store;
return QList<QString>() << name_store;
}
DesNode::DesNode(DocCore *core, int type_value, DesNode *pnode)
@ -178,7 +178,7 @@ QList<Result::DesNode*> ParseCore::queryStoryChain(const QString &name) const
QList<Result::DesNode*> retlist;
for(auto &xnode : allStoryChains())
if(static_cast<NamedNode*>(xnode)->name() == name)
if(static_cast<NamedNode*>(xnode)->name()[0] == name)
retlist << xnode;
return retlist;
@ -189,7 +189,7 @@ QList<Result::DesNode*> ParseCore::queryStoryPoint(DesNode *chain, const QString
QList<Result::DesNode*> retlist;
for(auto &n : chain->children())
if(n->typeValue() == NODE_STORYPOINT &&
static_cast<NamedNode*>(n)->name() == name)
static_cast<NamedNode*>(n)->name()[0] == name)
retlist << n;
return retlist;
@ -214,7 +214,7 @@ QList<Result::DesNode*> ParseCore::queryStoryUnit(const QString &name) const
QList<Result::DesNode*> retlist;
for(auto &k : allStoryUnits())
if(static_cast<NamedNode*>(k)->name() == name)
if(static_cast<NamedNode*>(k)->name()[0] == name)
retlist << k;
return retlist;
@ -225,12 +225,12 @@ QList<Result::DesNode*> ParseCore::queryStoryFragment(DesNode *unit, const QStri
QList<Result::DesNode*> retlist;
for(auto &n : unit->children())
if(n->typeValue() == NODE_STORYFRAGMENT &&
static_cast<NamedNode*>(n)->name() == name)
static_cast<NamedNode*>(n)->name()[0] == name)
retlist << n;
return retlist;
}
QList<Result::DesNode*> ParseCore::queryStoryBoard(const QString &name) const
QList<DesNode *> ParseCore::allStoryBoards() const
{
QList<Result::DesNode*> retlist;
@ -238,14 +238,71 @@ QList<Result::DesNode*> ParseCore::queryStoryBoard(const QString &name) const
for(auto &k : keys)
if(k->docType() == DocType::STORYBOARD)
for(auto &n : *nodes_map[k]){
if(n->typeValue() == NODE_STORYBOARD &&
static_cast<NamedNode*>(n)->name() == name)
if(n->typeValue() == NODE_STORYBOARD)
retlist << n;
}
return retlist;
}
QList<Result::DesNode*> ParseCore::queryStoryBoard(const QString &name) const
{
QList<Result::DesNode*> retlist;
for(auto &it : allStoryBoards())
if(static_cast<NamedNode*>(it)->name()[0] == name)
retlist << it;
return retlist;
}
QList<DesNode *> ParseCore::queryStoryFragmentRefer(DesNode *unit, const QString &name) const
{
QList<Result::DesNode*> retlist;
for(auto &it : unit->children()){
if(it->typeValue() == NODE_FRAGMENTREFERENCE && static_cast<NamedNode*>(it)->name()[0] == name)
retlist << it;
}
return retlist;
}
QList<DesNode *> ParseCore::allStoryConcept() const
{
QList<DesNode*> rets;
for(auto &it : nodes_map.keys()){
if(it->docType() == DocType::STORYCONCEPTS)
for(auto n : *nodes_map[it])
if(n->typeValue() == NODE_STORYCONCEPT)
rets << n;
}
return rets;
}
QList<DesNode *> ParseCore::queryStoryConcept(const QString &name) const
{
QList<DesNode*> rets;
for(auto &it : allStoryConcept()){
if(static_cast<NamedNode*>(it)->name()[0] == name)
rets << it;
}
return rets;
}
QList<DesNode *> ParseCore::queryStoryStrongPoint(DesNode *concept, const QString &name) const
{
QList<DesNode*> rets;
for(auto &it : concept->children()){
if(it->typeValue() == NODE_STORYSTRONGPOINT &&
static_cast<NamedNode*>(it)->name()[0] == name)
rets << it;
}
return rets;
}
QList<DesNode *> ParseCore::queryStoryDepiction(const QString &name) const
{
QList<Result::DesNode*> retlist;
@ -253,7 +310,7 @@ QList<DesNode *> ParseCore::queryStoryDepiction(const QString &name) const
if(it->docType() == DocType::STORYOUTLINES)
for(auto &n : *nodes_map[it])
if(n->typeValue() == NODE_STORYDEPICTION &&
static_cast<NamedNode*>(n)->name() == name)
static_cast<NamedNode*>(n)->name()[0] == name)
retlist << n;
}

View File

@ -30,7 +30,8 @@ namespace Parse
STORYBOARD = DOC_STORYBOARD,
STORYUNIT = DOC_STORYUNIT,
STORYCHAIN = DOC_STORYCHAIN,
STORYOUTLINES = DOC_VOLUMEOUTLINE
STORYOUTLINES = DOC_VOLUMEOUTLINE,
STORYCONCEPTS = DOC_STORYCONCEPT
};
/**
@ -194,7 +195,7 @@ namespace Parse
*
* \return
*/
QString name() const;
virtual QList<QString> name() const;
private:
QString name_store;
@ -314,7 +315,13 @@ namespace Parse
virtual QList<Result::DesNode*> queryStoryUnit(const QString &name) const;
virtual QList<Result::DesNode*> queryStoryFragment(Result::DesNode *unit, const QString &name) const;
virtual QList<Result::DesNode*> allStoryBoards() const;
virtual QList<Result::DesNode*> queryStoryBoard(const QString &name) const;
virtual QList<Result::DesNode*> queryStoryFragmentRefer(Result::DesNode *unit, const QString &name) const;
virtual QList<Result::DesNode*> allStoryConcept() const;
virtual QList<Result::DesNode*> queryStoryConcept(const QString &name) const;
virtual QList<Result::DesNode*> queryStoryStrongPoint(Result::DesNode *concept, const QString &name) const;
/**
* @brief

View File

@ -19,7 +19,8 @@ SOURCES += \
StoryUnitDocumentParser.cpp \
WordsPeak.cpp \
XSyntaxBase.cpp \
libParse.cpp
libParse.cpp \
storyconceptdocumentparser.cpp
HEADERS += \
ComnDef.h \
@ -34,7 +35,8 @@ HEADERS += \
WordsPeak.h \
XSyntaxBase.h \
libParse.h \
libParse_global.h
libParse_global.h \
storyconceptdocumentparser.h
TRANSLATIONS += \
libParse_zh_CN.ts

View File

@ -0,0 +1,193 @@
#include "StoryChainDocumentParser.h"
#include "storyconceptdocumentparser.h"
using namespace Parse;
using namespace Parse::Result;
using namespace Syntax;
using namespace Syntax::Defines;
using namespace Lex;
StoryConceptDocumentParser::StoryConceptDocumentParser(ParseCore *core)
{
appendTokensDefine({
{"{概念定义}","#概念"},
{"{要点定义}", "#要点"},
{"{描述文本}", "[^#@\\{\\}\\n]+"},
{"{左界限}","\\{"},
{"{右界限}","\\}"},
{"{换行符}","\\n"}
}, "{无法识别}");
auto chain_parser = new NodeStoryConceptParser(core);
appendParser(chain_parser);
}
Parse::NodeStoryConcept::NodeStoryConcept(const QString &name, DocCore *doc)
: Result::NamedNode(name, doc, NODE_STORYCONCEPT, nullptr)
{
}
bool NodeStoryConcept::check(QList<ErrorMessage> &reasons) const
{
return true;
}
QString NodeStoryConcept::toString() const
{
QString string = "";
string += "#概念 "+name()[0] + " {";
for(auto &c : children())
string += "\n" + QString(depth(), ' ') + c->toString();
string +="\n" + QString(depth(),' ') + "}";
return string;
}
NodeStoryStrongPoint::NodeStoryStrongPoint(NodeStoryConcept *parent, const QString &name)
: Result::NamedNode(name, parent->doc(), NODE_STORYSTRONGPOINT, parent),
concept_point(parent)
{
}
bool NodeStoryStrongPoint::check(QList<ErrorMessage> &reasons) const
{
return true;
}
QString NodeStoryStrongPoint::toString() const
{
QString string = "#要点 " + name()[0] + " {";
for(auto &c : children())
string += "\n" + QString(depth(), ' ') + c->toString();
string += "\n" + QString(depth(),' ') + "}";
return string;
}
QList<QString> NodeStoryStrongPoint::name() const
{
QList<QString> rets;
rets << NamedNode::name()[0] << concept_point->name()[0];
return rets;
}
NodeStoryConceptParser::NodeStoryConceptParser(Result::ParseCore *core)
: Syntax::XSyntaxBase("概念解析"), core(core)
{
set_common_expression("::换行前缀", {Elm("{换行符}"), Elm("{换行符}", true)});
auto rule = addRule("进入概念解析", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmunit = seqs[cnt-1];
auto defunit = seqs[cnt-2];
auto node = new NodeStoryConcept(nmunit.Text, docRef());
refocusNode(node);
auto word1 = new Words(node, docRef(), defunit.Text, defunit.StartRow, defunit.StartCol);
auto word0 = new Words(node, docRef(), nmunit.Text, nmunit.StartRow, nmunit.StartCol);
docRef()->append(word1);
docRef()->append(word0);
return ParseResult::SelfManipulate;
});
rule->addExpression("基础概念定义", {Elm("{概念定义}"), Elm("{描述文本}", true)});
rule->addExpression("拓展概念定义", {Exp("::换行前缀"), Exp("基础概念定义", true)});
rule = addRule("进入成分解析", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
auto node = currNode();
auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
docRef()->append(word);
return ParseResult::EnterNext;
});
rule->addExpression("基础成分解析", { Elm("{左界限}", true) });
rule->addExpression("拓展成分解析", { Exp("::换行前缀"), Exp("基础成分解析", true) });
rule = addRule("跳出成分解析", 2, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
auto node = currNode();
auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
docRef()->append(word);
return ParseResult::Completed;
});
rule->addExpression("基础跳出解析", { Elm("{右界限}", true) });
rule->addExpression("拓展跳出解析", { Exp("::换行前缀"), Exp("基础跳出解析", true) });
addChild(QList<SyntaxParser*>() << new NodeStoryPureTextDesGroupParser(this)
<< new NodeStoryStrongPointParser(this));
}
NodeStoryStrongPointParser::NodeStoryStrongPointParser(NodeStoryConceptParser *pparser)
: Syntax::XSyntaxBase("要点解析")
{
set_common_expression("::换行前缀", {Elm("{换行符}"), Elm("{换行符}", true)});
auto rule = addRule("进入要点解析", 0, [this, pparser](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmunit = seqs[cnt-1];
auto defunit = seqs[cnt-2];
auto node = new NodeStoryStrongPoint(static_cast<NodeStoryConcept*>(pparser->currNode()), nmunit.Text);
refocusNode(node);
pparser->currNode()->appendChild(node);
auto word1 = new Words(node, docRef(), defunit.Text, defunit.StartRow, defunit.StartCol);
auto word0 = new Words(node, docRef(), nmunit.Text, nmunit.StartRow, nmunit.StartCol);
docRef()->append(word1);
docRef()->append(word0);
return ParseResult::SelfManipulate;
});
rule->addExpression("基础要点定义", {Elm("{要点定义}"), Elm("{描述文本}", true)});
rule->addExpression("拓展要点定义", {Exp("::换行前缀"), Exp("基础要点定义", true)});
rule = addRule("进入成分解析", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
auto node = currNode();
auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
docRef()->append(word);
return ParseResult::EnterNext;
});
rule->addExpression("基础成分解析", { Elm("{左界限}", true) });
rule->addExpression("拓展成分解析", { Exp("::换行前缀"), Exp("基础成分解析", true) });
rule = addRule("跳出成分解析", 2, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
auto node = currNode();
auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
docRef()->append(word);
return ParseResult::Completed;
});
rule->addExpression("基础跳出解析", { Elm("{右界限}", true) });
rule->addExpression("拓展跳出解析", { Exp("::换行前缀"), Exp("基础跳出解析", true) });
addChild(QList<SyntaxParser*>() << new NodeStoryPureTextDesGroupParser(this));
}

View File

@ -0,0 +1,81 @@
#ifndef STORYCONCEPTDOCUMENTPARSER_H
#define STORYCONCEPTDOCUMENTPARSER_H
#include "ParseFrame.h"
#include "SyntaxBase.h"
#include "XSyntaxBase.h"
namespace Parse {
class NodeStoryConcept : public Result::NamedNode
{
public:
NodeStoryConcept(const QString &name, Result::DocCore *doc);
// DesNode interface
public:
virtual bool check(QList<ErrorMessage> &reasons) const override;
virtual QString toString() const override;
};
class NodeStoryConceptParser : public Syntax::XSyntaxBase
{
public:
NodeStoryConceptParser(Result::ParseCore *core);
private:
Result::ParseCore *const core;
};
class NodeStoryStrongPoint : public Result::NamedNode
{
public:
NodeStoryStrongPoint(NodeStoryConcept *parent, const QString &name);
// DesNode interface
public:
virtual bool check(QList<ErrorMessage> &reasons) const override;
virtual QString toString() const override;
// NamedNode interface
public:
virtual QList<QString> name() const override;
private:
NodeStoryConcept *const concept_point;
};
class NodeStoryStrongPointParser : public Syntax::XSyntaxBase
{
public:
NodeStoryStrongPointParser(NodeStoryConceptParser *pparser);
};
class StoryConceptDocumentParser : public Syntax::ParseFrame
{
public:
StoryConceptDocumentParser(Result::ParseCore *core);
};
}
#endif // STORYCONCEPTDOCUMENTPARSER_H