#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;
}
