예제 #1
0
        private static bool TryReadHatPower(string text, ref int pos, out int power)
        {
            if (text[pos] != '^')
            {
                // leaving this even if it is a try method. Getting here means something should have been checked before
                throw new InvalidOperationException("Check that there is a hat power to read before calling this");
            }

            pos++;
            WhiteSpaceReader.TryRead(text, ref pos);

            var ps = OperatorReader.TryReadSign(text, ref pos);

            if (ps == Sign.None)
            {
                ps = Sign.Positive;
            }

            if (OperatorReader.TryReadSign(text, ref pos) != Sign.None)
            {
                // not allowing a^--2 as it is most likely a typo
                power = 0;
                return(false);
            }

            WhiteSpaceReader.TryRead(text, ref pos);
            if (IntReader.TryReadInt32(text, ref pos, out power))
            {
                power *= (int)ps;
                return(true);
            }

            power = 0;
            return(false);
        }
예제 #2
0
        internal static bool TryRead(string text, ref int pos, out IReadOnlyList <SymbolAndPower> result)
        {
            var start = pos;
            var sign  = Sign.Positive;
            List <SymbolAndPower> saps = null;

            while (pos < text.Length)
            {
                WhiteSpaceReader.TryRead(text, ref pos);
                if (!TryRead(text, ref pos, out SymbolAndPower sap))
                {
                    pos    = start;
                    result = null;
                    return(false);
                }

                if (sap.Power < 0 &&
                    sign == Sign.Negative)
                {
                    pos    = start;
                    result = null;
                    return(false);
                }

                if (sign == Sign.Negative)
                {
                    sap = new SymbolAndPower(sap.Symbol, -1 * sap.Power);
                }

                if (saps == null)
                {
                    saps = new List <SymbolAndPower>();
                }

                saps.Add(sap);

                var op = OperatorReader.TryReadMultiplyOrDivide(text, ref pos);
                if (op != MultiplyOrDivide.None)
                {
                    WhiteSpaceReader.TryRead(text, ref pos);
                    if (OperatorReader.TryReadMultiplyOrDivide(text, ref pos) != MultiplyOrDivide.None)
                    {
                        pos    = start;
                        result = null;
                        return(false);
                    }

                    if (op == MultiplyOrDivide.Division)
                    {
                        if (sign == Sign.Negative)
                        {
                            pos    = start;
                            result = null;
                            return(false);
                        }

                        sign = Sign.Negative;
                    }
                }
            }

            if (saps == null || !IsUnique(saps))
            {
                result = null;
                return(false);
            }

            result = saps;
            return(true);
        }
예제 #3
0
        internal static bool TryReadInt32(string text, ref int pos, out int result)
        {
            if (pos == text.Length)
            {
                result = 0;
                return(false);
            }

            var sign = OperatorReader.TryReadSign(text, ref pos);

            var start = pos;
            var end   = Math.Min(text.Length, pos + MaxDigits - 1);

            result = 0;

            while (pos < end)
            {
                var c = text[pos] - '0';
                if (c < 0 || c > 9)
                {
                    break;
                }

                result *= 10;
                result += c;
                pos++;
            }

            if (pos == start)
            {
                if (sign != Sign.None)
                {
                    pos--;
                }

                return(false);
            }

            if (pos < end ||
                !IsDigit(text, pos))
            {
                switch (sign)
                {
                case Sign.Negative:
                    result = -result;
                    return(true);

                case Sign.None:
                case Sign.Positive:
                    return(true);

                default:
                    throw new InvalidEnumArgumentException(nameof(sign), (int)sign, typeof(Sign));
                }
            }

            // getting here means we must handle the last digit and potential overflows.
            long temp = result;

            temp *= 10;
            temp += text[pos] - '0';

            switch (sign)
            {
            case Sign.Negative:
            {
                temp = -temp;
                if (temp >= int.MinValue)
                {
                    result = (int)temp;
                    pos++;
                    return(true);
                }

                pos    = start - 1;
                result = 0;
                return(false);
            }

            case Sign.None:
            case Sign.Positive:
            {
                if (temp <= int.MaxValue)
                {
                    result = (int)temp;
                    pos++;
                    return(true);
                }

                pos = start - sign == Sign.Positive
                            ? 1
                            : 0;
                result = 0;
                return(false);
            }

            default:
                throw new InvalidEnumArgumentException(nameof(sign), (int)sign, typeof(Sign));
            }
        }