Пример #1
0
        private bool QuickConvertToInt32(CompoundTokenDetails details, ParsingContext context)
        {
            int radix = GetRadix(details);

            if (radix == 10 && details.Body.Length > 10)
            {
                return(false);                                      //10 digits is maximum for int32; int32.MaxValue = 2 147 483 647
            }
            try {
                //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
                int iValue = 0;
                if (radix == 10)
                {
                    iValue = Convert.ToInt32(details.Body, context.Culture);
                }
                else
                {
                    iValue = Convert.ToInt32(details.Body, radix);
                }
                details.Value = iValue;
                return(true);
            } catch {
                return(false);
            }
        }//method
Пример #2
0
        }//method

        private void AssignTypeCodes(CompoundTokenDetails details)
        {
            //Type could be assigned when we read suffix; if so, just exit
            if (details.TypeCodes != null)
            {
                return;
            }
            //Decide on float types
            var hasDot  = details.IsSet((short)(NumberFlagsInternal.HasDot));
            var hasExp  = details.IsSet((short)(NumberFlagsInternal.HasExp));
            var isFloat = (hasDot || hasExp);

            if (!isFloat)
            {
                details.TypeCodes = DefaultIntTypes;
                return;
            }
            //so we have a float. If we have exponent symbol then use it to select type
            if (hasExp)
            {
                TypeCode code;
                if (_exponentsTable.TryGetValue(details.ExponentSymbol[0], out code))
                {
                    details.TypeCodes = new TypeCode[] { code };
                    return;
                }
            }//if hasExp
            //Finally assign default float type
            details.TypeCodes = new TypeCode[] { DefaultFloatType };
        }
Пример #3
0
        protected virtual void ReadPrefix(ISourceStream source, CompoundTokenDetails details)
        {
            if (!_prefixesFirsts.Contains(source.PreviewChar))
            {
                return;
            }
            var comparisonType = CaseSensitivePrefixesSuffixes ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

            foreach (string pfx in Prefixes)
            {
                // Prefixes are usually case insensitive, even if language is case-sensitive. So we cannot use source.MatchSymbol here,
                // we need case-specific comparison
                if (string.Compare(source.Text, source.PreviewPosition, pfx, 0, pfx.Length, comparisonType) != 0)
                {
                    continue;
                }
                //We found prefix
                details.Prefix          = pfx;
                source.PreviewPosition += pfx.Length;
                //Set flag from prefix
                short pfxFlags;
                if (!string.IsNullOrEmpty(details.Prefix) && PrefixFlags.TryGetValue(details.Prefix, out pfxFlags))
                {
                    details.Flags |= (short)pfxFlags;
                }
                return;
            } //foreach
        }     //method
Пример #4
0
        }//method

        private bool TryConvertToLong(CompoundTokenDetails details, bool useULong, ParsingContext context)
        {
            try {
                int radix = GetRadix(details);
                //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
                if (radix == 10)
                {
                    if (useULong)
                    {
                        details.Value = Convert.ToUInt64(details.Body, context.Culture);
                    }
                    else
                    {
                        details.Value = Convert.ToInt64(details.Body, context.Culture);
                    }
                }
                else
                if (useULong)
                {
                    details.Value = Convert.ToUInt64(details.Body, radix);
                }
                else
                {
                    details.Value = Convert.ToInt64(details.Body, radix);
                }
                return(true);
            } catch (OverflowException) {
                details.Error = string.Format(Resources.ErrCannotConvertValueToType, details.Value, TypeCode.Int64.ToString());
                return(false);
            }
        }
