Example #1
0
        private double ReadNumber(SimpleParser parser)
        {
            var factor = parser.NextIs('-') ? -1 : 1;

            parser.ConsumeAny('+', '-');
            if (!double.TryParse(parser.ConsumeAny("0.123456789".ToCharArray()), NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
            {
                return(double.NaN);
            }
            return(factor * result);
        }
Example #2
0
        public double Eval()
        {
            var op_count = -1;

            while (parser.HasNext)
            {
                if (Operations.Count > op_count)
                {
                    op_count = Operations.Count;
                }
                else
                {
                    break;
                }
                parser.ConsumeAny(' ');
                if (parser.NextIs('('))
                {
                    parser.Skip(1);
                    var exp = new Expression(parser)
                    {
                        MustConsumeClosingBracket = true
                    };
                    exp.Eval();
                    var op = new Operation {
                        Operator = "+", Expression = exp
                    };
                    Operations.Add(op);
                }
                else if (parser.NextIs("+-*^/%".ToCharArray()))
                {
                    var op = new Operation()
                    {
                        Operator = parser.NextChar.ToString()
                    };
                    parser.Skip(1);
                    parser.ConsumeAny(' ');
                    if (parser.NextIs('('))
                    {
                        parser.Skip(1);
                        var exp = new Expression(parser);
                        exp.MustConsumeClosingBracket = true;
                        op.Expression = exp;
                        exp.Eval();
                    }
                    else
                    {
                        op.Expression = new Expression(ReadNumber(parser));
                    }
                    Operations.Add(op);
                }
                else if (parser.NextIs("0.123456789".ToCharArray()))
                {
                    Operations.Add(new Operation {
                        Operator = "+", Expression = new Expression(ReadNumber(parser))
                    });
                }
                else if (parser.NextIs(')') && MustConsumeClosingBracket)
                {
                    parser.Skip(1);
                    break;
                }
            }
            if (!Operations.Any())
            {
                return(double.NaN);
            }
            var first_op = Operations.First();

            if (string.IsNullOrEmpty(first_op.Operator))
            {
                first_op.Operator = "+";
            }
            else if (first_op.Operator == "-")
            {
                first_op.Operator         = "+";
                first_op.Expression.Value = (first_op.Expression.Value ?? Double.NaN) * (-1);
            }
            if (Operations.Count == 1)
            {
                var op  = Operations[0];
                var val = op.Expression.Value;
                if (val == null)
                {
                    return(double.NaN);
                }
                if (op.Operator == "-")
                {
                    Value = (-1.0 * (val.Value));
                }
                else
                {
                    Value = val;
                }
            }
            else if (Operations.Count == 2)
            {
                Value = Operations[1].Apply(Operations[0].Apply(0));
            }
            else
            {
                if (Precedence(Operations[0].Operator) > 0)
                {
                    return(double.NaN); // only + and minus may be first operator!
                }
                // repeated contraction by precedence
                while (Operations.Count > 1)
                {
                    var highest_op = Operations.Select(x => x.Operator).OrderByDescending(x => Precedence(x)).First();
                    if (Precedence(highest_op) == 0)
                    {
                        double sum = 0;
                        foreach (var op in Operations)
                        {
                            sum = op.Apply(sum);
                        }
                        return(sum);
                    }
                    var ops = new List <Operation>();
                    int i   = 0;
                    foreach (var op in Operations)
                    {
                        if (op.Operator == highest_op)
                        {
                            var last_op = ops[ops.Count - 1];
                            last_op.Expression.Value = op.Apply(last_op.Expression.Value ?? double.NaN);
                            i++;
                            continue;
                        }
                        ops.Add(op);
                        i++;
                    }
                    Operations = ops;
                }
                return(Operations[0].Apply(0));
            }
            return(Value ?? double.NaN);
        }