udled_tokenizers/
str.rs

1use alloc::string::ToString;
2use udled::{Lex, Span, Tokenizer};
3use unicode_segmentation::UnicodeSegmentation;
4
5pub struct IgnoreCase<T>(pub T);
6
7impl<T> Tokenizer for IgnoreCase<T>
8where
9    T: AsRef<str>,
10{
11    type Token<'a> = Lex<'a>;
12
13    fn to_token<'a>(
14        &self,
15        reader: &mut udled::Reader<'_, 'a>,
16    ) -> Result<Self::Token<'a>, udled::Error> {
17        let tokens = self.0.as_ref().graphemes(true);
18
19        let start = reader.position();
20
21        for token in tokens {
22            let next = reader.eat_ch()?;
23            if token.to_lowercase() != next.to_lowercase() {
24                return Err(reader.error(self.0.as_ref().to_string()));
25            }
26        }
27
28        if start == reader.position() {
29            return Err(reader.error(self.0.as_ref().to_string()));
30        }
31
32        let span = Span::new(start, reader.position());
33        let lex = span.slice(reader.source()).expect("Slice");
34
35        Ok(Lex::new(lex, span))
36    }
37}
38
39#[cfg(test)]
40mod test {
41    use udled::Input;
42
43    use super::IgnoreCase;
44
45    macro_rules! parse {
46        ($parser: literal, $($input:literal),+) => {
47          $(
48            let mut input = Input::new($input);
49            let ret = input.parse(IgnoreCase($parser)).expect("parse");
50
51            assert_eq!($input,ret.as_str());
52          )+
53        };
54    }
55
56    #[test]
57
58    fn ignore_case() {
59        parse!("DOCTYPE", "docType", "DOCTYPE", "DocType");
60        parse!("ÆæpÅLLÆ", "ææpållæ");
61    }
62}