Пример #5
0
        protected virtual void ReadSuffix(ISourceStream source, CompoundTokenDetails details)
        {
            if (!_suffixesFirsts.Contains(source.PreviewChar))
            {
                return;
            }
            var comparisonType = CaseSensitivePrefixesSuffixes ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase;

            foreach (string sfx in Suffixes)
            {
                //Suffixes are usually case insensitive, even if language is case-sensitive. So we cannot use source.MatchSymbol here,
                // we need case-specific comparison
                if (string.Compare(source.GetText(source.PreviewPosition, sfx.Length), 0, sfx, 0, sfx.Length, comparisonType) != 0)
                {
                    continue;
                }
                //We found suffix
                details.Suffix          = sfx;
                source.PreviewPosition += sfx.Length;
                //Set TypeCode from suffix
                TypeCode[] codes;
                if (!string.IsNullOrEmpty(details.Suffix) && SuffixTypeCodes.TryGetValue(details.Suffix, out codes))
                {
                    details.TypeCodes = codes;
                }
                return;
            } //foreach
        }     //method
        }//method

        private char ReadUnicodeEscape(ISourceStream source, CompoundTokenDetails details)
        {
            //Position is currently at "\" symbol
            source.PreviewPosition++; //move to U/u char
            int len;

            switch (source.PreviewChar)
            {
            case 'u': len = 4; break;

            case 'U': len = 8; break;

            default:
                details.Error = O2_Misc_Microsoft_MPL_Libs.Irony_Parser.Resources.ErrInvEscSymbol; // "Invalid escape symbol, expected 'u' or 'U' only."
                return('\0');
            }
            if (source.PreviewPosition + len > source.Text.Length)
            {
                details.Error = O2_Misc_Microsoft_MPL_Libs.Irony_Parser.Resources.ErrInvEscSeq; // "Invalid escape sequence";
                return('\0');
            }
            source.PreviewPosition++; //move to the first digit
            string digits = source.Text.Substring(source.PreviewPosition, len);
            char   result = (char)Convert.ToUInt32(digits, 16);

            source.PreviewPosition += len;
            details.Flags          |= (int)IdFlagsInternal.HasEscapes;
            return(result);
        }
Пример #7
0
        private char ReadUnicodeEscape(ISourceStream source, CompoundTokenDetails details)
        {
            //Position is currently at "\" symbol
            source.Position++; //move to U/u char
            int len;

            switch (source.CurrentChar)
            {
            case 'u': len = 4; break;

            case 'U': len = 8; break;

            default:
                details.Error = "Invalid escape symbol, expected 'u' or 'U' only.";
                return('\0');
            }
            if (source.Position + len > source.Text.Length)
            {
                details.Error = "Invalid escape symbol";
                return('\0');
            }
            source.Position++; //move to the first digit
            string digits = source.Text.Substring(source.Position, len);
            char   result = (char)Convert.ToUInt32(digits, 16);

            source.Position += len;
            details.Flags   |= (int)IdFlags.HasEscapes;
            return(result);
        }
        public override Token TryMatch(CompilerContext context, ISourceStream source)
        {
            Token token;

            //Try quick parse first, but only if we're not continuing
            if (context.ScannerState.Value == 0)
            {
                token = QuickParse(context, source);
                if (token != null)
                {
                    return(token);
                }
                source.Position = source.TokenStart.Position; //revert the position
            }

            CompoundTokenDetails details = new CompoundTokenDetails();

            InitDetails(context, details);

            if (context.ScannerState.Value == 0)
            {
                ReadPrefix(source, details);
            }
            if (!ReadBody(source, details))
            {
                return(null);
            }
            if (details.Error != null)
            {
                return(context.CreateErrorTokenAndReportError(source.TokenStart, source.CurrentChar.ToString(), details.Error));
            }
            if (details.IsPartial)
            {
                details.Value = details.Body;
            }
            else
            {
                ReadSuffix(source, details);

                if (!ConvertValue(details))
                {
                    return(context.CreateErrorTokenAndReportError(source.TokenStart, source.CurrentChar.ToString(), "Failed to convert the value: " + details.Error));
                }
            }
            token = CreateToken(context, source, details);

            if (details.IsPartial)
            {
                //Save terminal state so we can continue
                context.ScannerState.TokenSubType  = (byte)details.SubTypeIndex;
                context.ScannerState.TerminalFlags = (short)details.Flags;
                context.ScannerState.TerminalIndex = this.MultilineIndex;
            }
            else
            {
                context.ScannerState.Value = 0;
            }
            return(token);
        }
Пример #9
0
        }//method

        protected override void ReadSuffix(ISourceStream source, CompoundTokenDetails details)
        {
            base.ReadSuffix(source, details);
            if (string.IsNullOrEmpty(details.Suffix))
            {
                details.TypeCodes = details.IsSet((short)(NumberFlags.HasDot | NumberFlags.HasExp)) ? _defaultFloatTypes : DefaultIntTypes;
            }
        }
        private void ProcessPartialBody(ISourceStream source, CompoundTokenDetails details)
        {
            int from = source.PreviewPosition;

            source.PreviewPosition = source.Text.Length;
            details.Body           = source.Text.Substring(from, source.PreviewPosition - from);
            details.IsPartial      = true;
        }
