/// <summary>
        /// Parse a filter ID, that is, an ID of the general form "[f1] s1-t1/v1",
        /// with the filters optional, and the variants optional.
        /// </summary>
        ///
        /// <param name="id">the id to be parsed</param>
        /// <param name="pos">INPUT-OUTPUT parameter. On input, the position of the firstcharacter to parse. On output, the position after the lastcharacter parsed.</param>
        /// <returns>a SingleID object or null if the parse fails</returns>
        public static TransliteratorIDParser.SingleID  ParseFilterID(String id, int[] pos)
        {
            int start = pos[0];

            TransliteratorIDParser.Specs specs = ParseFilterID(id, pos, true);
            if (specs == null)
            {
                pos[0] = start;
                return(null);
            }

            // Assemble return results
            TransliteratorIDParser.SingleID single = SpecsToID(specs, FORWARD);
            single.filter = specs.filter;
            return(single);
        }
        /// <summary>
        /// Convert the elements of the 'list' vector, which are SingleID objects,
        /// into actual Transliterator objects. In the course of this, some (or all)
        /// entries may be removed. If all entries are removed, the Null
        /// transliterator will be added.
        /// Delete entries with empty basicIDs; these are generated by elements like
        /// "(A)" in the forward direction, or "A()" in the reverse. THIS MAY RESULT
        /// IN AN EMPTY VECTOR. Convert SingleID entries to actual transliterators.
        /// </summary>
        ///
        /// <param name="list">vector of SingleID objects. On exit, vector of one or moreTransliterators.</param>
        public static void InstantiateList(ArrayList list)
        {
            Transliterator t;

            for (int i = 0; i <= list.Count;)       // [sic]: i<=list.size()
            // We run the loop too long by one, so we can
            // do an insert after the last element
            {
                if (i == list.Count)
                {
                    break;
                }

                TransliteratorIDParser.SingleID single = (TransliteratorIDParser.SingleID)list[i];
                if (single.basicID.Length == 0)
                {
                    ILOG.J2CsMapping.Collections.Collections.RemoveAt(list, i);
                }
                else
                {
                    t = single.GetInstance();
                    if (t == null)
                    {
                        t = single.GetInstance();
                        throw new ArgumentException("Illegal ID "
                                                    + single.canonID);
                    }
                    list[i] = t;
                    ++i;
                }
            }

            // An empty list is equivalent to a Null transliterator.
            if (list.Count == 0)
            {
                t = IBM.ICU.Text.Transliterator.GetBasicInstance("Any-Null", null);
                if (t == null)
                {
                    // Should never happen
                    throw new ArgumentException(
                              "Internal error; cannot instantiate Any-Null");
                }
                list.Add(t);
            }
        }
        /// <summary>
        /// Parse a compound ID, consisting of an optional forward global filter, a
        /// separator, one or more single IDs delimited by separators, an an optional
        /// reverse global filter. The separator is a semicolon. The global filters
        /// are UnicodeSet patterns. The reverse global filter must be enclosed in
        /// parentheses.
        /// </summary>
        ///
        /// <param name="id">the pattern the parse</param>
        /// <param name="dir">the direction.</param>
        /// <param name="canonID_0">OUTPUT parameter that receives the canonical ID, consisting ofcanonical IDs for all elements, as returned byparseSingleID(), separated by semicolons. Previous contentsare discarded.</param>
        /// <param name="list">OUTPUT parameter that receives a list of SingleID objectsrepresenting the parsed IDs. Previous contents are discarded.</param>
        /// <param name="globalFilter">OUTPUT parameter that receives a pointer to a newly createdglobal filter for this ID in this direction, or null if thereis none.</param>
        /// <returns>true if the parse succeeds, that is, if the entire id is consumed
        /// without syntax error.</returns>
        public static bool ParseCompoundID(String id, int dir,
                                           StringBuilder canonID_0, ArrayList list, UnicodeSet[] globalFilter)
        {
            int[] pos        = new int[] { 0 };
            int[] withParens = new int[1];
            list.Clear();
            UnicodeSet filter_1;

            globalFilter[0]  = null;
            canonID_0.Length = 0;

            // Parse leading global filter, if any
            withParens[0] = 0;     // parens disallowed
            filter_1      = ParseGlobalFilter(id, pos, dir, withParens, canonID_0);
            if (filter_1 != null)
            {
                if (!IBM.ICU.Impl.Utility.ParseChar(id, pos, ID_DELIM))
                {
                    // Not a global filter; backup and resume
                    canonID_0.Length = 0;
                    pos[0]           = 0;
                }
                if (dir == FORWARD)
                {
                    globalFilter[0] = filter_1;
                }
            }

            bool sawDelimiter = true;

            for (;;)
            {
                TransliteratorIDParser.SingleID single = ParseSingleID(id, pos, dir);
                if (single == null)
                {
                    break;
                }
                if (dir == FORWARD)
                {
                    list.Add(single);
                }
                else
                {
                    list.Insert(0, single);
                }
                if (!IBM.ICU.Impl.Utility.ParseChar(id, pos, ID_DELIM))
                {
                    sawDelimiter = false;
                    break;
                }
            }

            if (list.Count == 0)
            {
                return(false);
            }

            // Construct canonical ID
            for (int i = 0; i < list.Count; ++i)
            {
                TransliteratorIDParser.SingleID single_2 = (TransliteratorIDParser.SingleID)list[i];
                canonID_0.Append(single_2.canonID);
                if (i != (list.Count - 1))
                {
                    canonID_0.Append(ID_DELIM);
                }
            }

            // Parse trailing global filter, if any, and only if we saw
            // a trailing delimiter after the IDs.
            if (sawDelimiter)
            {
                withParens[0] = 1;     // parens required
                filter_1      = ParseGlobalFilter(id, pos, dir, withParens, canonID_0);
                if (filter_1 != null)
                {
                    // Don't require trailing ';', but parse it if present
                    IBM.ICU.Impl.Utility.ParseChar(id, pos, ID_DELIM);

                    if (dir == REVERSE)
                    {
                        globalFilter[0] = filter_1;
                    }
                }
            }

            // Trailing unparsed text is a syntax error
            IBM.ICU.Impl.Utility.SkipWhitespace(id, pos[0]);
            if (pos[0] != id.Length)
            {
                return(false);
            }

            return(true);
        }