示例#1
0
        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);
                }
            }
        }
示例#2
0
#pragma warning restore IDE0079 // Remove unnecessary suppression
        private void ParseHexadecimalNumber(ref TokenInfo info)
        {
            _builder.Clear();
            ConsumeHexDigits();
            var isHexFloat = false;

            if (TextWindow.PeekChar() == '.')
            {
                TextWindow.AdvanceChar();
                isHexFloat = true;
                _builder.Append('.');
                ConsumeHexDigits();
            }

            if (CharUtils.AsciiLowerCase(TextWindow.PeekChar()) == 'p')
            {
                TextWindow.AdvanceChar();
                isHexFloat = true;
                _builder.Append('p');
                if (TextWindow.PeekChar() is '+' or '-')
                {
                    _builder.Append(TextWindow.NextChar());
                }
                ConsumeDecimalDigits(_builder);
            }

            var(isUnsignedLong, isSignedLong, isComplex) = (false, false, false);

            if (TextWindow.AdvanceIfMatches("ull", true))
            {
                if (isHexFloat)
                {
                    AddError(ErrorCode.ERR_LuajitSuffixInFloat);
                }
                else
                {
                    isUnsignedLong = true;
                }
            }
            else if (TextWindow.AdvanceIfMatches("ll", true))
            {
                if (isHexFloat)
                {
                    AddError(ErrorCode.ERR_LuajitSuffixInFloat);
                }
                else
                {
                    isSignedLong = true;
                }
            }
            else if (TextWindow.AdvanceIfMatches("i", true))
            {
                isComplex = true;
            }

            info.Text = TextWindow.GetText(intern: true);
            if (!_options.SyntaxOptions.AcceptUnderscoreInNumberLiterals && info.Text.IndexOf('_') >= 0)
            {
                AddError(ErrorCode.ERR_UnderscoreInNumericLiteralNotSupportedInVersion);
            }
            if (!Options.SyntaxOptions.AcceptLuaJITNumberSuffixes && (isUnsignedLong || isSignedLong || isComplex))
            {
                AddError(ErrorCode.ERR_NumberSuffixNotSupportedInVersion);
            }

            if (isUnsignedLong)
            {
                if (!ulong.TryParse(TextWindow.Intern(_builder), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var result))
                {
                    AddError(ErrorCode.ERR_NumericLiteralTooLarge);
                }

                info.ValueKind  = ValueKind.ULong;
                info.ULongValue = result;
            }
            else if (isSignedLong)
            {
                if (!long.TryParse(TextWindow.Intern(_builder), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var result))
                {
                    AddError(ErrorCode.ERR_NumericLiteralTooLarge);
                }

                info.ValueKind = ValueKind.Long;
                info.LongValue = result;
            }
            else if (isComplex)
            {
                var result = 0d;
                try
                {
                    result = HexFloat.DoubleFromHexString(TextWindow.Intern(_builder));
                }
                catch (OverflowException)
                {
                    AddError(ErrorCode.ERR_DoubleOverflow);
                }

                info.ValueKind    = ValueKind.Complex;
                info.ComplexValue = new Complex(0, result);
            }
            else if (isHexFloat || _options.SyntaxOptions.HexIntegerFormat == IntegerFormats.NotSupported)
            {
                if (!_options.SyntaxOptions.AcceptHexFloatLiterals)
                {
                    AddError(ErrorCode.ERR_HexFloatLiteralNotSupportedInVersion);
                }

                var result = 0d;
                try
                {
                    result = HexFloat.DoubleFromHexString(TextWindow.Intern(_builder));
                }
                catch (OverflowException)
                {
                    AddError(ErrorCode.ERR_DoubleOverflow);
                }
                info.ValueKind   = ValueKind.Double;
                info.DoubleValue = result;
            }
            else
            {
                if (!long.TryParse(TextWindow.Intern(_builder), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var result))
                {
                    AddError(ErrorCode.ERR_NumericLiteralTooLarge);
                }
                switch (_options.SyntaxOptions.HexIntegerFormat)
                {
                case IntegerFormats.Double:
                    info.ValueKind   = ValueKind.Double;
                    info.DoubleValue = result;
                    break;

                case IntegerFormats.Int64:
                    info.ValueKind = ValueKind.Long;
                    info.LongValue = result;
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(_options.SyntaxOptions.HexIntegerFormat);
                }
            }
        }