コード例 #1
0
ファイル: UnitFactory.cs プロジェクト: dabbers/MathParser
        private IMathNode isSpeicalFormattedNumber(string expression)
        {
            expression = expression.Trim();
            var nbc = new NumericBaseConverter();

            // Probably formatted via 0x hex? Check for hex input
            if (expression[0] == '0' && (expression[1] == 'x' || expression[1] == 'X'))
            {
                try
                {
                    string number = expression.Substring(2);
                    var    val    = (decimal)Int64.Parse(number, System.Globalization.NumberStyles.HexNumber);
                    var    inner  = new NumericMathNode(new UnitDouble(val, UnitTypes.Hexadecimal, NumericBaseUnits.Hexadecimal, nbc))
                    {
                        UnitType = UnitTypes.Hexadecimal
                    };
                    return(new UnitUniLeafMathNode(inner, UnitTypes.Hexadecimal, nbc, NumericBaseUnits.Hexadecimal));
                }
                catch { }
            }
            if (expression[0] == '0' && (expression[1] == 'b' || expression[1] == 'B'))
            {
                try
                {
                    string number = expression.Substring(2);
                    var    val    = (decimal)Convert.ToInt64(number, 2);
                    var    inner  = new NumericMathNode(new UnitDouble(val, UnitTypes.Binary, NumericBaseUnits.Binary, nbc))
                    {
                        UnitType = UnitTypes.Binary
                    };
                    return(new UnitUniLeafMathNode(inner, UnitTypes.Binary, nbc, NumericBaseUnits.Binary));
                }
                catch { }
            }
            if (expression[0] == '0')
            {
                try
                {
                    var val   = (decimal)Convert.ToInt64(expression, 8);
                    var inner = new NumericMathNode(new UnitDouble(val, UnitTypes.Octal, NumericBaseUnits.Octal, nbc))
                    {
                        UnitType = UnitTypes.Octal
                    };
                    return(new UnitUniLeafMathNode(inner, UnitTypes.Octal, nbc, NumericBaseUnits.Octal));
                }
                catch { }
            }

            return(null);
        }
コード例 #2
0
ファイル: MathParser.cs プロジェクト: dabbers/MathParser
        private IMathNode parse(string expression)
        {
            if (String.IsNullOrEmpty(expression))
            {
                return(null);
            }

            expression = expression.Trim();

            expression = expression.TrimOuterParens();

            short  lowestop = -1;
            int    oppos    = -1;
            int    parens   = 0;
            int    oplength = 0;
            string symbol   = String.Empty;

            // Check for misplaced operators ( + - / * ^ )
            if (this.invalidPreceedingOperators.Keys.Contains(expression[0].ToString()) || this.invalidPreceedingOperators.Keys.Contains(expression.Last().ToString()))
            {
                throw new InvalidOperatorException(expression[0], expression);
            }

            int startPos = 0;

            if (expression[0] == '-' || expression[0] == '~')
            {
                startPos++;
            }
            int lastNonWhiteSpace = -1;

            // get first smallest operator and parse left and right
            for (int pos = expression.Length - 1; pos >= startPos; pos--)
            {
                short opval;
                char  tmp = expression[pos];

                if (expression[pos] == ')')
                {
                    lastNonWhiteSpace = pos;
                    parens++;
                }

                else if (expression[pos] == '(')
                {
                    lastNonWhiteSpace = pos;
                    parens--;
                }

                if (parens < 0)
                {
                    throw new InvalidMathExpressionException(expression);
                }

                var searchop = expression[pos].ToString();
                if (searchop == "<" || searchop == ">")
                {
                    searchop = expression[pos - 1].ToString() + expression[pos].ToString();
                    pos--;
                }

                if (!this.operators.ContainsKey(searchop))
                {
                    if (!Char.IsWhiteSpace(expression[pos]))
                    {
                        lastNonWhiteSpace = pos;
                    }
                    continue;
                }

                if (this.invalidPreceedingOperators.ContainsKey(searchop) && this.operators.ContainsKey(expression[pos - 1].ToString()))
                {
                    throw new InvalidOperatorException(searchop[0], expression);
                }

                opval = this.operators[searchop];

                // check for a - sign after this just in case.
                if ((parens != 0 || lowestop >= opval) && expression[pos + 1] != '-')
                {
                    continue;
                }

                lowestop = opval;
                oppos    = pos;
                oplength = searchop.Length - 1;
                symbol   = searchop;
            }

            if (parens != 0)
            {
                throw new InvalidMathExpressionException(expression);
            }

            // No opperator was found, we are parsing something else
            if (oppos == -1)
            {
                decimal dbl;
                // We want to do octal parsing later on, so check this isn't an octal #. Otherwise, verify it's a decimal or 0.
                if ((expression[0] != '0' || expression.Length == 1 || expression[1] == '0' || expression[1] == '.') && decimal.TryParse(expression.Trim(), out dbl))
                {
                    return(new NumericMathNode(dbl));
                }
                else // This isn't a number... So it must be a function or variable
                {
                    // expression stores our function(args)

                    var node = uniLeafFact.CreateUniLeafNode(expression.Trim(), this);
                    if (null == node)
                    {
                        decimal val;
                        // Check for a constant if not a function
                        if (symbols.TryGetValue(expression.Trim(), out val))
                        {
                            node = new NumericMathNode(val);
                        }
                        else
                        {
                            // Check for unit label if not a function nor a constant
                            var result = UnitFactory.TryParse(expression, this);

                            if (result != null)
                            {
                                return(result);
                            }

                            if (expression[0] == '-')
                            {
                                return(new MultiplicationBiLeafMathNode(new NumericMathNode(-1), this.Parse(expression.Substring(1))));
                            }
                            else if (expression[0] == '~')
                            {
                                return(new NegateUniLeafMathNode(this.Parse(expression.Substring(1))));
                            }
                            else if (expression[0] == '"' && expression.Last() == '"')
                            {
                                return(new StringMathNode(expression.Substring(1, expression.Length - 2)));
                            }

                            throw new InvalidMathExpressionException(expression);
                        }
                    }

                    return(node);
                }
            }
            else
            {
                string left = String.Empty;

                if (oppos - 1 > 0)
                {
                    left = expression.Substring(0, oppos - oplength);
                }
                else
                {
                    left = expression[0].ToString();
                }

                string right = expression.Substring(oppos + 1 + oplength, expression.Length - oppos - 1 - oplength);

                return(operFact.CreateOperatorNode(symbol, this.parse(left), this.parse(right)));
            }
        }