Feedback

C# - Simple EvaluierungsEngine

Veröffentlicht von am 10/31/2015
(0 Bewertungen)
Ein simpler aritmetischer parser:

Expression result = "3+5*5";
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!