private bool TryReadFrac( out FloatLiteral frac, int fracBase, Func <BigInteger, char, BigInteger?> tryAccumulateFracDigit) { (BigInteger, int)pair; bool parsed = TryReadNum(out pair, (BigInteger.Zero, 0), (acc, c) => { var(i, n) = acc; var maybeAcc = tryAccumulateFracDigit(i, c); if (maybeAcc.HasValue) { return(maybeAcc.Value, n + 1); } else { return(null); } }); if (parsed) { var(i, n) = pair; frac = FloatLiteral.Number(i, fracBase, -n); return(true); } else { frac = FloatLiteral.Zero(fracBase); return(false); } }
/// <summary> /// Losslessly changes a float literal's base. Base changes only work if old base /// is a power of the new base. /// </summary> /// <param name="newBase">The new base.</param> /// <returns>An equivalent float literal with base <paramref name="newBase"/>.</returns> public FloatLiteral ChangeBase(int newBase) { if (Kind != FloatLiteralKind.Number || Base == newBase) { return(this); } else if (Exponent == 0) { return(FloatLiteral.Number(IsNegative, Significand, newBase, 0)); } // Note: `x * (n ^ m) ^ k` equals `x * n ^ (m * k)`. var power = 1; var resultBase = Base; while (resultBase != newBase) { if (resultBase < newBase || resultBase % newBase != 0) { throw new InvalidOperationException( $"Float literal '{this}' with base '{Base}' cannot be transformed losslessly to float with base '{newBase}'."); } resultBase /= newBase; power++; } return(FloatLiteral.Number(IsNegative, Significand, newBase, power * Exponent)); }
private bool TryReadUnsignedNumber( bool negate, out object result, IntegerReader tryReadNum, FloatReader tryReadFrac, char exponentChar, int exponent) { BigInteger num; if (tryReadNum(out num)) { if (Expect('.')) { FloatLiteral frac; if (!tryReadFrac(out frac)) { frac = FloatLiteral.Zero(exponent); } var floatNum = num + frac; if (Expect(exponentChar) || Expect(char.ToUpperInvariant(exponentChar))) { floatNum = floatNum.ChangeBase(exponent); if (!TryAppendExponent(floatNum, out floatNum)) { result = null; return(false); } } result = MaybeNegate(floatNum, negate); } else if (Expect(exponentChar) || Expect(char.ToUpperInvariant(exponentChar))) { FloatLiteral floatNum; if (!TryAppendExponent(FloatLiteral.Number(num, exponent), out floatNum)) { result = null; return(false); } result = MaybeNegate(floatNum, negate); } else { result = MaybeNegate(num, negate); } return(true); } else { result = null; return(false); } }