Пример #11
0
        private bool ConvertToBigInteger(CompoundTokenDetails details)
        {
            //ignore leading zeros and sign
            details.Body = details.Body.TrimStart('+').TrimStart('-').TrimStart('0');
            if (string.IsNullOrEmpty(details.Body))
            {
                details.Body = "0";
            }
            int bodyLength   = details.Body.Length;
            int radix        = GetRadix(details);
            int wordLength   = GetSafeWordLength(details);
            int sectionCount = GetSectionCount(bodyLength, wordLength);

            ulong[] numberSections = new ulong[sectionCount]; //big endian

            try
            {
                int startIndex = details.Body.Length - wordLength;
                for (int sectionIndex = sectionCount - 1; sectionIndex >= 0; sectionIndex--)
                {
                    if (startIndex < 0)
                    {
                        wordLength += startIndex;
                        startIndex  = 0;
                    }
                    //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
                    if (radix == 10)
                    {
                        numberSections[sectionIndex] = Convert.ToUInt64(details.Body.Substring(startIndex, wordLength));
                    }
                    else
                    {
                        numberSections[sectionIndex] = Convert.ToUInt64(details.Body.Substring(startIndex, wordLength), radix);
                    }

                    startIndex -= wordLength;
                }
            }
            catch
            {
                details.Error = Resources.ErrInvNumber;//  "Invalid number.";
                return(false);
            }
            //produce big integer
            ulong      safeWordRadix   = GetSafeWordRadix(details);
            BigInteger bigIntegerValue = numberSections[0];

            for (int i = 1; i < sectionCount; i++)
            {
                bigIntegerValue = checked (bigIntegerValue * safeWordRadix + numberSections[i]);
            }
            if (details.Sign == "-")
            {
                bigIntegerValue = -bigIntegerValue;
            }
            details.Value = bigIntegerValue;
            return(true);
        }
Пример #12
0
 protected override void ReadPrefix(ISourceStream source, CompoundTokenDetails details)
 {
     //check that is not a  0 followed by dot;
     //this may happen in Python for number "0.123" - we can mistakenly take "0" as octal prefix
     if (source.PreviewChar == '0' && source.NextPreviewChar == '.')
     {
         return;
     }
     base.ReadPrefix(source, details);
 }//method
 protected override bool ReadBody(ISourceStream source, CompoundTokenDetails details)
 {
     if (!details.PartialContinues)
     {
         if (!ReadStartSymbol(source, details))
         {
             return(false);
         }
     }
     return(CompleteReadBody(source, details));
 }
Пример #14
0
        protected override bool ReadBody(ISourceStream source, CompoundTokenDetails details)
        {
            int      start        = source.PreviewPosition;
            bool     allowEscapes = details.IsSet((short)IdOptions.AllowsEscapes);
            CharList outputChars  = new CharList();

            while (!source.EOF())
            {
                char current = source.PreviewChar;
                if (Grammar.IsWhitespaceOrDelimiter(current))
                {
                    break;
                }
                if (allowEscapes && current == this.EscapeChar)
                {
                    current = ReadUnicodeEscape(source, details);
                    //We  need to back off the position. ReadUnicodeEscape sets the position to symbol right after escape digits.
                    //This is the char that we should process in next iteration, so we must backup one char, to pretend the escaped
                    // char is at position of last digit of escape sequence.
                    source.PreviewPosition--;
                    if (details.Error != null)
                    {
                        return(false);
                    }
                }
                //Check if current character is OK
                if (!CharOk(current, source.PreviewPosition == start))
                {
                    break;
                }
                //Check if we need to skip this char
#if NETSTANDARD
                UnicodeCategory currCat = CharUnicodeInfo.GetUnicodeCategory(current);
#else
                UnicodeCategory currCat = char.GetUnicodeCategory(current); //I know, it suxx, we do it twice, fix it later
#endif
                if (!this.CharsToRemoveCategories.Contains(currCat))
                {
                    outputChars.Add(current); //add it to output (identifier)
                }
                source.PreviewPosition++;
            }//while
            if (outputChars.Count == 0)
            {
                return(false);
            }
            //Convert collected chars to string
            details.Body = new string(outputChars.ToArray());
            if (!CheckCaseRestriction(details.Body))
            {
                return(false);
            }
            return(!string.IsNullOrEmpty(details.Body));
        }
 protected override bool ConvertValue(CompoundTokenDetails details)
 {
     if (details.IsSet((short)IdOptions.NameIncludesPrefix))
     {
         details.Value = details.Prefix + details.Body;
     }
     else
     {
         details.Value = details.Body;
     }
     return(true);
 }
Пример #16
0
        protected override void InitDetails(ParsingContext context, CompoundTokenDetails details)
        {
            base.InitDetails(context, details);
            if (context.VsLineScanState.Value == 0)
            {
                return;
            }
            //we are continuing partial string on the next line
            details.Flags        = context.VsLineScanState.TerminalFlags;
            details.SubTypeIndex = context.VsLineScanState.TokenSubType;
            var stringInfo = _subTypes[context.VsLineScanState.TokenSubType];

            details.StartSymbol = stringInfo.Start;
        }
