internal static MimeAddresses       Parse(string mimeAddressesString, bool readOnly)
        {
            if (mimeAddressesString is null)
            {
                if (readOnly)
                {
                    throw new ArgumentNullException(nameof(mimeAddressesString));
                }

                return(new MimeAddresses());
            }

            try {
                MimeAddresses rtn      = new MimeAddresses();
                int           position = 0;

                for (;;)
                {
                    rtn.Add(MimeAddress.Parse(mimeAddressesString, ref position, readOnly));

                    if (position >= mimeAddressesString.Length)
                    {
                        break;
                    }

                    if (MimeLexicalToken.Parse(mimeAddressesString, ref position).Type != MimeLexicalTokenType.Comma)
                    {
                        throw new Exception("data after addresses.");
                    }
                }

                rtn._readOnly = readOnly;

                return(rtn);
            }
            catch (Exception err) {
                throw new MimeException("Invalid address '" + mimeAddressesString + "', " + err.Message);
            }
        }
        protected void                MimeParse(string mimeValue, bool readOnly)
        {
            int Position = 0;

            if (mimeValue is null)
            {
                if (readOnly)
                {
                    throw new ArgumentNullException(nameof(mimeValue));
                }

                return;
            }

            try {
                MimeLexicalToken typeToken;
                MimeLexicalToken sepToken;
                MimeLexicalToken nameToken;
                MimeLexicalToken valueToken;

                typeToken = MimeLexicalToken.Parse(mimeValue, ref Position);

                if (typeToken.Type != MimeLexicalTokenType.Atom)
                {
                    throw new Exception("invalid type");
                }

                _type = typeToken.GetString(mimeValue);

                while ((sepToken = MimeLexicalToken.ParseSkipWhiteSpaceComment(mimeValue, ref Position)).Type == MimeLexicalTokenType.SemiColon)
                {
                    nameToken = MimeLexicalToken.ParseSkipWhiteSpaceComment(mimeValue, ref Position);
                    if (nameToken.Type != MimeLexicalTokenType.Atom)
                    {
                        throw new Exception("invalid paramater name.");
                    }

                    if (MimeLexicalToken.ParseSkipWhiteSpaceComment(mimeValue, ref Position).Type != MimeLexicalTokenType.Assign)
                    {
                        throw new Exception("invalid paramater name.");
                    }

                    valueToken = MimeLexicalToken.ParseSkipWhiteSpaceComment(mimeValue, ref Position);
                    if (valueToken.Type != MimeLexicalTokenType.Atom && valueToken.Type != MimeLexicalTokenType.QuotedString)
                    {
                        throw new Exception("invalid paramater value.");
                    }

                    if (_parameters == null)
                    {
                        _parameters = new MimeFields();
                    }

                    _parameters.Add(new MimeField(nameToken.GetString(mimeValue), valueToken.GetString(mimeValue)));
                }

                if (sepToken.Type != MimeLexicalTokenType.EOL)
                {
                    throw new Exception("extra data.");
                }

                if (readOnly)
                {
                    _readOnly = true;

                    if (_parameters != null)
                    {
                        _parameters.SetCollectionReadOnly();
                    }
                }
            }
            catch (Exception Err) {
                throw new MimeException("Invalid mime field value '" + mimeValue + "'," + Err.Message);
            }
        }
        internal static MimeAddress         Parse(string mimeAddressString, ref int position, bool readOnly)
        {
            MimeLexicalToken addressesToken   = new MimeLexicalToken();
            MimeLexicalToken displayNameToken = new MimeLexicalToken();
            MimeLexicalToken tempToken;
            MimeLexicalToken curToken;

            curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);

            if (curToken.Type == MimeLexicalTokenType.WhiteSpace)
            {
                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
            }

            if (curToken.Type == MimeLexicalTokenType.Atom)
            {
                tempToken = curToken;

                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);

                if (curToken.Type == MimeLexicalTokenType.At)
                {
                    addressesToken = tempToken;
                    addressesToken.AddAddress(curToken);

                    curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
                    if (curToken.Type != MimeLexicalTokenType.Atom)
                    {
                        throw new Exception("invalid address.");
                    }

                    addressesToken.AddAddress(curToken);

                    curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
                }
                else
                {
                    displayNameToken = tempToken;

                    while (curToken.Type == MimeLexicalTokenType.Atom || curToken.Type == MimeLexicalTokenType.WhiteSpace)
                    {
                        displayNameToken.AddPhrase(curToken);
                        curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
                    }

                    displayNameToken.TrimTrailingWhiteSpace(mimeAddressString);
                }
            }
            else
            if (curToken.Type == MimeLexicalTokenType.QuotedString)
            {
                displayNameToken = curToken;

                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);

                if (curToken.Type == MimeLexicalTokenType.WhiteSpace)
                {
                    curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
                }
            }

            if (curToken.Type == MimeLexicalTokenType.AngleBracketOpen)
            {
                if (addressesToken.Type != MimeLexicalTokenType.None)
                {
                    throw new Exception("dubble address");
                }

                if (curToken.Type == MimeLexicalTokenType.WhiteSpace)
                {
                    curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
                }

                while ((curToken = MimeLexicalToken.Parse(mimeAddressString, ref position)).Type == MimeLexicalTokenType.Atom ||
                       curToken.Type == MimeLexicalTokenType.At)
                {
                    addressesToken.AddAddress(curToken);
                }

                if (curToken.Type == MimeLexicalTokenType.WhiteSpace)
                {
                    curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
                }

                if (curToken.Type != MimeLexicalTokenType.AngleBracketClose)
                {
                    throw new Exception("missing '>'.");
                }

                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
            }

            if (curToken.Type == MimeLexicalTokenType.WhiteSpace)
            {
                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
            }

            if (curToken.Type == MimeLexicalTokenType.Comment)
            {
                if (displayNameToken.Type == MimeLexicalTokenType.None)
                {
                    displayNameToken = curToken;
                }

                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
            }

            if (curToken.Type == MimeLexicalTokenType.WhiteSpace)
            {
                curToken = MimeLexicalToken.Parse(mimeAddressString, ref position);
            }

            if (addressesToken.Type == MimeLexicalTokenType.None)
            {
                throw new Exception("missing address");
            }

            if (curToken.Type != MimeLexicalTokenType.EOL && curToken.Type != MimeLexicalTokenType.WhiteSpace)
            {
                position = curToken.Begin;
            }

            return(new MimeAddress(addressesToken.GetString(mimeAddressString), displayNameToken.GetString(mimeAddressString), readOnly));
        }