intuicio_parser/
extendable.rs

1use crate::{
2    alternation::AlternationParser, ParseResult, Parser, ParserExt, ParserHandle, ParserRegistry,
3};
4use std::sync::RwLock;
5
6pub mod shorthand {
7    use super::*;
8
9    pub fn ext_exchange(parser: ParserHandle) -> ParserHandle {
10        ExtendableParser::exchange(parser).into_handle()
11    }
12
13    pub fn ext_depth(parser: ParserHandle) -> ParserHandle {
14        ExtendableParser::depth(parser).into_handle()
15    }
16
17    pub fn ext_variants() -> ParserHandle {
18        ExtendableParser::variants().into_handle()
19    }
20
21    pub fn ext_wrap(parser: ParserHandle, extendable: ParserHandle) -> ParserHandle {
22        ExtendableWrapperParser::new(parser, extendable).into_handle()
23    }
24}
25
26#[derive(Clone)]
27enum ExtendableParserInner {
28    Exchange(ParserHandle),
29    Depth(ParserHandle),
30    Variants(AlternationParser),
31}
32
33pub struct ExtendableParser {
34    inner: RwLock<ExtendableParserInner>,
35}
36
37impl ExtendableParser {
38    pub fn exchange(parser: ParserHandle) -> Self {
39        Self {
40            inner: RwLock::new(ExtendableParserInner::Exchange(parser)),
41        }
42    }
43
44    pub fn depth(parser: ParserHandle) -> Self {
45        Self {
46            inner: RwLock::new(ExtendableParserInner::Depth(parser)),
47        }
48    }
49
50    pub fn variants() -> Self {
51        Self {
52            inner: RwLock::new(ExtendableParserInner::Variants(Default::default())),
53        }
54    }
55}
56
57impl Parser for ExtendableParser {
58    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
59        if let Ok(inner) = self.inner.read() {
60            match &*inner {
61                ExtendableParserInner::Exchange(parser) => parser.parse(registry, input),
62                ExtendableParserInner::Depth(parser) => parser.parse(registry, input),
63                ExtendableParserInner::Variants(parser) => parser.parse(registry, input),
64            }
65        } else {
66            Err("ExtendableParser cannot be read".into())
67        }
68    }
69
70    fn extend(&self, parser: ParserHandle) {
71        if let Ok(mut inner) = self.inner.write() {
72            match &mut *inner {
73                ExtendableParserInner::Exchange(inner) => {
74                    *inner = parser;
75                }
76                ExtendableParserInner::Depth(inner) => {
77                    parser.extend(inner.clone());
78                    *inner = parser;
79                }
80                ExtendableParserInner::Variants(inner) => {
81                    inner.prepend(parser);
82                }
83            }
84        }
85    }
86}
87
88#[derive(Clone)]
89pub struct ExtendableWrapperParser {
90    parser: ParserHandle,
91    extendable: ParserHandle,
92}
93
94impl ExtendableWrapperParser {
95    pub fn new(parser: ParserHandle, extendable: ParserHandle) -> Self {
96        Self { parser, extendable }
97    }
98}
99
100impl Parser for ExtendableWrapperParser {
101    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
102        self.parser.parse(registry, input)
103    }
104
105    fn extend(&self, parser: ParserHandle) {
106        self.extendable.extend(parser);
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use crate::{
113        extendable::{ExtendableParser, ExtendableWrapperParser},
114        shorthand::{
115            ext_depth, ext_exchange, ext_variants, ext_wrap, lit, oc, seq, slot_empty, ws,
116        },
117        ParserRegistry,
118    };
119
120    fn is_async<T: Send + Sync>() {}
121
122    #[test]
123    fn test_extendable() {
124        is_async::<ExtendableParser>();
125        is_async::<ExtendableWrapperParser>();
126
127        let registry = ParserRegistry::default();
128        let keyword_foo = lit("foo");
129        let keyword_bar = lit("bar");
130        let keyword_zee = lit("zee");
131
132        let exchange = ext_exchange(keyword_foo.clone());
133        assert!(exchange.parse(&registry, "foo").is_ok());
134        assert!(exchange.parse(&registry, "bar").is_err());
135        assert!(exchange.parse(&registry, "zee").is_err());
136        exchange.extend(keyword_bar.clone());
137        assert!(exchange.parse(&registry, "foo").is_err());
138        assert!(exchange.parse(&registry, "bar").is_ok());
139        assert!(exchange.parse(&registry, "zee").is_err());
140        exchange.extend(keyword_zee.clone());
141        assert!(exchange.parse(&registry, "foo").is_err());
142        assert!(exchange.parse(&registry, "bar").is_err());
143        assert!(exchange.parse(&registry, "zee").is_ok());
144
145        let variants = ext_variants();
146        assert!(variants.parse(&registry, "foo").is_err());
147        assert!(variants.parse(&registry, "bar").is_err());
148        assert!(variants.parse(&registry, "zee").is_err());
149        variants.extend(keyword_foo);
150        assert!(variants.parse(&registry, "foo").is_ok());
151        assert!(variants.parse(&registry, "bar").is_err());
152        assert!(variants.parse(&registry, "zee").is_err());
153        variants.extend(keyword_bar);
154        assert!(variants.parse(&registry, "foo").is_ok());
155        assert!(variants.parse(&registry, "bar").is_ok());
156        assert!(variants.parse(&registry, "zee").is_err());
157        variants.extend(keyword_zee);
158        assert!(variants.parse(&registry, "foo").is_ok());
159        assert!(variants.parse(&registry, "bar").is_ok());
160        assert!(variants.parse(&registry, "zee").is_ok());
161
162        let signature = seq([lit("fn"), ws(), lit("foo"), lit("("), lit(")")]);
163        let depth = ext_depth(signature);
164        depth.parse(&registry, "fn foo()").unwrap();
165        let async_signature = {
166            let slot = slot_empty();
167            ext_wrap(seq([lit("async"), ws(), slot.clone()]), slot)
168        };
169        async_signature.parse(&registry, "async ").unwrap();
170        depth.extend(async_signature);
171        depth.parse(&registry, "async fn foo()").unwrap();
172
173        let signature = {
174            let slot = slot_empty();
175            ext_wrap(oc(slot.clone(), lit("("), lit(")")), slot)
176        };
177        assert!(signature.parse(&registry, "(foo)").is_err());
178        signature.extend(lit("foo"));
179        assert!(signature
180            .parse(&registry, "(foo)")
181            .unwrap()
182            .1
183            .is::<String>());
184    }
185}