Пример #17
0
 private int GetRadix(CompoundTokenDetails details)
 {
     if (details.IsSet((short)NumberOptions.Hex))
     {
         return(16);
     }
     if (details.IsSet((short)NumberOptions.Octal))
     {
         return(8);
     }
     if (details.IsSet((short)NumberOptions.Binary))
     {
         return(2);
     }
     return(10);
 }
Пример #18
0
 private string GetDigits(CompoundTokenDetails details)
 {
     if (details.IsSet((short)NumberOptions.Hex))
     {
         return(Strings.HexDigits);
     }
     if (details.IsSet((short)NumberOptions.Octal))
     {
         return(Strings.OctalDigits);
     }
     if (details.IsSet((short)NumberOptions.Binary))
     {
         return(Strings.BinaryDigits);
     }
     return(Strings.DecimalDigits);
 }
Пример #19
0
 private int GetSafeWordLength(CompoundTokenDetails details)
 {
     if (details.IsSet((short)NumberOptions.Hex))
     {
         return(15);
     }
     if (details.IsSet((short)NumberOptions.Octal))
     {
         return(21); //maxWordLength 22
     }
     if (details.IsSet((short)NumberOptions.Binary))
     {
         return(63);
     }
     return(19); //maxWordLength 20
 }
Пример #20
0
 //radix^safeWordLength
 private ulong GetSafeWordRadix(CompoundTokenDetails details)
 {
     if (details.IsSet((short)NumberOptions.Hex))
     {
         return(1152921504606846976);
     }
     if (details.IsSet((short)NumberOptions.Octal))
     {
         return(9223372036854775808);
     }
     if (details.IsSet((short)NumberOptions.Binary))
     {
         return(9223372036854775808);
     }
     return(10000000000000000000);
 }
Пример #21
0
 protected override void ReadSuffix(ISourceStream source, CompoundTokenDetails details)
 {
     base.ReadSuffix(source, details);
     //"char" type can be identified by suffix (like VB where c suffix identifies char)
     // in this case we have details.TypeCodes[0] == char  and we need to set the IsChar flag
     if (details.TypeCodes != null && details.TypeCodes[0] == TypeCode.Char)
     {
         details.Flags |= (int)StringOptions.IsChar;
     }
     else if (details.IsSet((short)StringOptions.IsChar))
     {
         //we may have IsChar flag set (from startEndSymbol, like in c# single quote identifies char)
         // in this case set type code
         details.TypeCodes = new[] { TypeCode.Char };
     }
 }
Пример #22
0
 private bool TryCastToIntegerType(TypeCode typeCode, CompoundTokenDetails details)
 {
     if (details.Value == null)
     {
         return(false);
     }
     try {
         if (typeCode != TypeCode.UInt64)
         {
             details.Value = Convert.ChangeType(details.Value, typeCode, CultureInfo.InvariantCulture);
         }
         return(true);
     } catch (Exception) {
         details.Error = string.Format(O2_Misc_Microsoft_MPL_Libs.Irony_Parser.Resources.ErrCannotConvertValueToType, details.Value, typeCode.ToString());
         return(false);
     }
 }//method
Пример #23
0
        //Extract the string content from lexeme, adjusts the escaped and double-end symbols
        protected override bool ConvertValue(CompoundTokenDetails details)
        {
            var value         = details.Body;
            var escapeEnabled = !details.IsSet((short)HereDocOptions.NoEscapes);

            //Fix all escapes
            if (escapeEnabled && value.IndexOf(EscapeChar) >= 0)
            {
                details.Flags |= (int)StringFlagsInternal.HasEscapes;
                var arr        = value.Split(EscapeChar);
                var ignoreNext = false;
                //we skip the 0 element as it is not preceeded by "\"
                for (var i = 1; i < arr.Length; i++)
                {
                    if (ignoreNext)
                    {
                        ignoreNext = false;
                        continue;
                    }
                    var s = arr[i];
                    if (string.IsNullOrEmpty(s))
                    {
                        //it is "\\" - escaped escape symbol.
                        arr[i]     = @"\";
                        ignoreNext = true;
                        continue;
                    }
                    //The char is being escaped is the first one; replace it with char in Escapes table
                    var first = s[0];
                    if (Escapes.TryGetValue(first, out char newFirst))
                    {
                        arr[i] = newFirst + s.Substring(1);
                    }
                    else
                    {
                        arr[i] = HandleSpecialEscape(arr[i], details);
                    }
                }
                value = string.Join(string.Empty, arr);
            }

            details.TypeCodes = new[] { TypeCode.String };
            details.Value     = value;

            return(true);
        }
