QtNovelUI/DesParser/ParseFrame.cpp

110 lines
2.6 KiB
C++

#include "ParseFrame.h"
#include "WordsPeak.h"
using namespace Parse;
using namespace Parse::Result;
using namespace Syntax;
using namespace Lex;
ParseFrame::ParseFrame() {}
QList<DesNode*> ParseFrame::analysis(DocCore*doc, const QString & path)
{
ExStream stream;
if (stream.initSource(path))
return QList<DesNode*>();
LexFoundation token_s(this->token_seqs, this->unknown_token);
QList<LexResult> lex_seqence;
std::tuple<int, int, QChar> temp;
while ((std::get<2>(temp = stream.read())) != EOF)
{
auto results = token_s.push(
std::get<0>(temp),
std::get<1>(temp),
std::get<2>(temp));
lex_seqence.append(results);
}
for (auto it : cascade_parsers)
it->docActive(doc);
QList<DesNode*> xrets;
do {
QList<DesNode*> nodes;
auto rst = inner_parse(lex_seqence, cascade_parsers, nodes);
if (rst == ParseResult::Failed)
lex_seqence.removeFirst();
xrets.append(nodes);
} while (lex_seqence.size());
return xrets;
}
void ParseFrame::appendTokensDefine(QList<LexDef> seqs, const QString & unknown_token)
{
this->unknown_token = unknown_token;
token_seqs.append(seqs);
}
void ParseFrame::appendParser(SyntaxParser * u)
{
cascade_parsers << u;
}
ParseResult ParseFrame::inner_parse(QList<LexResult> &lex_seqence, QList<SyntaxParser*> parsers, QList<DesNode*> &nodes_out)
{
QList<DesNode*> nodes;
// 遍历解析器,获取匹配
for (auto it : parsers) {
if (!it->applied(lex_seqence))
continue;
it->reset();
for (;;) {
// 在当前层级解析标记序列
ParseResult result = it->parse(lex_seqence);
auto node = it->currNode();
if (node && !nodes.contains(node))
nodes << node;
switch (result) {
case ParseResult::SelfManipulate:
// 进入下一个循环,继续使用本解析器解析
break;
case ParseResult::EnterNext: {
// 移交解析任务给成员解析器
ChildCheck:
QList<DesNode*> tlist;
auto child_parsers = it->children();
auto rst = inner_parse(lex_seqence, child_parsers, tlist);
// 一个成员解析器完成全部解析任务,继续核对下一个解析器
if (rst == ParseResult::Completed)
goto ChildCheck;
// 成员解析器无法处理,返回父解析器
}break;
case ParseResult::Completed:
// 本解析器处理解析完成
nodes_out.append(nodes);
return ParseResult::Completed;
case ParseResult::Failed:
auto token = lex_seqence.first();
auto word = new Words(it->docRef()->unknowns(), it->docRef(), token.Text, token.StartRow, token.StartCol);
it->docRef()->append(word);
lex_seqence.removeFirst();
break;
}
}
}
return ParseResult::Failed;
}