intuicio_parser/
not.rs

1use crate::{
2    ParseResult, Parser, ParserExt, ParserHandle, ParserNoValue, ParserOutput, ParserRegistry,
3};
4
5pub mod shorthand {
6    use super::*;
7
8    pub fn not(parser: ParserHandle) -> ParserHandle {
9        NotParser::new(parser).into_handle()
10    }
11}
12
13#[derive(Clone)]
14pub struct NotParser(ParserHandle);
15
16impl NotParser {
17    pub fn new(parser: ParserHandle) -> Self {
18        Self(parser)
19    }
20}
21
22impl Parser for NotParser {
23    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
24        match self.0.parse(registry, input) {
25            Ok(_) => Err("Expected to not match input".into()),
26            Err(_) => Ok((input, ParserOutput::new(ParserNoValue).ok().unwrap())),
27        }
28    }
29
30    fn extend(&self, parser: ParserHandle) {
31        self.0.extend(parser);
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use crate::{
38        not::NotParser,
39        shorthand::{lit, not, seq},
40        ParserRegistry,
41    };
42
43    fn is_async<T: Send + Sync>() {}
44
45    #[test]
46    fn test_not() {
47        is_async::<NotParser>();
48
49        let registry = ParserRegistry::default();
50        let sentence = seq([lit("foo"), not(lit("bar"))]);
51        let (rest, _) = sentence.parse(&registry, "foozee").unwrap();
52        assert_eq!(rest, "zee");
53    }
54}