Feedback

C# - Simple EvaluierungsEngine

Veröffentlicht von am 31.10.2015
(0 Bewertungen)
Ein simpler aritmetischer parser:

Expression result = "3+5*5";
GFU-Schulungen  [Anzeige]

C# 2017/2015/2013 Aufbau

In dieser Schulung lernen Sie fortgeschrittene Techniken im Bereich .Net C#. Dabei stehen neben den eigentlichen Techniken auch architektonische Aspekte im Mittelpunkt.

XML und .NET Überblick

Um auf dem neuesten Wissensstand zu sein, sollten Sie unser aktuelles ASP .NET Komplett Seminar belegen.
Nach dem Seminar kennen Sie die wichtigsten Strömungen in der Software-Technologie

using System.Parsers.Mathematics;

namespace System.Parsers.Mathematics
{
	public class Expression
    {
        private readonly List<Stack> _stacks = new List<Stack>();

        internal Expression()
        {
        }

        public object Result { get; set; }
        public string Term { get; internal set; }

        public static Expression Parse(string expr, VariableStack[] vars)
        {
            var returns = new Expression {Term = expr};

            expr = expr.Replace("²", "²0");
            expr = expr.Replace("³", "³0");
            expr = expr.Replace("sqrt[", "√");
            expr = expr.Replace("pi", "π");
            expr = expr.Replace("]", "");
            expr = expr.Replace("√", "1√");
            expr = expr.Replace("π", "1π1");
            expr = expr.Replace("True", "1");
            expr = expr.Replace("False", "0");

            if (vars != null)
                expr = vars.Aggregate(expr, (current, var) => current.Replace(@var.Name, @var.Value.ToString()));

            char[] chars = expr.ToCharArray();
            string result = "";
            var group_stack = new GroupStack(new List<Stack>());

            bool bracket_open = false;
            foreach (char c in chars)
            {
                if (isNum(c))
                {
                    result += c;
                }
                else
                {
                    if (isOP(c))
                    {
                        if (!bracket_open)
                        {
                            returns._stacks.Add(new NumStack(Convert.ToDouble(result)));
                            returns._stacks.Add(new OpStack(c.ToString()));
                        }
                        else
                        {
                            group_stack.Value.Add(new NumStack(Convert.ToDouble(result)));
                            group_stack.Value.Add(new OpStack(c.ToString()));
                        }
                        result = "";
                    }
                    else if (c == '(')
                        bracket_open = true;
                    else if (c == ')')
                    {
                        bracket_open = false;
                        // group_stack.Value.Add(returns.getLastNum(expr, group_stack.Value));
                        returns._stacks.Add(group_stack);
                        group_stack = new GroupStack(new List<Stack>());
                    }
                }
            }

            group_stack.Value = returns.dotbeforestatement(group_stack.Value);
            returns.Calculate();

            return returns;
        }

        internal void Calculate()
        {
            for (int i = 0; i < _stacks.Count - 1; i++)
            {
                Stack stack = _stacks[i];
                var opStack = stack as OpStack;
                if (opStack != null)
                {
                    var first = (NumStack) _stacks[i - 1];
                    var second = (NumStack) _stacks[i + 1];
                    OpStack op = opStack;
                    var _result = new NumStack(0);
                    bool resultisbool = false;
                    bool boolresult = false;

                    switch (op.Value)
                    {
                        case "+":
                            _result = new NumStack(first.Value + second.Value);
                            break;
                        case "-":
                            _result = new NumStack(first.Value - second.Value);
                            break;
                        case "*":
                            _result = new NumStack(first.Value*second.Value);
                            break;
                        case "/":
                            _result = new NumStack(first.Value/second.Value);
                            break;
                        case "^":
                            _result = new NumStack(Math.Pow(first.Value, second.Value));
                            break;
                        case "%":
                            _result = new NumStack(first.Value%second.Value);
                            break;
                        case "&":
                            _result = new NumStack(Convert.ToDouble(first.Value.ToString() + second.Value.ToString()));
                            break;
                        case "²":
                            _result = new NumStack(first.Value*first.Value);
                            break;
                        case "³":
                            _result = new NumStack(first.Value*first.Value*first.Value);
                            break;
                        case "√":
                            _result = new NumStack(Math.Sqrt(second.Value));
                            break;
                        case "π":
                            _result = new NumStack(Math.PI);
                            break;
                        case "<":
                            resultisbool = true;
                            boolresult = first.Value < second.Value;
                            break;
                        case ">":
                            resultisbool = true;
                            boolresult = first.Value > second.Value;
                            break;
                        case "!":
                            resultisbool = true;
                            boolresult = first.Value != second.Value;
                            break;
                    }

                    _stacks.RemoveAt(0);
                    _stacks.RemoveAt(0);
                    _stacks.RemoveAt(0);
                    _stacks.Insert(0, _result);

                    Result = (_stacks[0] as NumStack).Value;

                    if (_stacks.Count != 1)
                    {
                        if (_stacks[0] != null && _stacks[1] != null && _stacks[2] != null)
                        {
                            Calculate();
                        }
                    }
                    if (resultisbool)
                    {
                        Result = boolresult;
                    }
                }
            }
        }

