udled_tokenizers/
string.rs1use udled::{token::Char, Error, Lex, Reader, Span, Tokenizer};
2
3#[derive(Debug, Clone, Copy, Default)]
4pub struct Str;
5
6impl Tokenizer for Str {
7 type Token<'a> = Lex<'a>;
8 fn to_token<'a>(&self, reader: &mut Reader<'_, 'a>) -> Result<Self::Token<'a>, Error> {
9 let start = reader.parse('"')?;
10
11 let end = loop {
12 if reader.eof() {
13 return Err(reader.error("Unexpected end of input while parsing string literal"));
14 }
15
16 let ch = reader.parse(Char)?;
17
18 if ch == r#"""# {
19 break ch.span;
20 }
21
22 if ch == "\\" {
23 match reader.eat_ch()? {
24 "\\" | "\'" | "\"" | "t" | "r" | "n" | "0" => {
25 continue;
26 }
27 _ => return Err(reader.error("Unknown escape sequence")),
28 }
29 }
30 };
31
32 let span = start + end;
33
34 let str = if span.len() == 2 {
35 Some("")
36 } else {
37 Span::new(span.start + 1, span.end - 1).slice(reader.source())
38 };
39
40 Ok(Lex::new(str.unwrap(), span))
41 }
42
43 fn peek<'a>(&self, reader: &mut Reader<'_, '_>) -> Result<bool, Error> {
44 reader.peek('"')
45 }
46}
47
48#[cfg(test)]
49mod test {
50
51 use udled::Input;
52
53 use super::*;
54
55 #[test]
56 fn empty_string() {
57 let mut input = Input::new(r#""""#);
58 let str = input.parse(Str).unwrap();
59 assert_eq!(str.value, "");
60 assert_eq!(str.span, Span::new(0, 2));
61 }
62
63 #[test]
64 fn string() {
65 let mut input = Input::new(r#""Hello, World!""#);
66 let str = input.parse(Str).unwrap();
67 assert_eq!(str.value, "Hello, World!");
68 assert_eq!(str.span, Span::new(0, 15));
69 }
70}