diff --git a/CoreTest/main.cpp b/CoreTest/main.cpp index 996e154..febc364 100644 --- a/CoreTest/main.cpp +++ b/CoreTest/main.cpp @@ -22,17 +22,20 @@ int main(int argc, char* argv[]) { auto rst = parser.parse(vwords); if (rst.first()->totalErrorCount()) { + int err_count = 0; auto pos_mark = rst.first()->token()->position(); for (auto item : rst) if (item->token()->position() == pos_mark) - for (auto line : item->totalErrors()) + for (auto line : item->totalErrors()){ + err_count++; qDebug().noquote() << line; + } + qDebug() << err_count << "===========finished=========================="; } else { auto prag_root = std::make_shared("HelloWorld!"); auto structx = parser.getAst(rst.first(), prag_root); parser.astPresent(structx); } - qDebug() << "===========finished=========================="; return a.exec(); } diff --git a/WsNovelManager/Program.fs b/WsNovelManager/Program.fs new file mode 100644 index 0000000..bf7c198 --- /dev/null +++ b/WsNovelManager/Program.fs @@ -0,0 +1,6 @@ +// For more information see https://aka.ms/fsharp-console-apps +open System + +let args = System.Environment.GetCommandLineArgs() |> Array.toList +if args.Length <> 5 then + failwith $"程序启动参数错误: -in story_dir -out html_out" \ No newline at end of file diff --git a/WsNovelManager/WsNovelManager.fsproj b/WsNovelManager/WsNovelManager.fsproj new file mode 100644 index 0000000..37bb8cf --- /dev/null +++ b/WsNovelManager/WsNovelManager.fsproj @@ -0,0 +1,13 @@ + + + + Exe + net8.0 + nsm + + + + + + + diff --git a/WsNovelParser.sln b/WsNovelParser.sln index 5334a21..88ad027 100644 --- a/WsNovelParser.sln +++ b/WsNovelParser.sln @@ -38,7 +38,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CoreTest", "CoreTest\CoreTe {EF557F71-99AA-4F2B-A5F5-1A4518A11C19} = {EF557F71-99AA-4F2B-A5F5-1A4518A11C19} EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AstConv", "AstConv\AstConv.fsproj", "{0C77216C-6484-4C94-BE06-D5D9FF18EA81}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AstConv", "AstConv\AstConv.fsproj", "{0C77216C-6484-4C94-BE06-D5D9FF18EA81}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WsNovelManager", "WsNovelManager\WsNovelManager.fsproj", "{D9350B75-3992-47A8-A0F3-41D16874D245}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -134,6 +136,18 @@ Global {0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x64.Build.0 = Release|Any CPU {0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x86.ActiveCfg = Release|Any CPU {0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x86.Build.0 = Release|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Debug|x64.ActiveCfg = Debug|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Debug|x64.Build.0 = Debug|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Debug|x86.ActiveCfg = Debug|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Debug|x86.Build.0 = Debug|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Release|Any CPU.Build.0 = Release|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Release|x64.ActiveCfg = Release|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Release|x64.Build.0 = Release|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Release|x86.ActiveCfg = Release|Any CPU + {D9350B75-3992-47A8-A0F3-41D16874D245}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/libSyntax/libsyntax.cpp b/libSyntax/libsyntax.cpp index 884c1bf..3333631 100644 --- a/libSyntax/libsyntax.cpp +++ b/libSyntax/libsyntax.cpp @@ -27,7 +27,7 @@ QList> __anyone_impl::children() const { } QList> __anyone_impl::parse(std::shared_ptr cursor) const { - if (cursor->parseFailure() && cursor->parseComplete()) + if (cursor->parseFailure() || cursor->parseComplete()) return QList>() << cursor; auto syntax = present(); @@ -79,7 +79,7 @@ QList> __sequence_impl::children() const { } QList> __sequence_impl::parse(std::shared_ptr cursor) const { - if (cursor->parseFailure() && cursor->parseComplete()) + if (cursor->parseFailure() || cursor->parseComplete()) return QList>() << cursor; QList> bridge_list{ cursor }; @@ -148,7 +148,7 @@ QList> __repeat_impl::children() const { #include QList> __repeat_impl::parse(std::shared_ptr cursor) const { - if (cursor->parseFailure() && cursor->parseComplete()) + if (cursor->parseFailure() || cursor->parseComplete()) return QList>() << cursor; auto syntax = present(); @@ -338,9 +338,15 @@ void MatchCursor::enterExprs() { this->_exprs_errors.push_back(new_expr); } -void MatchCursor::logExprsError(const QString& msg) { - this->_total_errors.push_back(msg); - this->_exprs_errors.last()->addError(msg); +void lib_syntax::MatchCursor::logExprsError(std::shared_ptr t, const QString& msg) { + if(!this->_total_errors.contains(t->position())) + this->_total_errors[t->position()] = QStringList(); + + auto exists = this->_total_errors[t->position()]; + exists.append(msg); + this->_total_errors[t->position()] = exists; + + this->_exprs_errors.last()->addError(t, msg); // 普适性质的判定标准 this->setFailure(this->exprsErrorCount() > 1); @@ -377,7 +383,28 @@ int MatchCursor::totalErrorCount() const { } QList MatchCursor::totalErrors() const { - return this->_total_errors; + QStringList flist; + for(auto set : this->_total_errors) + flist.append(set); + + return flist; +} + +void lib_syntax::MatchCursor::mergeWith(const MatchCursor& other) { + for(auto key : other._total_errors.keys()){ + if (!this->_total_errors.contains(key)) + this->_total_errors[key] = QStringList(); + + auto values = other._total_errors[key]; + auto this_values = this->_total_errors[key]; + this_values.append(values); + this->_total_errors[key] = this_values; + } + for (auto key : this->_total_errors.keys()) { + auto values = this->_total_errors[key]; + values = values.toSet().toList(); + this->_total_errors[key] = values; + } } void MatchCursor::setCurrent(std::shared_ptr t, std::shared_ptr remains) { @@ -400,11 +427,11 @@ lib_syntax::MatchCursor::ErrsPack::ErrsPack(const ErrsPack& other) : _error_collection(other._error_collection) { } -void MatchCursor::ErrsPack::addError(const QString& msg) { - this->_error_collection.append(msg); +void lib_syntax::MatchCursor::ErrsPack::addError(std::shared_ptr t, const QString& msg) { + this->_error_collection << std::make_pair(t, msg); } -QList MatchCursor::ErrsPack::errors() const { +QList, QString>> MatchCursor::ErrsPack::errors() const { return _error_collection; } diff --git a/libSyntax/libsyntax.h b/libSyntax/libsyntax.h index 2d370bd..a953a82 100644 --- a/libSyntax/libsyntax.h +++ b/libSyntax/libsyntax.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include "ast_basic.h" @@ -40,12 +41,12 @@ namespace lib_syntax { ErrsPack(); ErrsPack(const ErrsPack& other); - void addError(const QString& msg); - QList errors() const; + void addError(std::shared_ptr, const QString& msg); + QList, QString>> errors() const; uint64_t errorCount() const; private: - QList _error_collection; + QList, QString>> _error_collection; }; MatchCursor(const QString& path); @@ -59,11 +60,12 @@ namespace lib_syntax { virtual QString parseSyntax() const; virtual void enterExprs(); - virtual void logExprsError(const QString& msg); + virtual void logExprsError(std::shared_ptr t, const QString& msg); virtual void quitExprs(); virtual int exprsErrorCount() const; virtual int totalErrorCount() const; virtual QList totalErrors() const; + virtual void mergeWith(const MatchCursor &other); virtual bool parseFailure() const; virtual void setFailure(bool mark = true); @@ -79,7 +81,7 @@ namespace lib_syntax { std::shared_ptr _prev_cursor = nullptr; bool _parse_stop_with_errors = false, _parse_complete = false; - QList _total_errors; // 所有解析错误 + QHash _total_errors; // 所有解析错误 QList> _exprs_errors; // 当前表达式解析错误 std::shared_ptr _current_token = nullptr; // 当前Token std::shared_ptr _remains_word = nullptr; // 剩余词语 @@ -209,7 +211,7 @@ namespace lib_syntax { // 只有在表达式的起始点遇到nullptr,才是正常结束。 if (current->token()->tokenType() != lib_token::IActionToken::Type::ElementBegin) { auto ncurs = std::make_shared(current); - ncurs->logExprsError(QString("SyntaxError[0x00001]输入错误,程序提前结束:%1。").arg(current->filePath())); + ncurs->logExprsError(nullptr, QString("SyntaxError[0x00001]输入错误,程序提前结束:%1。").arg(current->filePath())); ncurs->setFailure(); return QList>() << ncurs; } @@ -241,7 +243,7 @@ namespace lib_syntax { QList> retvals; // 少一个 auto short_one = std::make_shared(current); - short_one->logExprsError(QString("SyntaxError[0x00002]语法匹配错误,缺失\"%1\">") + short_one->logExprsError(w_this, QString("SyntaxError[0x00002]语法匹配错误,缺失\"%1\">") .arg(this->_define_peers->reviseWords()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file())); auto tkins0 = std::make_shared(w_this->row(), w_this->column(), w_this->position(), QString("<+%1>").arg(this->_define_peers->reviseWords()), w_this->file(), this->_define_peers); @@ -251,7 +253,7 @@ namespace lib_syntax { // 错一个 auto error_one = std::make_shared(current); - error_one->logExprsError(QString("SyntaxError[0x00003]语法匹配错误,请修正\"%1\">") + error_one->logExprsError(w_this, QString("SyntaxError[0x00003]语法匹配错误,请修正\"%1\">") .arg(w_this->content()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file())); auto tkins = std::make_shared(w_this->row(), w_this->column(), w_this->position(), QString("<%1(%2)>").arg(w_this->content()).arg(this->_define_peers->reviseWords()), w_this->file(), this->_define_peers); @@ -271,7 +273,7 @@ namespace lib_syntax { } auto clone_ins = std::make_shared(current); - clone_ins->logExprsError(QString("SyntaxError[0x00004]语法匹配错误,请删除\"%1\">") + clone_ins->logExprsError(w_this, QString("SyntaxError[0x00004]语法匹配错误,请删除\"%1\">") .arg(w_this->content()).arg(w_this->row()).arg(w_this->column()).arg(w_this->file())); clone_ins->setCurrent(chain, remains); retvals << clone_ins; @@ -307,7 +309,7 @@ namespace lib_syntax { virtual QList> parse(std::shared_ptr cursor) const override { // 提前结束,直接返回 - if (cursor->parseFailure() && cursor->parseComplete()) + if (cursor->parseFailure() || cursor->parseComplete()) return QList>() << cursor; auto syntax = present(); @@ -337,6 +339,14 @@ namespace lib_syntax { std::copy_if(nbranch.begin(), nbranch.end(), std::back_inserter(branch_procs), [](std::shared_ptr ins) { return !ins->parseFailure(); }); + + if(branch_procs.size()){ + auto first_cursor = branch_procs.first(); + for (auto curr = ++branch_procs.begin(); curr != branch_procs.end(); curr++) { + std::const_pointer_cast(first_cursor)->mergeWith(**curr); + } + branch_procs = { first_cursor }; + } } // 表达式匹配结尾 @@ -363,7 +373,7 @@ namespace lib_syntax { } // 匹配失败 - return branch_procs; + return nbranch; } protected: diff --git a/libWords/libwords.cpp b/libWords/libwords.cpp index d7db0e9..9f9e13c 100644 --- a/libWords/libwords.cpp +++ b/libWords/libwords.cpp @@ -110,3 +110,9 @@ int WordContent::column() const { std::shared_ptr WordContent::nextWord() const { return nullptr; } + +LIBWORDS_EXPORT uint lib_words::qHash(const std::shared_ptr& t, uint seed) noexcept { + if(t) + return qHash(QString("W:%1").arg(t->position()), seed); + return qHash(QString(), seed); +} diff --git a/libWords/libwords.h b/libWords/libwords.h index 55a2925..cc59ace 100644 --- a/libWords/libwords.h +++ b/libWords/libwords.h @@ -117,4 +117,8 @@ namespace lib_words { WordsException(const QString& message); virtual QString message() const; }; + + + LIBWORDS_EXPORT uint qHash(const std::shared_ptr& t, uint seed = 0) Q_DECL_NOTHROW; + } \ No newline at end of file