Пример #1
0
        /// <summary>
        /// Returns the next character using the given options, or <see cref="DONE"/> if there
        /// are no more characters, and advance the position to the next
        /// character.
        /// </summary>
        /// <param name="options">One or more of the following options, bitwise-OR-ed
        /// together: <see cref="RuleCharacterIteratorOptions.ParseVariables"/>,
        /// <see cref="RuleCharacterIteratorOptions.ParseEscapes"/>,
        /// <see cref="RuleCharacterIteratorOptions.SkipWhitespace"/>.</param>
        /// <returns>The current 32-bit code point, or <see cref="DONE"/>.</returns>
        public virtual int Next(RuleCharacterIteratorOptions options)
        {
            int c = DONE;

            isEscaped = false;

            for (; ;)
            {
                c = Current();
                Advance(UTF16.GetCharCount(c));

                if (c == SymbolTable.SYMBOL_REF && buf == null &&
                    (options & RuleCharacterIteratorOptions.ParseVariables) != 0 && sym != null)
                {
                    string name = sym.ParseReference(text, pos, text.Length);
                    // If name == null there was an isolated SYMBOL_REF;
                    // return it.  Caller must be prepared for this.
                    if (name == null)
                    {
                        break;
                    }
                    bufPos = 0;
                    buf    = sym.Lookup(name);
                    if (buf == null)
                    {
                        throw new ArgumentException(
                                  "Undefined variable: " + name);
                    }
                    // Handle empty variable value
                    if (buf.Length == 0)
                    {
                        buf = null;
                    }
                    continue;
                }

                if ((options & RuleCharacterIteratorOptions.SkipWhitespace) != 0 &&
                    PatternProps.IsWhiteSpace(c))
                {
                    continue;
                }

                if (c == '\\' && (options & RuleCharacterIteratorOptions.ParseEscapes) != 0)
                {
                    int[] offset = new int[] { 0 };
                    c = Utility.UnescapeAt(Lookahead(), offset);
                    Jumpahead(offset[0]);
                    isEscaped = true;
                    if (c < 0)
                    {
                        throw new ArgumentException("Invalid escape");
                    }
                }

                break;
            }

            return(c);
        }