Пример #24
0
 private bool TryCastToIntegerType(TypeCode typeCode, CompoundTokenDetails details, ParsingContext context)
 {
     if (details.Value == null)
     {
         return(false);
     }
     try {
         if (typeCode != TypeCode.UInt64)
         {
             details.Value = Convert.ChangeType(details.Value, typeCode, context.Culture);
         }
         return(true);
     } catch (Exception) {
         details.Error = string.Format(Resources.ErrCannotConvertValueToType, details.Value, typeCode.ToString());
         return(false);
     }
 }//method
Пример #25
0
 private bool TryCastToIntegerType(TypeCode typeCode, CompoundTokenDetails details)
 {
     if (details.Value == null)
     {
         return(false);
     }
     try {
         if (typeCode != TypeCode.UInt64)
         {
             details.Value = Convert.ChangeType(details.Value, typeCode, CultureInfo.InvariantCulture);
         }
         return(true);
     } catch (Exception e) {
         Trace.WriteLine("Error converting to integer: text=[" + details.Body + "], type=" + typeCode + ", error: " + e.Message);
         return(false);
     }
 }//method
Пример #26
0
        protected override string HandleSpecialEscape(string segment, CompoundTokenDetails details)
        {
            if (string.IsNullOrEmpty(segment))
            {
                return(string.Empty);
            }
            char first = segment[0];

            switch (first)
            {
            case 'a':
            case 'b':
            case 'f':
            case 'n':
            case 'r':
            case 't':
            case 'v':
            case '\\':
            case '"':
            case '\'':
                break;

            case '0':
            case '1':
            case '2':
            {
                bool success = false;
                if (segment.Length >= 3)
                {
                    //Verify that a numeric escape is 3 characters
                    string value = segment.Substring(0, 3);
                    int    dummy = 0;
                    success = Int32.TryParse(value, out dummy);
                }

                if (!success)
                {
                    details.Error = "Invalid escape sequence: \000 must be a valid number.";
                }
            }
            break;
            }
            details.Error = "Invalid escape sequence: \\" + segment;
            return(segment);
        }
Пример #27
0
        }//method

        private bool TryConvertToUlong(CompoundTokenDetails details)
        {
            try {
                int radix = GetRadix(details);
                //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
                if (radix == 10)
                {
                    details.Value = Convert.ToUInt64(details.Body, CultureInfo.InvariantCulture);
                }
                else
                {
                    details.Value = Convert.ToUInt64(details.Body, radix);
                }
                return(true);
            } catch (OverflowException) {
                return(false);
            }
        }
Пример #28
0
        protected override bool ConvertValue(CompoundTokenDetails details, ParsingContext context)
        {
            if (base.ConvertValue(details, context) || details.Error != null)
            {
                return(true);
            }

            switch (details.TypeCodes[0])
            {
            case TypeCode.Double:
                if (QuickConvertToDouble(details))
                {
                    return(true);
                }
                break;
            }

            return(false);
        }
Пример #29
0
        }//method

        private bool QuickConvertToDouble(CompoundTokenDetails details)
        {
            if (details.IsSet((short)(NumberFlags.Binary | NumberFlags.Octal | NumberFlags.Hex | NumberFlags.HasExp)))
            {
                return(false);
            }
            if (DecimalSeparator != '.')
            {
                return(false);
            }
            double dvalue;

            if (!double.TryParse(details.Body, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out dvalue))
            {
                return(false);
            }
            details.Value = dvalue;
            return(true);
        }
Пример #30
0
        }//method

        private bool TryConvertToUlong(CompoundTokenDetails details)
        {
            try {
                int radix = GetRadix(details);
                //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
                if (radix == 10)
                {
                    details.Value = Convert.ToUInt64(details.Body, CultureInfo.InvariantCulture);
                }
                else
                {
                    details.Value = Convert.ToUInt64(details.Body, radix);
                }
                return(true);
            } catch (OverflowException) {
                details.Error = string.Format(O2_Misc_Microsoft_MPL_Libs.Irony_Parser.Resources.ErrCannotConvertValueToType, details.Value, TypeCode.UInt64.ToString());
                return(false);
            }
        }