        #region "ObjectOperators"

        public static Expression operator +(Expression e1, Expression e2)
        {
            return Parse(e1.Result + "+" + e2.Result, null);
        }

        public static bool operator ==(Expression e1, Expression e2)
        {
            return e1 == e2;
        }

        public static bool operator !=(Expression e1, Expression e2)
        {
            return e1 != e2;
        }

        public static Expression operator +(Expression e1, string e2)
        {
            e2 = e2.Replace("=", "");
            return Parse(e2, null);
        }

        public static Expression operator -(Expression e1, Expression e2)
        {
            return Parse(e1.Result + "-" + e2.Result, null);
        }

        public static Expression operator *(Expression e1, Expression e2)
        {
            return Parse(e1.Result + "*" + e2.Result, null);
        }

        public static Expression operator /(Expression e1, Expression e2)
        {
            return Parse(e1.Result + "/" + e2.Result, null);
        }

        public static Expression operator <(Expression e1, Expression e2)
        {
            return Parse(e1.Result + "<" + e2.Result, null);
        }

        public static Expression operator >(Expression e1, Expression e2)
        {
            return Parse(e1.Result + ">" + e2.Result, null);
        }

        public static implicit operator Expression(string v)
        {
            double r;
            return double.TryParse(v, out r) ? Parse(v + "*1", null) : Parse(v, null);
        }

        public static implicit operator double(Expression instance)
        {
            return (double) instance.Result;
        }

        public static implicit operator bool(Expression instance)
        {
            return (bool) instance.Result;
        }

        public static implicit operator string(Expression instance)
        {
            return instance.Result.ToString();
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            return base.Equals(obj);
        }

        #endregion

        #region "Help Functions"

        private static bool isNum(char s)
        {
            double result;
            return double.TryParse(s.ToString(), out result);
        }

        private static bool isOP(char s)
        {
            return s == '+' | s == '-' | s == '*' | s == '/' | s == '^' | s == '%' | s == '&' | s == '²' | s == '3' |
                   s == '<' | s == '>' | s == '!' | s == '√' | s == 'π';
        }

        private bool isPunctiaton(char s)
        {
            return s == '*' | s == '/';
        }

        private NumStack getLastNum(string s, List<Stack> st)
        {
            string[] c = s.Split(Convert.ToChar((st[st.Count - 1] as OpStack).Value));
            return new NumStack(Convert.ToInt32(c[c.Length - 1]));
        }

        private List<Stack> dotbeforestatement(List<Stack> st)
        {
            List<Stack> returns = st;

            for (int i = 0; i < st.Count; i++)
            {
                Stack s = st[i];

                if (s is OpStack)
                {
                    var op = s as OpStack;
                    if (isPunctiaton(Convert.ToChar(op.Value)))
                    {
                        if (st.Count < 3)
                        {
                            Stack firstop = st[i - 2];
                            Stack first = st[i - 1];
                            Stack ops = s;
                            Stack second = st[i + 1];

                            returns.Remove(first);
                            returns.Remove(ops);
                            returns.Remove(second);
                            returns.Remove(firstop);

                            returns.InsertRange(0, new[] {first, ops, second, firstop});
                        }
                    }
                }
            }

            return returns;
        }

        #endregion

        #region "Implementations"

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public Expression Clone()
        {
            return this;
        }

        public override string ToString()
        {
            return Result.ToString();
        }

        #endregion
    }
	
    public abstract class Stack<t> : Stack
    {
        public t Value { get; set; }
        protected Stack(t v)
        {
            Value = v;
        }
        public override string ToString()
        {
            return Value.ToString();
        }
    }

    public abstract class Stack
    {
    }
	
	public class VariableStack : Stack
    {
        public string Name;
        public object Value;

        public VariableStack(string name, object value)
        {
            Name = name;
            Value = value;
        }
    }
	
	public class OpStack : Stack<string>
    {
        public OpStack(string v)
            : base(v)
        {
        }
    }
	
	public class NumStack : Stack<double>
    {
        public NumStack(double v)
            : base(v)
        {
        }
    }
	public class GroupStack : System.Parsers.Mathematics.Stack<List<Stack>>
    {
        public GroupStack(List<System.Parsers.Mathematics.Stack> v) : base(v)
        {
        }
    }
}
Abgelegt unter math.

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!