public void                    AddAddress(MimeLexicalToken token)
 {
     if (this.Type != MimeLexicalTokenType.None)
     {
         if (token.Type != MimeLexicalTokenType.None)
         {
             this.End  = token.End;
             this.Type = MimeLexicalTokenType.Address;
         }
     }
     else
     {
         this.Begin = token.Begin;
         this.End   = token.End;
         this.Type  = token.Type;
     }
 }
        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));
        }
        public static MimeLexicalToken        Parse(string str, ref int Position)
        {
            int Length           = str.Length;
            MimeLexicalToken rtn = new MimeLexicalToken();

            rtn.Begin   =
                rtn.End = Position;

            if (Position >= Length)
            {
                rtn.Type = MimeLexicalTokenType.EOL;
                return(rtn);
            }

            switch (str[Position])
            {
            case ' ':
            case '\t':
            case '\n':
            case '\r':
                while (rtn.End < Length && _isLinearWhiteSpace(str[rtn.End]))
                {
                    ++rtn.End;
                }

                rtn.Type = MimeLexicalTokenType.WhiteSpace;
                break;

            case '<':
                rtn.Type = MimeLexicalTokenType.AngleBracketOpen;
                ++rtn.End;
                break;

            case '>':
                rtn.Type = MimeLexicalTokenType.AngleBracketClose;
                ++rtn.End;
                break;

            case '@':
                rtn.Type = MimeLexicalTokenType.At;
                ++rtn.End;
                break;

            case ',':
                rtn.Type = MimeLexicalTokenType.Comma;
                ++rtn.End;
                break;

            case ';':
                rtn.Type = MimeLexicalTokenType.SemiColon;
                ++rtn.End;
                break;

            case ':':
                rtn.Type = MimeLexicalTokenType.Colon;
                ++rtn.End;
                break;

            case '=':
                rtn.Type = MimeLexicalTokenType.Assign;
                ++rtn.End;
                break;

            case '\"':
                rtn.Type = MimeLexicalTokenType.QuotedString;
                ++rtn.End;

                while (str[rtn.End] != '\"')
                {
                    if (str[rtn.End] == '\\')
                    {
                        ++rtn.End;
                    }

                    if (++rtn.End >= Length)
                    {
                        throw new MimeException("Unterminated string in '" + str + "'.");
                    }
                }

                ++rtn.End;
                break;

            case '(':
                rtn.Type = MimeLexicalTokenType.Comment;
                ++rtn.End;

                while (rtn.End < Length && str[rtn.End] != ')')
                {
                    if (str[rtn.End] == '\\')
                    {
                        ++rtn.End;
                    }

                    if (++rtn.End >= Length)
                    {
                        throw new MimeException("Unterminated comment in '" + str + "'.");
                    }
                }

                ++rtn.End;
                break;

            case '[':
                rtn.Type = MimeLexicalTokenType.DomainLiteral;
                ++rtn.End;

                while (rtn.End < Length && str[rtn.End] != ')')
                {
                    if (str[rtn.End] == '\\')
                    {
                        ++rtn.End;
                    }

                    if (++rtn.End >= Length)
                    {
                        throw new MimeException("Unterminated domain-literal in '" + str + "'.");
                    }
                }

                ++rtn.End;
                break;

            case ')':
            case ']':
                throw new MimeException("Invalid character in '" + str + "'.");

            default:
                rtn.Type = MimeLexicalTokenType.Atom;

                while (rtn.End < Length && !_isSpecial(str[rtn.End]))
                {
                    if (str[rtn.End] == '\\')
                    {
                        ++rtn.End;
                    }

                    ++rtn.End;
                }
                break;
            }

            Position = rtn.End;
            return(rtn);
        }