private void ParseBinaryNumber(ref TokenInfo info) { var num = 0UL; var digits = 0; var hasUnderscores = false; var hasOverflown = false; char digit; while (CharUtils.IsBinary(digit = TextWindow.PeekChar()) || digit == '_') { TextWindow.AdvanceChar(); if (digit == '_') { hasUnderscores = true; continue; } // Next shift will overflow if 63rd bit is set if ((num & 0x8000_0000_0000_0000) != 0) { hasOverflown = true; } num = (num << 1) | (ulong)CharUtils.DecimalValue(digit); digits++; } var(isUnsignedLong, isSignedLong, isComplex) = (false, false, false); if (TextWindow.AdvanceIfMatches("ull", true)) { isUnsignedLong = true; } else if (TextWindow.AdvanceIfMatches("ll", true)) { isSignedLong = true; } else if (TextWindow.AdvanceIfMatches("i", true)) { isComplex = true; } if (!_options.SyntaxOptions.AcceptBinaryNumbers) { AddError(ErrorCode.ERR_BinaryNumericLiteralNotSupportedInVersion); } if (!_options.SyntaxOptions.AcceptUnderscoreInNumberLiterals && hasUnderscores) { AddError(ErrorCode.ERR_UnderscoreInNumericLiteralNotSupportedInVersion); } if (!Options.SyntaxOptions.AcceptLuaJITNumberSuffixes && (isUnsignedLong || isSignedLong || isComplex)) { AddError(ErrorCode.ERR_NumberSuffixNotSupportedInVersion); } if (digits < 1) { num = 0; // Safe default AddError(ErrorCode.ERR_InvalidNumber); } if (hasOverflown || (num > long.MaxValue && !isUnsignedLong)) { num = 0; // Safe default AddError(ErrorCode.ERR_NumericLiteralTooLarge); } info.Text = TextWindow.GetText(intern: true); if (isUnsignedLong) { info.ValueKind = ValueKind.ULong; info.ULongValue = num; } else if (isSignedLong) { info.ValueKind = ValueKind.Long; info.LongValue = unchecked ((long)num); } else if (isComplex) { info.ValueKind = ValueKind.Complex; info.ComplexValue = new Complex(0, num); } else { switch (_options.SyntaxOptions.BinaryIntegerFormat) { case IntegerFormats.NotSupported: case IntegerFormats.Double: info.ValueKind = ValueKind.Double; info.DoubleValue = num; break; case IntegerFormats.Int64: info.ValueKind = ValueKind.Long; info.LongValue = unchecked ((long)num); break; default: throw ExceptionUtilities.UnexpectedValue(_options.SyntaxOptions.BinaryIntegerFormat); } } }
private void ParseOctalNumber(ref TokenInfo info) { var num = 0L; var digits = 0; var hasUnderscores = false; var hasOverflown = false; char digit; while (CharUtils.IsOctal(digit = TextWindow.PeekChar()) || digit == '_') { TextWindow.AdvanceChar(); if (digit == '_') { hasUnderscores = true; continue; } // If any of these bits are set, we'll overflow if ((num & 0x7000_0000_0000_0000) != 0) { hasOverflown = true; } num = (num << 3) | CharUtils.DecimalValue(digit); digits++; } if (!_options.SyntaxOptions.AcceptOctalNumbers) { AddError(ErrorCode.ERR_OctalNumericLiteralNotSupportedInVersion); } if (!_options.SyntaxOptions.AcceptUnderscoreInNumberLiterals && hasUnderscores) { AddError(ErrorCode.ERR_UnderscoreInNumericLiteralNotSupportedInVersion); } if (digits < 1) { num = 0; // Safe default AddError(ErrorCode.ERR_InvalidNumber); } if (hasOverflown) { num = 0; // Safe default AddError(ErrorCode.ERR_NumericLiteralTooLarge); } info.Text = TextWindow.GetText(intern: true); switch (_options.SyntaxOptions.OctalIntegerFormat) { case IntegerFormats.NotSupported: case IntegerFormats.Double: info.ValueKind = ValueKind.Double; info.DoubleValue = num; break; case IntegerFormats.Int64: info.ValueKind = ValueKind.Long; info.LongValue = num; break; default: throw ExceptionUtilities.UnexpectedValue(_options.SyntaxOptions.OctalIntegerFormat); } }