using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using NTERA.Core;
using NTERA.EmuEra.Game.EraEmu.GameProc;
using NTERA.EmuEra.Game.EraEmu.Sub;
namespace NTERA.EmuEra.Game.EraEmu.GameData
{
//1756 新設。ParserやLexicalAnalyzerなどが知りたい情報をまとめる
//本当は引数として渡すべきなのかもしれないが全てのParserの引数を書きなおすのが面倒なのでstatic
internal static class ParserMediator
{
///
/// emuera.config等で発生した警告
/// Initializeより前に発生する
///
///
///
public static void ConfigWarn(string str, ScriptPosition pos, int level, string stack)
{
if (level < Config.Config.DisplayWarningLevel && !Program.AnalysisMode)
return;
warningList.Add(new ParserWarning(str, pos, level, stack));
}
static IConsole console;
public static void Initialize(IConsole console)
{
ParserMediator.console = console;
}
#region Rename
public static Dictionary RenameDic { get; private set; }
//1756 Process.Load.csより移動
public static void LoadEraExRenameFile(string filepath)
{
if (RenameDic != null)
RenameDic.Clear();
//とにかく辞書を作る。辞書がnullのときは UseRenameFileがNOの時のみ
RenameDic = new Dictionary();
EraStreamReader eReader = new EraStreamReader(false);
if ((!File.Exists(filepath)) || (!eReader.Open(filepath)))
{
return;
}
string line = null;
ScriptPosition pos = null;
Regex reg = new Regex(@"\\,", RegexOptions.Compiled);
try
{
while ((line = eReader.ReadLine()) != null)
{
if (line.Length == 0)
continue;
if (line.StartsWith(";"))
continue;
string[] baseTokens = reg.Split(line);
if (!baseTokens[baseTokens.Length - 1].Contains(","))
continue;
string[] last = baseTokens[baseTokens.Length - 1].Split(',');
baseTokens[baseTokens.Length - 1] = last[0];
string[] tokens = new string[2];
tokens[0] = string.Join(",", baseTokens);
tokens[1] = last[1];
pos = new ScriptPosition(eReader.Filename, eReader.LineNo, line);
//右がERB中の表記、左が変換先になる。
string value = tokens[0].Trim();
string key = string.Format("[[{0}]]", tokens[1].Trim());
RenameDic[key] = value;
pos = null;
}
}
catch (Exception e)
{
if (pos != null)
throw new CodeEE(e.Message, pos);
else
throw new CodeEE(e.Message);
}
finally
{
eReader.Close();
}
}
#endregion
public static void Warn(string str, ScriptPosition pos, int level)
{
Warn(str, pos, level, null);
}
public static void Warn(string str, ScriptPosition pos, int level, string stack)
{
if (level < Config.Config.DisplayWarningLevel && !Program.AnalysisMode)
return;
if (console != null && !console.RunERBFromMemory)
warningList.Add(new ParserWarning(str, pos, level, stack));
}
///
/// Parser中での警告出力
///
///
///
/// 警告レベル.0:軽微なミス.1:無視できる行.2:行が実行されなければ無害.3:致命的
public static void Warn(string str, LogicalLine line, int level, bool isError, bool isBackComp)
{
Warn(str, line, level, isError, isBackComp, null);
}
public static void Warn(string str, LogicalLine line, int level, bool isError, bool isBackComp, string stack)
{
if (isError)
{
line.IsError = true;
line.ErrMes = str;
}
if (level < Config.Config.DisplayWarningLevel && !Program.AnalysisMode)
return;
if (isBackComp && !Config.Config.WarnBackCompatibility)
return;
if (console != null && !console.RunERBFromMemory)
warningList.Add(new ParserWarning(str, line.Position, level, stack));
// console.PrintWarning(str, line.Position, level);
}
private static List warningList = new List();
public static bool HasWarning => warningList.Count > 0;
public static void ClearWarningList()
{
warningList.Clear();
}
public static void FlushWarningList()
{
for (int i = 0; i < warningList.Count; i++)
{
ParserWarning warning = warningList[i];
console.PrintWarning(warning.WarningMes + warning.WarningPos, warning.WarningLevel);
if (warning.StackTrace != null)
{
string[] stacks = warning.StackTrace.Split('\n');
for (int j = 0; j < stacks.Length; j++)
{
console.PrintSystemLine(stacks[j]);
}
}
}
warningList.Clear();
}
private class ParserWarning
{
public ParserWarning(string mes, ScriptPosition pos, int level, string stackTrace)
{
WarningMes = mes;
WarningPos = pos;
WarningLevel = level;
StackTrace = stackTrace;
}
public string WarningMes;
public ScriptPosition WarningPos;
public int WarningLevel;
public string StackTrace;
}
}
}