/// <summary> /// Converts string literal text into its value. Returns null if the specified string token is malformed due to lexer error recovery. /// </summary> /// <param name="stringToken">the string token</param> public static string?TryGetStringValue(Token stringToken) { var(start, end) = stringToken.Type switch { TokenType.StringComplete => (LanguageConstants.StringDelimiter, LanguageConstants.StringDelimiter), TokenType.StringLeftPiece => (LanguageConstants.StringDelimiter, LanguageConstants.StringHoleOpen), TokenType.StringMiddlePiece => (LanguageConstants.StringHoleClose, LanguageConstants.StringHoleOpen), TokenType.StringRightPiece => (LanguageConstants.StringHoleClose, LanguageConstants.StringDelimiter), _ => (null, null), }; if (start == null || end == null) { return(null); } if (stringToken.Text.Length < start.Length + end.Length || stringToken.Text.Substring(0, start.Length) != start || stringToken.Text.Substring(stringToken.Text.Length - end.Length) != end) { // any lexer-generated token should not hit this problem as the start & end are already verified return(null); } var contents = stringToken.Text.Substring(start.Length, stringToken.Text.Length - start.Length - end.Length); var window = new SlidingTextWindow(contents); // the value of the string will be shorter because escapes are longer than the characters they represent var buffer = new StringBuilder(contents.Length); while (!window.IsAtEnd()) { var nextChar = window.Next(); if (nextChar == '\'') { return(null); } if (nextChar == '\\') { // escape sequence begins if (window.IsAtEnd()) { return(null); } char escapeChar = window.Next(); if (CharacterEscapes.TryGetValue(escapeChar, out char escapeCharValue) == false) { // invalid escape character return(null); } buffer.Append(escapeCharValue); // continue to next iteration continue; } // regular string char - append to buffer buffer.Append(nextChar); } return(buffer.ToString()); }
public Lexer(SlidingTextWindow textWindow) { this.textWindow = textWindow; }
public Lexer(SlidingTextWindow textWindow, IDiagnosticWriter diagnosticWriter) { this.textWindow = textWindow; this.diagnosticWriter = diagnosticWriter; }