Пример #31
0
        protected override string HandleSpecialEscape(string segment, CompoundTokenDetails details)
        {
            if (string.IsNullOrEmpty(segment)) return string.Empty;
            char first = segment[0];
            switch (first)
            {
                case 'a':
                case 'b':
                case 'f':
                case 'n':
                case 'r':
                case 't':
                case 'v':
                case '\\':
                case '"':
                case '\'':
                    break;

                case '0':
                case '1':
                case '2':
                    {
                        bool success = false;
                        if (segment.Length >=3)
                        {
                            //Verify that a numeric escape is 3 characters
                            string value = segment.Substring(0, 3);
                            int dummy = 0;
                            success = Int32.TryParse(value, out dummy);

                        }

                        if(!success)
                            details.Error = "Invalid escape sequence: \000 must be a valid number.";

                    }
                    break;
            }
            details.Error = "Invalid escape sequence: \\" + segment;
            return segment;
        }
Пример #32
0
    }//method

    protected override void ReadSuffix(ISourceStream source, CompoundTokenDetails details) {
      base.ReadSuffix(source, details);
      if (string.IsNullOrEmpty(details.Suffix))
        details.TypeCodes = details.IsSet((short) (NumberFlags.HasDot | NumberFlags.HasExp)) ? _defaultFloatTypes : DefaultIntTypes;
    }
Пример #33
0
    private bool ConvertToBigInteger(CompoundTokenDetails details) {
      //ignore leading zeros and sign
      details.Body = details.Body.TrimStart('+').TrimStart('-').TrimStart('0');
      int bodyLength = details.Body.Length;
      int radix = GetRadix(details);
      int wordLength = GetSafeWordLength(details);
      int sectionCount = GetSectionCount(bodyLength, wordLength);
      ulong[] numberSections = new ulong[sectionCount]; //big endian

      try {
        int startIndex = details.Body.Length - wordLength;
        for (int sectionIndex = sectionCount - 1; sectionIndex >= 0; sectionIndex--) {
          if (startIndex < 0) {
            wordLength += startIndex;
            startIndex = 0;
          }
          //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
          if (radix == 10)
            numberSections[sectionIndex] = Convert.ToUInt64(details.Body.Substring(startIndex, wordLength));
          else
            numberSections[sectionIndex] = Convert.ToUInt64(details.Body.Substring(startIndex, wordLength), radix);

          startIndex -= wordLength;
        }
      } catch {
        details.Error = "Invalid number.";
        return false;
      }
      //produce big integer
      ulong safeWordRadix = GetSafeWordRadix(details);
      BigInteger bigIntegerValue = numberSections[0];
      for (int i = 1; i < sectionCount; i++)
        bigIntegerValue = checked(bigIntegerValue * safeWordRadix + numberSections[i]);
      if (details.Sign == "-")
        bigIntegerValue = -bigIntegerValue;
      details.Value = bigIntegerValue;
      return true;
    }
Пример #34
0
 protected override void InitDetails(CompilerContext context, CompoundTokenDetails details) {
   base.InitDetails(context, details);
   details.Flags = (short) this.Flags;
 }
Пример #35
0
 protected override void ReadPrefix(ISourceStream source, CompoundTokenDetails details) {
   //check that is not a  0 followed by dot; 
   //this may happen in Python for number "0.123" - we can mistakenly take "0" as octal prefix
   if (source.CurrentChar == '0' && source.NextChar == '.') return;
   base.ReadPrefix(source, details);
 }//method
Пример #36
0
 protected static bool FlagIsSet(CompoundTokenDetails details, NumberFlags flag)
 {
     return (details.Flags & (int) flag ) != 0;
 }
Пример #37
0
 private int GetRadix(CompoundTokenDetails details) {
   if (details.IsSet((short)NumberFlags.Hex))
     return 16;
   if (details.IsSet((short)NumberFlags.Octal))
     return 8;
   if (details.IsSet((short)NumberFlags.Binary))
     return 2;
   return 10;
 }
Пример #38
0
 private string GetDigits(CompoundTokenDetails details)
 {
     if (FlagIsSet(details, NumberFlags.Hex))
     return TextUtils.HexDigits;
       if (FlagIsSet(details, NumberFlags.Octal))
     return TextUtils.OctalDigits;
       if (FlagIsSet(details, NumberFlags.Binary))
     return TextUtils.BinaryDigits;
       return TextUtils.DecimalDigits;
 }
