using GDNXFD.Data; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace GDNXFD.Alert.Interpreter { public class CodeGenerator { private string className; private string expression; private List varList; private Stack sustainStack; private List sustainList; private Stack barcketStack; private int sustainSeq = 1; public CodeGenerator(string clsName, string exps) { if (string.IsNullOrWhiteSpace(clsName)) { className = GenerateRandomString(10); } else { className = clsName.Trim(); } varList = new List(); if (string.IsNullOrWhiteSpace(exps)) { varList.Add("true"); return; } try { expression = exps.Trim().TrimEnd(';'); expression = ReplaceStatusContinued(expression); expression = ReplaceSuddenChange(expression); expression = ReplaceLastUpdateTime(expression); expression = ReplaceDiffMinutes(expression); expression = ReplaceDiffSeconds(expression); PhrasingExpression(expression); if (varList != null && varList.Count > 0) { foreach (string strVar in varList) { if (DataCache.Instance.RelateUniformCodes == null) DataCache.Instance.RelateUniformCodes = new List(); if (!DataCache.Instance.RelateUniformCodes.Contains(strVar)) DataCache.Instance.RelateUniformCodes.Add(strVar); } } if (sustainList != null && sustainList.Count > 0) { foreach (SustainModel sm in sustainList) { if (string.IsNullOrEmpty(sm.Expression) || sm.EndIndex == 0 || sm.Duration==0) throw new ExpressionException("Sustain方法不完整!"); if (sm.VarList != null) { foreach (string strVar in sm.VarList) { if (DataCache.Instance.RelateUniformCodes == null) DataCache.Instance.RelateUniformCodes = new List(); if (!DataCache.Instance.RelateUniformCodes.Contains(strVar)) DataCache.Instance.RelateUniformCodes.Add(strVar); } } } } } catch(ExpressionException) { throw; } catch (Exception ex) { throw new ExpressionException(ex); } } public void PhrasingExpression(string exps) { char[] arr = exps.ToCharArray(); for (int i = 0; i < arr.Length; i++) { #region Sustain函数开始匹配 if (arr[i] == 'S' && i + 7 < arr.Length && arr[i + 1] == 'u' && arr[i + 2] == 's' && arr[i + 3] == 't' && arr[i + 4] == 'a' && arr[i + 5] == 'i' && arr[i + 6] == 'n') { int offset = i; i += 7; while (IsWhite(arr[i]) && i < arr.Length - 1) i++; //去除空白 if (arr[i] == '(') { SustainModel sModel = new SustainModel(); sModel.Sequence = sustainSeq++; sModel.StartIndex = offset; if (sustainStack == null) sustainStack = new Stack(); if (sustainStack.Count > 0) { SustainModel sm = sustainStack.Peek(); if (sm.SustainList == null) sm.SustainList = new List(); sm.SustainList.Add(sModel); } sustainStack.Push(sModel); if (sustainStack.Count == 1) { if (sustainList == null) sustainList = new List(); sustainList.Add(sModel); } i++; } } #endregion #region AI、DI变量匹配 //AI, DI变量提取 if ((arr[i] == 'A' || arr[i] == 'D') && i + 1 < arr.Length && arr[i + 1] == 'I') { if (i == 0 || !IsLetterOrNumber(arr[i-1])) { int offset = i; i += 2; while ((IsLetterOrNumber(arr[i]) || arr[i] == '_') && i < arr.Length - 1) i++; //提取以AI或DI开头的单词 string expVar = new string(arr, offset, i == arr.Length - 1 ? i - offset + 1 : i - offset); if (sustainStack != null && sustainStack.Count > 0) { SustainModel sm = sustainStack.Peek(); if (sm.VarList == null) sm.VarList = new List(); if (!sm.VarList.Contains(expVar)) sm.VarList.Add(expVar); } else { if (varList == null) varList = new List(); if (!varList.Contains(expVar)) varList.Add(expVar); } } } #endregion #region Sustain函数结尾匹配 if (sustainStack != null && sustainStack.Count > 0) { SustainModel sm = sustainStack.Peek(); if (arr[i] == '(') { if (barcketStack == null) barcketStack = new Stack(); barcketStack.Push('('); } else if (arr[i] == ')') { if (barcketStack != null && barcketStack.Count > 0) { barcketStack.Pop(); } else { sm.EndIndex = i; sm.Expression = new string(arr, sm.StartIndex, sm.EndIndex-sm.StartIndex+1); if (sm.Duration == 0 && sm.DurationIndex !=0) { string strDuration = new string(arr, sm.DurationIndex, sm.EndIndex-sm.DurationIndex); int duration = 0; if (int.TryParse(strDuration.Trim(), out duration)) { sm.Duration = duration; } else { throw new ExpressionException("表达式格式错误!位置:" + i); } } if (sm.Interval == 0 && sm.IntervalIndex != 0) { string str = new string(arr, sm.IntervalIndex, sm.EndIndex-sm.IntervalIndex); int interval = 0; if (int.TryParse(str.Trim(), out interval)) { sm.Interval = interval; } else { throw new ExpressionException("表达式格式错误!位置:" + i); } } sustainStack.Pop(); } } else if (arr[i] == ',') { if (barcketStack == null || barcketStack.Count == 0) { if (sm.DurationIndex == 0) sm.DurationIndex = i+1; else { sm.IntervalIndex = i+1; string strDuration = new string(arr, sm.DurationIndex, i-sm.DurationIndex); int duration = 0; if (int.TryParse(strDuration.Trim(), out duration)) { sm.Duration = duration; } else { throw new ExpressionException("表达式格式错误!位置:" + i); } } } } } #endregion } } private bool IsLetterOrNumber(char c) { if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) return true; return false; } private bool IsWhite(char c) { if (c == ' ' || c == '\n' || c == '\r' || c == '\t') return true; return false; } public string ToClassString() { StringBuilder sbMembers = null; if (varList != null && varList.Count > 0) { sbMembers = new StringBuilder(); foreach (string member in varList) { if (member.StartsWith("AI")) sbMembers.AppendLine(string.Format(CodeTemplate.AIDeclare, member)); else if (member.StartsWith("DI")) sbMembers.AppendLine(string.Format(CodeTemplate.DIDeclare, member)); } } string exps = expression; StringBuilder sbSustainMethod = null; if (sustainList != null && sustainList.Count > 0) { sbSustainMethod = new StringBuilder(); foreach (SustainModel sm in sustainList) { exps = exps.Replace(sm.Expression, sm.GetCallString()); GenerateSustainMethod(sm, ref sbSustainMethod); } } string retStatement = string.Format(CodeTemplate.ReturnStatement, exps); return string.Format(CodeTemplate.Outline, className, sbMembers == null ? "" : sbMembers.ToString(), retStatement, sbSustainMethod == null ? "" : sbSustainMethod.ToString()); } public void GenerateSustainMethod(SustainModel sm, ref StringBuilder sbSustainMethod) { sbSustainMethod.Append(sm.ToMethodString()); if (sm.SustainList != null) { foreach (SustainModel ssm in sm.SustainList) GenerateSustainMethod(ssm, ref sbSustainMethod); } } private string GenerateRandomString(int codeCount) { string str = string.Empty; int seed = new Random().Next(); Random random = new Random(seed); for (int i = 0; i < codeCount; i++) { int num = random.Next(); str = str + ((char)(65 + ((ushort)(num % 26)))).ToString(); } return str; } private string ReplaceDiffMinutes(string exp) { if (!exp.Contains("DiffMinutes")) return exp; string regex = @"DiffMinutes\(\w+,\s*\d+\)"; MatchCollection coll = Regex.Matches(exp, regex); foreach (Match item in coll) { string rplStr = ConvertDiffMinutes(item.Value); exp = exp.Replace(item.Value, rplStr); } return exp; } private string ConvertDiffMinutes(string sc) { string template = "DiffMinutes(\"STR{0}\",{1},objectId,objectType)"; string tmp = sc.Trim(); tmp = tmp.TrimStart('D', 'i', 'f', 'f', 'M', 'i', 'n', 'u', 't', 'e', 's'); tmp = tmp.Trim(); tmp = tmp.TrimStart('('); tmp = tmp.TrimEnd(')'); string[] arr = tmp.Split(','); return string.Format(template, arr[0].Trim(), arr[1].Trim()); } private string ReplaceDiffSeconds(string exp) { if (!exp.Contains("DiffSeconds")) return exp; string regex = @"DiffSeconds\(\w+,\s*\d+\)"; MatchCollection coll = Regex.Matches(exp, regex); foreach (Match item in coll) { string rplStr = ConvertDiffSeconds(item.Value); exp = exp.Replace(item.Value, rplStr); } return exp; } private string ConvertDiffSeconds(string sc) { string template = "DiffSeconds(\"STR{0}\",{1},objectId,objectType)"; string tmp = sc.Trim(); tmp = tmp.TrimStart('D', 'i', 'f', 'f', 'S', 'e', 'c', 'o', 'n', 'd', 's'); tmp = tmp.Trim(); tmp = tmp.TrimStart('('); tmp = tmp.TrimEnd(')'); string[] arr = tmp.Split(','); return string.Format(template, arr[0].Trim(), arr[1].Trim()); } private string ReplaceStatusContinued(string exp) { if (!exp.Contains("StatusContinued")) return exp; string regex = @"StatusContinued\(\w+,\s*\d+\)"; MatchCollection coll = Regex.Matches(exp, regex); foreach (Match item in coll) { string rplStr = ConvertStatusContinued(item.Value); exp = exp.Replace(item.Value, rplStr); } return exp; } private string ConvertStatusContinued(string sc) { string template = "StatusContinued(\"STR{0}\",{1},objectId,objectType)"; string tmp = sc.Trim(); tmp = tmp.TrimStart('S', 't', 'a', 't', 'u', 's', 'C', 'o', 'n', 't', 'i', 'n', 'u', 'e', 'd'); tmp = tmp.Trim(); tmp = tmp.TrimStart('('); tmp = tmp.TrimEnd(')'); string[] arr = tmp.Split(','); return string.Format(template, arr[0].Trim(), arr[1].Trim()); } private string ReplaceSuddenChange(string exp) { if (!exp.Contains("SuddenChange")) return exp; string regex = @"SuddenChange\(\w+,\s*\d+,\s*\d+(\.\d+)?\)"; MatchCollection coll = Regex.Matches(exp, regex); foreach (Match item in coll) { string rplStr = ConvertSuddenChange(item.Value); exp = exp.Replace(item.Value, rplStr); } return exp; } private string ConvertSuddenChange(string sc) { string template = "SuddenChange(\"STR{0}\",{1},{2},objectId,objectType)"; string tmp = sc.Trim(); tmp = tmp.TrimStart('S', 'u', 'd', 'd', 'e', 'n', 'C', 'h', 'a', 'n', 'g','e'); tmp = tmp.Trim(); tmp = tmp.TrimStart('('); tmp = tmp.TrimEnd(')'); string[] arr = tmp.Split(','); return string.Format(template, arr[0].Trim(), arr[1].Trim(), arr[2].Trim()); } private string ReplaceLastUpdateTime(string exp) { if (!exp.Contains("LastUpdateTime")) return exp; string regex = @"LastUpdateTime\(\w+\)"; MatchCollection coll = Regex.Matches(exp, regex); foreach (Match item in coll) { string rplStr = ConvertLastUpdateTime(item.Value); exp = exp.Replace(item.Value, rplStr); } return exp; } private string ConvertLastUpdateTime(string sc) { string template = "LastUpdateTime(\"STR{0}\",objectId,objectType)"; string tmp = sc.Trim(); tmp = tmp.TrimStart('L', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'T', 'i', 'm', 'e'); tmp = tmp.Trim(); tmp = tmp.TrimStart('('); tmp = tmp.TrimEnd(')'); return string.Format(template, tmp.Trim()); } } }