MCPcopy Create free account
hub / github.com/LaBatata101/sith-language-server / lex_string

Method lex_string

crates/sith_python_parser/src/lexer.rs:886–999  ·  view source on GitHub ↗

Lex a string literal.

(&mut self, quote: char)

Source from the content-addressed store, hash-verified

884
885 /// Lex a string literal.
886 fn lex_string(&mut self, quote: char) -> TokenKind {
887 #[cfg(debug_assertions)]
888 debug_assert_eq!(self.cursor.previous(), quote);
889
890 if quote == '"' {
891 self.current_flags |= TokenFlags::DOUBLE_QUOTES;
892 }
893
894 // If the next two characters are also the quote character, then we have a triple-quoted
895 // string; consume those two characters and ensure that we require a triple-quote to close
896 if self.cursor.eat_char2(quote, quote) {
897 self.current_flags |= TokenFlags::TRIPLE_QUOTED_STRING;
898 }
899
900 let value_start = self.offset();
901
902 let quote_byte = u8::try_from(quote).expect("char that fits in u8");
903 let value_end = if self.current_flags.is_triple_quoted() {
904 // For triple-quoted strings, scan until we find the closing quote (ignoring escaped
905 // quotes) or the end of the file.
906 loop {
907 let Some(index) = memchr::memchr(quote_byte, self.cursor.rest().as_bytes()) else {
908 self.cursor.skip_to_end();
909
910 return self.push_error(LexicalError::new(
911 LexicalErrorType::UnclosedStringError,
912 self.token_range(),
913 ));
914 };
915
916 // Rare case: if there are an odd number of backslashes before the quote, then
917 // the quote is escaped and we should continue scanning.
918 let num_backslashes = self.cursor.rest().as_bytes()[..index]
919 .iter()
920 .rev()
921 .take_while(|&&c| c == b'\\')
922 .count();
923
924 // Advance the cursor past the quote and continue scanning.
925 self.cursor.skip_bytes(index + 1);
926
927 // If the character is escaped, continue scanning.
928 if num_backslashes % 2 == 1 {
929 continue;
930 }
931
932 // Otherwise, if it's followed by two more quotes, then we're done.
933 if self.cursor.eat_char2(quote, quote) {
934 break self.offset() - TextSize::new(3);
935 }
936 }
937 } else {
938 // For non-triple-quoted strings, scan until we find the closing quote, but end early
939 // if we encounter a newline or the end of the file.
940 loop {
941 let Some(index) =
942 memchr::memchr3(quote_byte, b'\r', b'\n', self.cursor.rest().as_bytes())
943 else {

Callers 2

lex_identifierMethod · 0.80

Calls 13

eat_char2Method · 0.80
expectMethod · 0.80
restMethod · 0.80
skip_to_endMethod · 0.80
push_errorMethod · 0.80
token_rangeMethod · 0.80
eat_charMethod · 0.80
offsetMethod · 0.45
is_triple_quotedMethod · 0.45
iterMethod · 0.45
skip_bytesMethod · 0.45
firstMethod · 0.45

Tested by

no test coverage detected