Пример #39
0
    private bool ConvertToFloat(TypeCode typeCode, CompoundTokenDetails details) {
      //only decimal numbers can be fractions
      if (details.IsSet((short)(NumberFlags.Binary | NumberFlags.Octal | NumberFlags.Hex))) {
        details.Error = "Invalid number.";
        return false;
      }
      string body = details.Body;
      //Some languages allow exp symbols other than E. Check if it is the case, and change it to E
      // - otherwise .NET conversion methods may fail
      if (details.IsSet((short)NumberFlags.HasExp) && details.ExponentSymbol.ToUpper() != "E")
        body = body.Replace(details.ExponentSymbol, "E");

      //'.' decimal seperator required by invariant culture
      if (details.IsSet((short)NumberFlags.HasDot) && DecimalSeparator != '.')
        body = body.Replace(DecimalSeparator, '.');

      switch (typeCode) {
        case TypeCode.Double:
        case TypeCodeImaginary:
          double dValue;
          if (!Double.TryParse(body, NumberStyles.Float, CultureInfo.InvariantCulture, out dValue)) return false;
          if (typeCode == TypeCodeImaginary)
            details.Value = new Complex64(0, dValue);
          else
            details.Value = dValue; 
          return true;
        case TypeCode.Single:
          float fValue;
          if (!Single.TryParse(body, NumberStyles.Float, CultureInfo.InvariantCulture, out fValue)) return false;
          details.Value = fValue;
          return true; 
        case TypeCode.Decimal:
          decimal decValue;
          if (!Decimal.TryParse(body, NumberStyles.Float, CultureInfo.InvariantCulture, out decValue)) return false;
          details.Value = decValue;
          return true;  
      }//switch
      return false; 
    }
Пример #40
0
    protected override bool ReadBody(ISourceStream source, CompoundTokenDetails details) {
      //remember start - it may be different from source.TokenStart, we may have skipped prefix
      int start = source.Position;
      char current = source.CurrentChar;
      if (current == '-' || current == '+') {
        details.Sign = current.ToString();
        source.Position++;
      }
      //Figure out digits set
      string digits = GetDigits(details);
      bool isDecimal = !details.IsSet((short) (NumberFlags.Binary | NumberFlags.Octal | NumberFlags.Hex));
      bool allowFloat = !IsSet(NumberFlags.IntOnly);
      bool foundDigits = false;

      while (!source.EOF()) {
        current = source.CurrentChar;
        //1. If it is a digit, just continue going
        if (digits.IndexOf(current) >= 0) {
          source.Position++;
          foundDigits = true; 
          continue;
        }
        //2. Check if it is a dot in float number
        bool isDot = current == DecimalSeparator;
        if (allowFloat && isDot) {
          //If we had seen already a dot or exponent, don't accept this one;
          bool hasDotOrExp = details.IsSet((short) (NumberFlags.HasDot | NumberFlags.HasExp));
          if (hasDotOrExp) break; //from while loop
          //In python number literals (NumberAllowPointFloat) a point can be the first and last character,
          //We accept dot only if it is followed by a digit
          if (digits.IndexOf(source.NextChar) < 0 && !IsSet(NumberFlags.AllowStartEndDot))
            break; //from while loop
          details.Flags |= (int) NumberFlags.HasDot;
          source.Position++;
          continue;
        }
        //3. Check if it is int number followed by dot or exp symbol
        bool isExpSymbol = (details.ExponentSymbol == null) && ExponentSymbols.IndexOf(current) >= 0;
        if (!allowFloat && foundDigits && (isDot || isExpSymbol)) {
          //If no partial float allowed then return false - it is not integer, let float terminal recognize it as float
          if (IsSet(NumberFlags.AvoidPartialFloat)) return false;  
          //otherwise break, it is integer and we're done reading digits
          break;
        }


        //4. Only for decimals - check if it is (the first) exponent symbol
        if (allowFloat && isDecimal && isExpSymbol) {
          char next = source.NextChar;
          bool nextIsSign = next == '-' || next == '+';
          bool nextIsDigit = digits.IndexOf(next) >= 0;
          if (!nextIsSign && !nextIsDigit)
            break;  //Exponent should be followed by either sign or digit
          //ok, we've got real exponent
          details.ExponentSymbol = current.ToString(); //remember the exp char
          details.Flags |= (int) NumberFlags.HasExp;
          source.Position++;
          if (nextIsSign)
            source.Position++; //skip +/- explicitly so we don't have to deal with them on the next iteration
          continue;
        }
        //4. It is something else (not digit, not dot or exponent) - we're done
        break; //from while loop
      }//while
      int end = source.Position;
      if (!foundDigits) 
        return false; 
      details.Body = source.Text.Substring(start, end - start);
      return true;
    }
