MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / lex_extended_string

Function lex_extended_string

src/sql-lexer/src/lexer.rs:281–336  ·  view source on GitHub ↗
(buf: &mut LexBuf)

Source from the content-addressed store, hash-verified

279}
280
281fn lex_extended_string(buf: &mut LexBuf) -> Result<Token, LexerError> {
282 fn lex_unicode_escape(buf: &mut LexBuf, n: usize) -> Result<char, LexerError> {
283 let pos = buf.pos() - 2;
284 buf.next_n(n)
285 .and_then(|s| u32::from_str_radix(s, 16).ok())
286 .and_then(|codepoint| char::try_from(codepoint).ok())
287 .ok_or_else(|| LexerError::new(pos, "invalid unicode escape"))
288 }
289
290 // We do not support octal (\o) or hexadecimal (\x) escapes, since it is
291 // possible to construct invalid UTF-8 with these escapes. We could check
292 // for and reject invalid UTF-8, of course, but it is too annoying to be
293 // worth doing right now. We still lex the escapes to produce nice error
294 // messages.
295
296 fn lex_octal_escape(buf: &mut LexBuf) -> LexerError {
297 let pos = buf.pos() - 2;
298 buf.take_while(|ch| matches!(ch, '0'..='7'));
299 LexerError::new(pos, "octal escapes are not supported")
300 }
301
302 fn lex_hexadecimal_escape(buf: &mut LexBuf) -> LexerError {
303 let pos = buf.pos() - 2;
304 buf.take_while(|ch| matches!(ch, '0'..='9' | 'A'..='F' | 'a'..='f'));
305 LexerError::new(pos, "hexadecimal escapes are not supported")
306 }
307
308 let mut s = String::new();
309 loop {
310 let pos = buf.pos() - 1;
311 loop {
312 match buf.next() {
313 Some('\'') if buf.consume('\'') => s.push('\''),
314 Some('\'') => break,
315 Some('\\') => match buf.next() {
316 Some('b') => s.push('\x08'),
317 Some('f') => s.push('\x0c'),
318 Some('n') => s.push('\n'),
319 Some('r') => s.push('\r'),
320 Some('t') => s.push('\t'),
321 Some('u') => s.push(lex_unicode_escape(buf, 4)?),
322 Some('U') => s.push(lex_unicode_escape(buf, 8)?),
323 Some('0'..='7') => return Err(lex_octal_escape(buf)),
324 Some('x') => return Err(lex_hexadecimal_escape(buf)),
325 Some(c) => s.push(c),
326 None => bail!(pos, "unterminated quoted string"),
327 },
328 Some(c) => s.push(c),
329 None => bail!(pos, "unterminated quoted string"),
330 }
331 }
332 if !lex_to_adjacent_string(buf) {
333 return Ok(Token::String(s));
334 }
335 }
336}
337
338fn lex_to_adjacent_string(buf: &mut LexBuf) -> bool {

Callers 1

lexFunction · 0.85

Calls 9

lex_unicode_escapeFunction · 0.85
lex_octal_escapeFunction · 0.85
lex_hexadecimal_escapeFunction · 0.85
lex_to_adjacent_stringFunction · 0.85
StringClass · 0.85
posMethod · 0.80
nextMethod · 0.45
consumeMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected