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); }
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); }
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)); } }