private void ReadStringLiteral(TextPosition start, bool allowMultiline) { var end = _position; bool isMultiLine = false; NextChar(); // Skip ' if (allowMultiline && _c == '\'') { end = _position; NextChar(); if (_c == '\'') { end = _position; NextChar(); // we have an opening ''' -> this a multi-line literal string isMultiLine = true; SkipImmediateNextLine(); } else { // Else this is an empty literal string _token = new SyntaxTokenValue(TokenKind.StringLiteral, start, end, string.Empty); return; } } _textBuilder.Length = 0; continue_parsing_string: while (_c != '\'' && _c != Eof) { if (!isMultiLine && CharHelper.IsNewLine(_c)) { AddError("Invalid newline in a string", _position, _position); } else if (CharHelper.IsControlCharacter(_c) && (!isMultiLine || !CharHelper.IsNewLine(_c))) { AddError($"Invalid control character found {((char)_c).ToPrintableString()}", start, start); } _textBuilder.AppendUtf32(_c); end = _position; NextChar(); } if (isMultiLine) { if (_c == '\'') { end = _position; NextChar(); if (_c == '\'') { end = _position; NextChar(); if (_c == '\'') { end = _position; NextChar(); } else { _textBuilder.Append('\''); _textBuilder.Append('\''); goto continue_parsing_string; } } else { _textBuilder.Append('\''); goto continue_parsing_string; } } else { AddError("Invalid End-Of-File found for multi-line literal string", end, end); } _token = new SyntaxTokenValue(TokenKind.StringLiteralMulti, start, end, _textBuilder.ToString()); } else { if (_c == '\'') { end = _position; NextChar(); } else { AddError("Invalid End-Of-File found on string literal", end, end); } _token = new SyntaxTokenValue(TokenKind.StringLiteral, start, end, _textBuilder.ToString()); } }