/// <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 }
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)); }
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); }