1. 程式人生 > 其它 >直譯器模式 字串解析

直譯器模式 字串解析

直譯器模式(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}");

        }
    }

檢視結果:

 .........