예제 #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
        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);
            }
        }