• 解释器模式 字符串解析


    解释器模式(Interpreter Pattern)

    提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

    .情景:将  string input = "(12+5)-(12+1)";进行解析,并计算出结果。

    第一眼看到这个问题瞬间蒙蔽。能直接计算为啥还要整成字符串?

    将结构拆解成为了  (I+I)-(I+I) I表示数字

    于是我们有了这样的结构:

        public  class Token
        {
            public enum Type 
            {
                Interger,Plus,Minus,Lparen,Rparen
            }
            public Type MyTpye;
            public string Text;
    
            public Token(Type myTpye, string text)
            {
                MyTpye = myTpye;
                Text = text;
            }
            public override string ToString()
            {
                return $"`{Text}`";
            }
        }
        class Program
        {
            static List<Token> ExpreesitionToken(string input)
            {
                List<Token> tokens = new List<Token>();
                for (int i = 0; i < input.Length; i++)
                {
                    switch (input[i])
                    {
                        case '+':
                            tokens.Add(new Token(Token.Type.Plus, input[i].ToString()));
                            break;
                        case '-':
                            tokens.Add(new Token(Token.Type.Minus, input[i].ToString()));
                            break;
                        case '(':
                            tokens.Add(new Token(Token.Type.Lparen, input[i].ToString()));
                            break;
                        case ')':
                            tokens.Add(new Token(Token.Type.Rparen, input[i].ToString()));
                            break;  
                        default: 
                            StringBuilder sb = new StringBuilder(input[i].ToString());
                            for (int j = i+1; j < input.Length; j++)
                            {
                                if (char.IsDigit(input[j]))
                                {
                                    sb.Append(input[j]);
                                    i=j;
                                }
                                else
                                {
                                    tokens.Add(new Token(Token.Type.Interger, sb.ToString()));
                                    break;
                                }
                            }
                            break;
                    }
                }
                return tokens; 
            }
    
            static void Main(string[] args)
            {
                string input = "(12+5)-(12+1)";
                ExpreesitionToken(input).ForEach(t => Console.WriteLine(t));
    
            }
        }

    输出看看:

     接下来就是重点了,如何进行解析?

    我们把表达式在拆解一个  就是 (A+A)-(B+B)=>A-B     其实就是把(括号)内的当成一个整体。  就 LeftElement   Operation   RightElement

        public interface IElement
        {
            int Value { get;}
        }
        public class Integer : IElement
        {
            public Integer(int value)
            {
                Value = value;
            }
            public int Value { get; }
        }
        public class BinaryOperation : IElement
        {
            public enum Type 
            {
                Additon,Subtraction
            }
            public Type type;
            public IElement Left;
            public IElement Right;
            public int Value 
            {
                get 
                {
                    switch (type)
                    {
                        case Type.Additon:
                            return Left.Value + Right.Value;
                            break;
                        case Type.Subtraction:
                            return Left.Value - Right.Value;
                            break;
                        default:
                            throw new AggregateException();
                    }
                } 
            }
        }

    最后传入数据项,返回一个操作:

            static IElement Parse(IReadOnlyList<Token> tokens)
            {
                var result = new BinaryOperation();
                bool haveLHS = false;
                for (int i = 0; i < tokens.Count; i++)
                {
                    var token = tokens[i];
                    switch (token.MyTpye)
                    {
                        case Token.Type.Interger:
                            var integer = new Integer(int.Parse(token.Text));
                            if (!haveLHS)
                            {
                                result.Left = integer;
                                haveLHS = true;
                            }
                            else
                            {
                                result.Right = integer;
                            }
                            break;
                        case Token.Type.Plus:
                            result.type = BinaryOperation.Type.Additon;
                            break;
                        case Token.Type.Minus:
                            result.type = BinaryOperation.Type.Subtraction;
                            break;
                        case Token.Type.Lparen:
                            int j = i;
                            for (; j < tokens.Count; j++)
                                if (tokens[j].MyTpye == Token.Type.Rparen)
                                    break;
                            var subExperssion = tokens.Skip(i + 1).Take(j - i - 1).ToList();
                            var element= Parse(subExperssion);
                            if (!haveLHS)
                            {
                                result.Left = element;
                                haveLHS = true;
                            }
                            else
                            {
                                result.Right = element;
                            }
                            i = j;
                            break; 
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
                return result;
            }

    完整代码:

        public interface IElement
        {
            int Value { get;}
        }
        public class Integer : IElement
        {
            public Integer(int value)
            {
                Value = value;
            }
            public int Value { get; }
        }
        public class BinaryOperation : IElement
        {
            public enum Type 
            {
                Additon,Subtraction
            }
            public Type type;
            public IElement Left;
            public IElement Right;
            public int Value 
            {
                get 
                {
                    switch (type)
                    {
                        case Type.Additon:
                            return Left.Value + Right.Value;
                            break;
                        case Type.Subtraction:
                            return Left.Value - Right.Value;
                            break;
                        default:
                            throw new AggregateException();
                    }
                } 
            }
        }
    
        public class Token
        {
            public enum Type
            {
                Interger, Plus, Minus, Lparen, Rparen
            }
            public Type MyTpye;
            public string Text;
    
            public Token(Type myTpye, string text)
            {
                MyTpye = myTpye;
                Text = text;
            }
            public override string ToString()
            {
                return $"`{Text}`";
            }
        }
        class Program
        {
            static List<Token> ExpreesitionToken(string input)
            {
                List<Token> tokens = new List<Token>();
                for (int i = 0; i < input.Length; i++)
                {
                    switch (input[i])
                    {
                        case '+':
                            tokens.Add(new Token(Token.Type.Plus, input[i].ToString()));
                            break;
                        case '-':
                            tokens.Add(new Token(Token.Type.Minus, input[i].ToString()));
                            break;
                        case '(':
                            tokens.Add(new Token(Token.Type.Lparen, input[i].ToString()));
                            break;
                        case ')':
                            tokens.Add(new Token(Token.Type.Rparen, input[i].ToString()));
                            break;
                        default:
                            StringBuilder sb = new StringBuilder(input[i].ToString());
                            for (int j = i + 1; j < input.Length; j++)
                            {
                                if (char.IsDigit(input[j]))
                                {
                                    sb.Append(input[j]);
                                    i = j;
                                }
                                else
                                {
                                    tokens.Add(new Token(Token.Type.Interger, sb.ToString()));
                                    break;
                                }
                            }
                            break;
                    }
                }
                return tokens;
            }
            static IElement Parse(IReadOnlyList<Token> tokens)
            {
                var result = new BinaryOperation();
                bool haveLHS = false;
                for (int i = 0; i < tokens.Count; i++)
                {
                    var token = tokens[i];
                    switch (token.MyTpye)
                    {
                        case Token.Type.Interger:
                            var integer = new Integer(int.Parse(token.Text));
                            if (!haveLHS)
                            {
                                result.Left = integer;
                                haveLHS = true;
                            }
                            else
                            {
                                result.Right = integer;
                            }
                            break;
                        case Token.Type.Plus:
                            result.type = BinaryOperation.Type.Additon;
                            break;
                        case Token.Type.Minus:
                            result.type = BinaryOperation.Type.Subtraction;
                            break;
                        case Token.Type.Lparen:
                            int j = i;
                            for (; j < tokens.Count; j++)
                                if (tokens[j].MyTpye == Token.Type.Rparen)
                                    break;
                            var subExperssion = tokens.Skip(i + 1).Take(j - i - 1).ToList();
                            var element= Parse(subExperssion);
                            if (!haveLHS)
                            {
                                result.Left = element;
                                haveLHS = true;
                            }
                            else
                            {
                                result.Right = element;
                            }
                            i = j;
                            break; 
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
                return result;
            }
    
            static void Main(string[] args)
            {
                string input = "(12+5)-(12+1)";
                var tokens = ExpreesitionToken(input);  
                var parsed = Parse(tokens);
                Console.WriteLine($"{input}={parsed.Value}");
    
            }
        }

    查看结果:

     

     .........

  • 相关阅读:
    Linux添加用户组和删除用户组
    购物意图分析
    架构是什么来的
    如何突破浏览器加载并发数的限制
    写JS自执行函数时要注意的
    网页是什么
    JVM
    javascript的边界
    浏览器
    HTTP
  • 原文地址:https://www.cnblogs.com/Zingu/p/16318024.html
Copyright © 2020-2023  润新知