Ejemplo n.º 1
0
        /// <summary>
        /// Parses string literal text, processes escaped sequences.
        /// </summary>
        /// <param name="buffer">Characters buffer to read from.</param>
        /// <param name="start">Offset in <paramref name="buffer"/> of first character.</param>
        /// <param name="length">Number of characters.</param>
        /// <param name="tryprocess">Callback that handles escaped character sequences. Returns new buffer position in case the sequence was processed, otherwise <c>-1</c>.</param>
        /// <param name="binary">Whether to force a binary string output.</param>
        /// <returns>Parsed text, either <see cref="string"/> or <see cref="byte"/>[].</returns>
        object ProcessStringText(char[] buffer, int start, int length, ProcessStringDelegate tryprocess, bool binary = false)
        {
            Debug.Assert(start >= 0);
            Debug.Assert(length >= 0);
            Debug.Assert(tryprocess != null);

            if (length == 0)
            {
                return(string.Empty);
            }

            int to = start + length;

            Debug.Assert(start >= 0);
            Debug.Assert(to <= buffer.Length);

            PhpStringBuilder lazyBuilder = null;

            // find first backslash quickly
            int index = start;

            while (index < to && buffer[index] != '\\')
            {
                index++;
            }

            //
            for (; index < to; index++)
            {
                var c = buffer[index];
                if (c == '\\' && index + 1 < to)
                {
                    // ensure string builder lazily
                    if (lazyBuilder == null)
                    {
                        lazyBuilder = new PhpStringBuilder(_encoding, binary, length);
                        lazyBuilder.Append(buffer, start, index - start);
                    }

                    int processed = tryprocess(buffer, index + 1, lazyBuilder);
                    if (processed > 0)
                    {
                        Debug.Assert(processed >= index + 1);
                        index = processed;
                        continue;
                    }
                }

                if (lazyBuilder != null)
                {
                    lazyBuilder.Append(c);
                }
            }

            //
            return(lazyBuilder == null
                ? Intern(buffer, start, length)
                : lazyBuilder.StringResult); // TODO: .Result; and handle String or byte[] properly
        }
Ejemplo n.º 2
0
        object GetTokenAsQuotedString(ProcessStringDelegate tryprocess, char quote)
        {
            // 1/ "..."
            // 2/ b"..."
            // 3/ ...

            bool binary = false;
            int  start  = token_start;
            int  end    = token_end;

            if (start == end)
            {
                return(string.Empty);
            }

            if (buffer[start] == 'b')
            {
                binary = true;
                start++;
            }

            if (end - start >= 2 && buffer[start] == quote && buffer[end - 1] == quote)
            {
                // quoted
                start++;
                end--;
            }
            else
            {
                if (binary) // rollback
                {
                    binary = false;
                    start--;
                }
            }

            return(ProcessStringText(buffer, start, end - start, tryprocess, binary));
        }
Ejemplo n.º 3
0
        bool ProcessEndNowDoc(ProcessStringDelegate tryprocess)
        {
            BEGIN(LexicalStates.ST_END_HEREDOC);
            int trail = LabelTrailLength();

            int start  = BufferTokenStart;
            int length = TokenLength - _hereDocLabel.Length - trail;

            string sourcetext = GetTokenSubstring(0, length, intern: false);
            string text       = tryprocess != null
                ? (string)ProcessStringText(buffer, start, length, tryprocess)
                : sourcetext;

            text = FixHeredocIndent(text);

            // move back at the end of the heredoc label - yyless does not work properly (requires additional condition for the optional ';')
            lookahead_index = token_end = lookahead_index - _hereDocLabel.Length - trail;

            _tokenSemantics.Object = new KeyValuePair <string, string>(text, sourcetext);

            //
            return(text.Length != 0);
        }