Пример #41
0
 private string GetDigits(CompoundTokenDetails details) {
   if (details.IsSet((short)NumberFlags.Hex))
     return Strings.HexDigits;
   if (details.IsSet((short)NumberFlags.Octal))
     return Strings.OctalDigits;
   if (details.IsSet((short)NumberFlags.Binary))
     return Strings.BinaryDigits;
   return Strings.DecimalDigits;
 }
Пример #42
0
    protected override bool ConvertValue(CompoundTokenDetails details) {
      if (String.IsNullOrEmpty(details.Body)) {
        details.Error = "Invalid number.";
        return false;
      }

      //Try quick paths
      switch (details.TypeCodes[0]) {
        case TypeCode.Int32: 
          if (QuickConvertToInt32(details)) return true;
          break;
        case TypeCode.Double:
          if (QuickConvertToDouble(details)) return true;
          break;
      }

      //Go full cycle
      details.Value = null;
      foreach (TypeCode typeCode in details.TypeCodes) {
        switch (typeCode) {
          case TypeCode.Single:   case TypeCode.Double:  case TypeCode.Decimal:  case TypeCodeImaginary:
            return ConvertToFloat(typeCode, details);
          case TypeCode.SByte:    case TypeCode.Byte:    case TypeCode.Int16:    case TypeCode.UInt16:
          case TypeCode.Int32:    case TypeCode.UInt32:  case TypeCode.Int64:    case TypeCode.UInt64:
            if (details.Value == null) //if it is not done yet
              TryConvertToUlong(details); //try to convert to ULong and place the result into details.Value field;
            if(TryCastToIntegerType(typeCode, details)) //now try to cast the ULong value to the target type 
              return true;
            break;
          case TypeCodeBigInt:
            if (ConvertToBigInteger(details)) return true;
            break; 
        }//switch
      }
      return false; 
    }//method
Пример #43
0
    }//method

    #endregion

    #region private utilities
    private bool QuickConvertToInt32(CompoundTokenDetails details) {
      int radix = GetRadix(details);
      if (radix == 10 && details.Body.Length > 10) return false;    //10 digits is maximum for int32; int32.MaxValue = 2 147 483 647
      try {
        //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
        int iValue = 0;
        if (radix == 10)
          iValue =  Convert.ToInt32(details.Body, CultureInfo.InvariantCulture);
        else
          iValue = Convert.ToInt32(details.Body, radix);
        details.Value = iValue;
        return true;
      } catch {
        return false;
      }
    }//method
Пример #44
0
    }//method

    private bool QuickConvertToDouble(CompoundTokenDetails details) {
      if (details.IsSet((short)(NumberFlags.Binary | NumberFlags.Octal | NumberFlags.Hex | NumberFlags.HasExp))) return false; 
      if (DecimalSeparator != '.') return false;
      double dvalue;
      if (!double.TryParse(details.Body, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out dvalue)) return false;
      details.Value = dvalue;
      return true; 
    }
Пример #45
0
 private int GetSafeWordLength(CompoundTokenDetails details) {
   if (details.IsSet((short)NumberFlags.Hex))
     return 15;
   if (details.IsSet((short)NumberFlags.Octal))
     return 21; //maxWordLength 22
   if (details.IsSet((short)NumberFlags.Binary))
     return 63;
   return 19; //maxWordLength 20
 }
Пример #46
0
 private bool TryCastToIntegerType(TypeCode typeCode, CompoundTokenDetails details) {
   if (details.Value == null) return false;
   try {
     if (typeCode != TypeCode.UInt64)
       details.Value = Convert.ChangeType(details.Value, typeCode, CultureInfo.InvariantCulture);
     return true;
   } catch (Exception e) {
     Trace.WriteLine("Error converting to integer: text=[" + details.Body + "], type=" + typeCode + ", error: " + e.Message); 
     return false;
   }
 }//method
Пример #47
0
    }//method

    private bool TryConvertToUlong(CompoundTokenDetails details) {
      try {
        int radix = GetRadix(details);
        //workaround for .Net FX bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
        if (radix == 10)
          details.Value = Convert.ToUInt64(details.Body, CultureInfo.InvariantCulture);
        else
          details.Value = Convert.ToUInt64(details.Body, radix);
        return true; 
      } catch(OverflowException) {
        return false;
      }
    }
Пример #48
0
 //radix^safeWordLength
 private ulong GetSafeWordRadix(CompoundTokenDetails details) {
   if (details.IsSet((short)NumberFlags.Hex))
     return 1152921504606846976;
   if (details.IsSet((short)NumberFlags.Octal))
     return 9223372036854775808;
   if (details.IsSet((short) NumberFlags.Binary))
     return 9223372036854775808;
   return 10000000000000000000;
 }