/// <summary>Union of <paramref name="o1"/> and <paramref name="o2"/>.</summary>
        public IOption Union(IOption o1, IOption o2)
        {
            StructList4 <IToken> tokens = new StructList4 <IToken>();

            if (o1 is IToken t1)
            {
                foreach (IToken t in t1.ListTokens(true))
                {
                    tokens.AddIfNew(t);
                }
            }
            if (o2 is IToken t2)
            {
                foreach (IToken t in t2.ListTokens(true))
                {
                    tokens.AddIfNew(t);
                }
            }
            if (tokens.Count == 0)
            {
                return(TokenList.NoTokens);
            }
            if (tokens.Count == 1)
            {
                return(tokens[0]);
            }
            return(new TokenList(tokens.ToArray()));
        }
        /// <summary>
        /// Get all the argument indices that are expressed in <paramref name="exp"/>.
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="argumentIndices"></param>
        static void GetArguments(IExpression exp, ref StructList4 <int> argumentIndices)
        {
            StructList8 <IExpression> stack = new StructList8 <IExpression>();

            stack.Add(exp);
            while (stack.Count > 0)
            {
                IExpression e = stack.Dequeue();
                if (e is IArgumentIndexExpression arg)
                {
                    argumentIndices.AddIfNew(arg.Index);
                }
                if (e is ICompositeExpression compositeExpression)
                {
                    for (int i = 0; i < compositeExpression.ComponentCount; i++)
                    {
                        IExpression ce = compositeExpression.GetComponent(i);
                        if (ce != null)
                        {
                            stack.Add(ce);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Concatenates two tokens non-recursively.
        /// Tokens may be null valued.
        /// </summary>
        /// <param name="t1">(optional) Token</param>
        /// <param name="t2">(optional) Token</param>
        /// <returns>null, t1, t2, or concatenated token</returns>
        public static IToken Concat(this IToken t1, IToken t2)
        {
            StructList4 <IToken> tokens = new StructList4 <IToken>();

            if (t1 != null)
            {
                if (t1 is ITokenEnumerable enumr)
                {
                    foreach (IToken t in enumr)
                    {
                        tokens.AddIfNew(t);
                    }
                }
                else
                {
                    tokens.AddIfNew(t1);
                }
            }
            if (t2 != null)
            {
                if (t2 is ITokenEnumerable enumr)
                {
                    foreach (IToken t in enumr)
                    {
                        tokens.AddIfNew(t);
                    }
                }
                else
                {
                    tokens.AddIfNew(t2);
                }
            }
            if (tokens.Count == 0)
            {
                return(null);
            }
            if (tokens.Count == 1)
            {
                return(tokens[0]);
            }
            return(new TokenList(tokens.ToArray()));
        }
        /// <summary>Flatten to simpler instance.</summary>
        public IOption Flatten(IOption o)
        {
            StructList4 <IToken> tokens = new StructList4 <IToken>();

            if (o is IToken t_)
            {
                foreach (IToken t in t_.ListTokens(true))
                {
                    tokens.AddIfNew(t);
                }
            }
            if (tokens.Count == 0)
            {
                return(TokenList.NoTokens);
            }
            if (tokens.Count == 1)
            {
                return(tokens[0]);
            }
            return(new TokenList(tokens.ToArray()));
        }