C# 使用栈结构实现 逻辑代码脚本的解析

   /// <summary>
    /// 代码解释器
    /// </summary>
    public class CodeStructureInterpreter
    {
        /// <summary>
        /// 数组开始括号 默认‘[’
        /// </summary>
        public char StartArrBrace { get; set; } = '[';

        /// <summary>
        /// 逻辑结束括号 默认‘]’
        /// </summary>
        public char EndArrBrace { get; set; } = ']';
        private Stack<int> _codeStack;
        private string _code;
        private static Dictionary<char, string> LogicDic = new Dictionary<char, string>()
        {
            {'', "AND"},
            {'', "OR"},
            {'', "NOT"}
        };


        public CodeStructureInterpreter(string code)
        {
            _code = code;
        }

        /// <summary>
        /// 提取
        /// </summary>
        public Interlingua DoExctract(out string msg)
        {
            msg = "";
            if (string.IsNullOrWhiteSpace(_code))
            {
                msg = "输入条件为空!";
                return null;
            }
            var codeArea = DoExtractCodeArea('{', '}', ref msg, true);

            return new Interlingua();
        }
        /// <summary>
        /// 提取代码块
        /// </summary>
        /// <returns></returns>
        public CodeArea DoExtractCodeArea(char startBrace, char endBrace, ref string msg, bool hasLogic = false)
        {
            var len = _code.Length;
            if (len == 0 || len == 1)
            {
                msg = "输入条件长度错误!";
                return null;
            }
            Stack<WordBrace> areaStack = new Stack<WordBrace>();
            //父节点和序号
            Dictionary<string, int> sortDic = new Dictionary<string, int>();
            var i = 0;
            List<CodeArea> tempList = new List<CodeArea>();
            while (i < len)
            {
                var depth = areaStack.Count;
                var code = _code[i];
                if (code == '"')//字符串跳过
                {
                    var str = GetCodeSting(_code, i, out int end, ref msg);
                    if (end == 0)
                    {
                        msg = string.IsNullOrWhiteSpace(msg) ? "字符串处理失败" : msg;
                        return null;
                    }
                    i = end + 1;
                    continue;
                }
                if (code == startBrace)
                {

                    var parentKey = "0";//父节点唯一标识
                    if (depth > 0)
                    {
                        var parent = areaStack.Peek();
                        parentKey = parent.Key;

                    }
                    if (sortDic.ContainsKey(parentKey))
                    {
                        sortDic[parentKey]++;
                    }
                    else
                    {
                        sortDic.Add(parentKey, 1);
                    }
                    var key = sortDic[parentKey].ToString();
                    key = $"{parentKey}_{key}";//当前节点唯一标识
                    areaStack.Push(new WordBrace(code, key, i, depth, sortDic[parentKey])
                    {
                        CodeAreaObj = new CodeArea() { Depth = depth, Key = key, ParentKey = parentKey }
                    });
                }
                else if (code == endBrace && depth > 0)
                {
                    if (depth == 0)
                    {
                        msg = $"{code} 附近语法错误,位置{i}。";
                        return null;
                    }
                    var start = areaStack.Pop();
                    var startIndex = start.Index + 1;
                    start.CodeAreaObj.Express = string.Join("", _code.Skip(startIndex).Take(i - startIndex));
                    tempList.Add(start.CodeAreaObj);

                    if (sortDic.ContainsKey(start.Key))
                    {
                        //重置排序
                        sortDic[start.Key] = 0;
                    }
                }
                else if (hasLogic && LogicDic.ContainsKey(code))
                {
                    if (depth == 0)
                    {
                        msg = $"{code} 附近语法错误,不匹配的逻辑符号,位置{i}。";
                        return null;
                    }
                    var temp = areaStack.Peek();
                    temp.CodeAreaObj.LogicOp.Add(LogicDic[code]);
                }
                i++;
            }
            if (areaStack.Count > 0)
            {
                var next = areaStack.Pop();
                msg = $"语法错误,没有关闭的表达式“{startBrace}”。位置{next.Index}";
                return null;
            }

            foreach (var codeArea in tempList)
            {
                Console.WriteLine($"key:{codeArea.Key},depth:{codeArea.Depth},logicOp:{string.Join(";", codeArea.LogicOp)},express:{codeArea.Express}");
            }

            var result = GetAreaTree("0_1", tempList, ref msg);
            if (!string.IsNullOrWhiteSpace(msg))
            {
                return null;
            }
            return result;
        }

        /// <summary>
        /// 获取字符串并返回结束位置
        /// </summary>
        /// <param name="start">起始位置</param>
        /// <param name="end">返回结束位置</param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string GetCodeSting(string code, int start, out int end, ref string msg)
        {
            char brace = '"';
            char escape = '\';
            string result = "";
            bool inEscape = false;
            end = 0;
            var len = code.Length;
            Stack<int> strStack = new Stack<int>();
            strStack.Push(start);
            for (int i = start + 1; i < len; i++)
            {
                if (inEscape)
                {
                    if (code[i] != brace && code[i] != escape)
                    {
                        msg = $"无法识别的转义符号{code[i]},位置:{i}";
                        return null;
                    }
                    inEscape = false;
                    continue;
                }
                if (code[i] == escape)
                {
                    inEscape = true;
                    continue;
                }
                if (code[i] == brace)
                {
                    strStack.Pop();
                    end = i;
                    var startIndex = start + 1;
                    result = string.Join("", code.Skip(startIndex).Take(i - startIndex));
                    break;
                }

            }
            if (strStack.Count > 0)
            {
                var i = strStack.Pop();
                msg = $"未能识别的符号 {code[i]} ,位置:{i}";
                return null;
            }
            return result.Trim();
        }
        /// <summary>
        /// 构造代码块树状结构
        /// </summary>
        /// <param name="key"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public CodeArea GetAreaTree(string key, List<CodeArea> list, ref string msg)
        {
            var result = list.Find(f => f.Key == key);
            if(result.LogicOp==null || result.LogicOp.Count==0)
                result.ExpressOpRules = GetFilterRulesByExpress(result.Express, ref msg);

            if (list.Exists(e => e.ParentKey == result.Key))
            {
                foreach (var codeArea in list.FindAll(f => f.ParentKey == result.Key))
                {
                    if (result.ChildrenAreas == null) result.ChildrenAreas = new List<CodeArea>();
                    result.ChildrenAreas.Add(GetAreaTree(codeArea.Key, list, ref msg));
                }

            }
            return result;
        }
        /// <summary>
        /// 转换成能筛选的表达式
        /// </summary>
        /// <returns></returns>
        private List<FilterRules> GetFilterRulesByExpress(string express, ref string msg)
        {
            if (string.IsNullOrWhiteSpace(express))
            {
                msg += "";
                return null;
            }
            var dataStart = express.IndexOf('"');
            var data = GetCodeSting(express, dataStart, out int end, ref msg);
            if (string.IsNullOrWhiteSpace(data) && end == 0)
            {
                msg += $"{express} 附近有语法错误";
                return null;
            }
            var other = express.Remove(dataStart, end- dataStart+1);
            if (!other.Contains(":"))
            {
                msg += $"{express} 附近有语法错误,没有找到 ‘:’ 号";
                return null;
            }
            var ohterArr = other.Split(':');
            if (ohterArr.Length != 2)
            {
                msg += $"{express} 附近有语法错误,请检查是否规范";
                return null;
            }
            var field = ohterArr[0];
            List<FilterRules> list = new List<FilterRules>();
            list.Add(new FilterRules() { Field = field, Fdata = data });
            return list;
        }
       
        //private FiltersOp GetFilterGroup(CodeArea codeArea)
        //{
        //    var result = new FiltersOp() { FilterOps = new List<FiltersOp>() };
        //    if (codeArea.LogicOp != null)
        //        result.GroupOp = string.Join(",", codeArea.LogicOp);
        //    if (codeArea.HasChildren)
        //    {
        //        foreach (var childrenArea in codeArea.ChildrenAreas)
        //        {
        //            result.FilterOps.Add(GetFilterGroup(childrenArea));
        //        }
        //    }
        //    else
        //    {
        //        result.OpRules = codeArea.ExpressOpRules;
        //        Console.WriteLine(string.Join(",", codeArea.ExpressOpRules.Select(s => s.Field)) );
        //        Console.WriteLine(string.Join(",", codeArea.ExpressOpRules.Select(s => s.Fdata)) );
        //    }
        //    return result;
        //}
    }
    /// <summary>
    /// 代码块
    /// </summary>
    public class CodeArea
    {
        /// <summary>
        /// 父级的序号
        /// </summary>
        public string ParentKey { get; set; }
        /// <summary>
        /// 当前Key "1_1"
        /// </summary>
        public string Key { get; set; }

        /// <summary>
        /// 深度
        /// </summary>
        public int Depth { get; set; }
        /// <summary>
        /// 序号
        /// </summary>
        public int Sort { get; set; }

        /// <summary>
        /// 表达式
        /// </summary>
        public string Express { get; set; }
        /// <summary>
        /// 关联符
        /// </summary>
        public List<string> LogicOp { get; set; } = new List<string>();
        /// <summary>
        /// 子代码块
        /// </summary>
        public List<CodeArea> ChildrenAreas { get; set; }
        /// <summary>
        /// 是否还有子代码块
        /// </summary>
        public bool HasChildren => ChildrenAreas?.Count > 0;
        /// <summary>
        ///表达式处理后的系统可识别的表达式
        /// </summary>
        public List<FilterRules> ExpressOpRules { get; set; }

    }
    /// <summary>
    /// 入栈 起始终止符 信息
    /// </summary>
    public class WordBrace
    {
        public WordBrace(char symble, string key, int index, int depth, int sort)
        {
            Symble = symble;
            Index = index;
            Depth = depth;
            Sort = sort;
            Key = key;

        }
        public char Symble { get; set; }
        public int Index { get; set; }
        public int Depth { get; set; }
        public int Sort { get; set; }
        public string Key { get; set; }
        public CodeArea CodeAreaObj { get; set; }
    }

    /// <summary>
    /// 过滤条件类
    /// </summary>
    public class FiltersOp
    {
        /// <summary>
        /// 操作符
        /// </summary>
        public string GroupOp { get; set; }
        /// <summary>
        /// 过滤规则,和字段
        /// </summary>
        public List<FilterRules> OpRules { get; set; }
        /// <summary>
        /// 下级过滤条件
        /// </summary>
        public List<FiltersOp> FilterOps { get; set; }
    }
    /// <summary>
    /// 过滤规则
    /// </summary>
    public class FilterRules
    {
        /// <summary>
        /// 字段
        /// </summary>
        public string Field { get; set; }
        /// <summary>
        /// 操作符
        /// </summary>
        public string Op { get; set; }
        /// <summary>
        ////// </summary>
        public string Fdata { get; set; }
    }

调用结果:

 CodeStructureInterpreter codeInterpreter = new CodeStructureInterpreter("{{{{字段:"空}}}}}\"\""} 和 {字段:"问"}和{字段:"a"}} 或 {字段:$in["旗","空"]}} 非 {{{字段:"空"} 和 {字段:"眼"}} 或 {{字段:"旗"} 和 {字段:"问"}}}}");
            codeInterpreter.DoExctract(out var msg);
            Console.WriteLine(msg);

原文地址:https://www.cnblogs.com/daxiongblog/p/13494362.html