コード例 #1
0
ファイル: ParseContext.cs プロジェクト: yscorecore/ys.knife
        public (bool, int) TryParseUnsignInt32()
        {
            int startIndex = Index;

            while (NotEnd() && char.IsDigit(Current()))
            {
                Index++;
            }
            if (Index > startIndex)
            {
                string numText = Text.Substring(startIndex, Index - startIndex);
                try
                {
                    return(true, int.Parse(numText));
                }
                catch (Exception ex)
                {
                    throw ParseErrors.InvalidNumberValue(this, numText, ex);
                }
            }
            else
            {
                return(false, 0);
            }
        }
コード例 #2
0
ファイル: ParseContext.cs プロジェクト: yscorecore/ys.knife
        public static (bool, object) TryParseValue(this ParseContext context)
        {
            var originIndex = context.Index;

            context.SkipWhiteSpace();
            if (context.End())
            {
                context.Index = originIndex;
                return(false, null);
            }
            var current = context.Current();

            if (current == '\"')
            {
                //string
                return(true, ParseStringValue(context));
            }
            else if (char.IsLetter(current))
            {
                //keyword eg
                string name = ParseName(context);
                if (KeyWordValues.TryGetValue(name, out var val))
                {
                    return(true, val);
                }
                else
                {
                    context.Index = originIndex;
                    return(false, null);
                }
            }
            else if (IsNumberStartChar(current, context))
            {
                //number
                return(true, ParseNumberValue(context));
            }
            else if (current == '[')
            {
                return(true, ParseArrayValue(context));
                //array
            }
            return(false, null);


            string ParseStringValue(ParseContext context)
            {
                // skip start
                context.Index++;
                bool lastIsEscapeChar = false;
                var  startIndex       = context.Index;

                while (context.NotEnd())
                {
                    if (lastIsEscapeChar)
                    {
                        lastIsEscapeChar = false;
                        context.Index++;
                        continue;
                    }
                    else
                    {
                        var current = context.Current();
                        if (current == '\"')
                        {
                            break;
                        }
                        lastIsEscapeChar = IsEscapeChar(current);
                        context.Index++;
                    }
                }
                string origin = context.Text.Substring(startIndex, context.Index - startIndex);

                // skip end
                context.Index++;
                try
                {
                    return(Regex.Unescape(origin));
                }
                catch (Exception ex)
                {
                    throw ParseErrors.InvalidStringValue(context, origin, ex);
                }
            }

            object ParseNumberValue(ParseContext context)
            {
                int  startIndex = context.Index;
                bool hasDecimsl = context.Current() == context.NumberDecimal;
                bool hasDigit   = char.IsDigit(context.Current());

                // skip first char
                context.Index++;
                while (context.NotEnd())
                {
                    var current = context.Current();
                    if (char.IsDigit(current))
                    {
                        hasDigit = true;
                        context.Index++;
                    }
                    else if (current == context.NumberGroupSeparator)
                    {
                        if (hasDecimsl)
                        {
                            throw ParseErrors.InvalidValue(context);
                        }
                        context.Index++;
                    }
                    else if (current == context.NumberDecimal)
                    {
                        if (hasDecimsl)
                        {
                            throw ParseErrors.InvalidValue(context);
                        }
                        else
                        {
                            hasDecimsl = true;
                        }
                        context.Index++;
                    }
                    else
                    {
                        break;
                    }
                }
                if (!hasDigit)
                {
                    throw ParseErrors.InvalidValue(context);
                }
                var numString = context.Text.Substring(startIndex, context.Index - startIndex);

                try
                {
                    if (hasDecimsl)
                    {
                        return(double.Parse(numString.Replace(context.NumberGroupSeparator.ToString(), string.Empty), NumberStyles.Any, context.CurrentCulture));
                    }
                    else
                    {
                        return(int.Parse(numString.Replace(context.NumberGroupSeparator.ToString(), string.Empty), NumberStyles.Any, context.CurrentCulture));
                    }
                }
                catch (Exception ex)
                {
                    throw ParseErrors.InvalidNumberValue(context, numString, ex);
                }
            }

            object ParseArrayValue(ParseContext context)
            {
                // skip start [
                List <object> datas = new List <object>();

                context.Index++;
                while (context.NotEnd())
                {
                    context.SkipWhiteSpace();
                    var current = context.Current();
                    if (current == ']')
                    {
                        context.Index++;
                        break;
                    }
                    datas.Add(ParseValue(context, false));
                    context.SkipWhiteSpace();
                    if (context.Current() == ',')
                    {
                        context.Index++;
                    }
                }
                return(datas.ToArray());
            }

            object ParseKeywordValue(ParseContext context)
            {
                int startIndex = context.Index;

                while (context.NotEnd() && IsValidNameChar(context.Current()))
                {
                    context.Index++;
                }
                string keyWord = context.Text.Substring(startIndex, context.Index - startIndex);

                if (KeyWordValues.TryGetValue(keyWord, out object value))
                {
                    return(value);
                }
                else
                {
                    throw ParseErrors.InvalidKeywordValue(context, keyWord);
                }
            }

            object ParseValue(ParseContext context, bool parseArray = true)
            {
                context.SkipWhiteSpace();
                var current = context.Current();

                if (current == '\"')
                {
                    //string
                    return(ParseStringValue(context));
                }
                else if (char.IsLetter(current))
                {
                    //keyword
                    return(ParseKeywordValue(context));
                }
                else if (IsNumberStartChar(current, context))
                {
                    //number
                    return(ParseNumberValue(context));
                }
                else if (parseArray && current == '[')
                {
                    return(ParseArrayValue(context));
                    //array
                }
                else
                {
                    throw ParseErrors.InvalidValue(context);
                }
            }
        }