/// <summary>
        /// 予約語(<c>true</c>, <c>false</c>, <c>null</c>)をパースします。<see cref="Parse(JsonScanner)" />で使用されます。
        /// </summary>
        /// <param name="scanner">指定するスキャナ。</param>
        /// <returns>予約語をそのまま返します。</returns>
        private static object ParseWord(JsonScanner scanner)
        {
            if (scanner.Check(IsSmallT))
            {
                if (!scanner.CheckAdvance("true"))
                {
                    throw new ArgumentMapParseException("word -> true required", scanner.Itext.PositionInfo);
                }

                return(true);
            }

            if (scanner.Check(IsSmallF))
            {
                if (!scanner.CheckAdvance("false"))
                {
                    throw new ArgumentMapParseException("word -> false required", scanner.Itext.PositionInfo);
                }

                return(false);
            }

            if (!scanner.Check(IsSmallN))
            {
                throw new ArgumentMapParseException("word -> unexpected character", scanner.Itext.PositionInfo);
            }
            if (!scanner.CheckAdvance("null"))
            {
                throw new ArgumentMapParseException("word -> null required", scanner.Itext.PositionInfo);
            }

            return(null);
        }
        /// <summary>
        /// 配列をパースします。これは<see cref="Parse(JsonScanner)" />や一部のメソッドで使用されます。
        /// </summary>
        /// <param name="scanner">指定するスキャナ。</param>
        /// <returns>パースに成功した場合<see cref="object" />の配列を返します。 <br />
        /// 何かの配列として利用するにはその他の処理が必要です。</returns>
        private static object[] ParseArray(JsonScanner scanner)
        {
            var osList = new List <object>();

            if (!scanner.CheckAdvance(IsLeftBracket))
            {
                throw new ArgumentMapParseException("array -> left bracket required", scanner.Itext.PositionInfo);
            }

            ParseWhitespace(scanner);

            if (scanner.CheckAdvance(IsRightBracket))
            {
                return(osList.ToArray());
            }

            while (true)
            {
                osList.Add(ParseValue(scanner));

                ParseWhitespace(scanner);

                if (scanner.CheckAdvance(IsRightBracket))
                {
                    return(osList.ToArray());
                }
                if (!scanner.CheckAdvance(IsComma))
                {
                    throw new ArgumentMapParseException("array -> comma required", scanner.Itext.PositionInfo);
                }

                ParseWhitespace(scanner);
            }
        }
        /// <summary>
        /// Json値の入れ子となるオブジェクトをパースします。<see cref="Parse(JsonScanner)" />の一部で使用されます。
        /// </summary>
        /// <param name="scanner">指定するスキャナ。</param>
        /// <returns><see cref="string" />にキー値を代入してハッシュマップで返します。</returns>
        private static Dictionary <string, object> ParseObject(JsonScanner scanner)
        {
            var osDict = new Dictionary <string, object>();

            if (!scanner.CheckAdvance(IsLeftBrace))
            {
                throw new ArgumentMapParseException("object -> left brace required", scanner.Itext.PositionInfo);
            }

            ParseWhitespace(scanner);

            if (scanner.CheckAdvance(IsRightBrace))
            {
                return(osDict);
            }

            while (true)
            {
                var key = ParseString(scanner);

                if (osDict.Keys.Contains(key))
                {
                    throw new ArgumentMapParseException("object -> same key", scanner.Itext.PositionInfo);
                }

                ParseWhitespace(scanner);

                if (!scanner.CheckAdvance(IsColon))
                {
                    throw new ArgumentMapParseException("object -> colon required", scanner.Itext.PositionInfo);
                }

                ParseWhitespace(scanner);

                osDict[key] = ParseValue(scanner);

                ParseWhitespace(scanner);

                if (scanner.CheckAdvance(IsRightBrace))
                {
                    return(osDict);
                }

                if (!scanner.CheckAdvance(IsComma))
                {
                    throw new ArgumentMapParseException("object -> comma required", scanner.Itext.PositionInfo);
                }

                ParseWhitespace(scanner);
            }
        }
        /// <summary>
        /// Json文字列をパースします。これは<see cref="Parse(JsonScanner)"/>の一部で使用されます。
        /// </summary>
        /// <param name="scanner">指定するスキャナ。</param>
        /// <returns>パースに成功した場合文字列をさらに返します。</returns>
        private static string ParseString(JsonScanner scanner)
        {
            const string b = "\b";
            const string f = "\f";
            const string n = "\n";
            const string r = "\r";
            const string t = "\t";

            scanner.Empty();

            if (!scanner.CheckAdvance(IsDoubleQuote))
            {
                throw new ArgumentMapParseException("string -> double quotation mark required", scanner.Itext.PositionInfo);
            }

            while (!scanner.CheckAdvance(IsDoubleQuote))
            {
                if (scanner.CheckAdvance(IsBackslash))
                {
                    if (scanner.CheckAddAdvance(IsDoubleQuote))
                    {
                        continue;
                    }
                    if (scanner.CheckAddAdvance(IsBackslash))
                    {
                        continue;
                    }
                    if (scanner.CheckAddAdvance(IsSlash))
                    {
                        continue;
                    }
                    if (scanner.CheckAdvance(IsSmallB))
                    {
                        scanner.Add(b);
                    }
                    else if (scanner.CheckAdvance(IsSmallF))
                    {
                        scanner.Add(f);
                    }
                    else if (scanner.CheckAdvance(IsSmallN))
                    {
                        scanner.Add(n);
                    }
                    else if (scanner.CheckAdvance(IsSmallR))
                    {
                        scanner.Add(r);
                    }
                    else if (scanner.CheckAdvance(IsSmallT))
                    {
                        scanner.Add(t);
                    }
                    else if (scanner.CheckAdvance(IsSmallU))
                    {
                        var codepoint = 0;

                        for (var i = 0; i < 4; i++)
                        {
                            try
                            {
                                codepoint = codepoint * 16 + scanner.Current.ToHexValue();

                                scanner.Advance();
                            }
                            catch (Exception)
                            {
                                break;
                            }
                        }

                        scanner.Add(Convert.ToChar(codepoint).ToString());
                    }
                    else
                    {
                        throw new ArgumentMapParseException("string -> not supported escape", scanner.Itext.PositionInfo);
                    }
                }
                else if (scanner.Check(IsControl))
                {
                    throw new ArgumentMapParseException("string -> control character", scanner.Itext.PositionInfo);
                }
                else
                {
                    scanner.AddAdvance();
                }
            }

            return(scanner.Scan);
        }