intuicio_parser/
lib.rs

1pub mod alternation;
2pub mod dynamic;
3pub mod extendable;
4pub mod extension;
5pub mod generator;
6pub mod inject;
7pub mod inspect;
8pub mod list;
9pub mod literal;
10pub mod map;
11pub mod not;
12pub mod one_or_more;
13pub mod open_close;
14pub mod optional;
15pub mod pratt;
16pub mod predict;
17pub mod regex;
18pub mod repeat;
19pub mod sequence;
20pub mod slot;
21pub mod template;
22pub mod zero_or_more;
23
24pub mod shorthand {
25    use super::*;
26
27    pub use crate::{
28        alternation::shorthand::*, dynamic::shorthand::*, extendable::shorthand::*,
29        extension::shorthand::*, inject::shorthand::*, inspect::shorthand::*, list::shorthand::*,
30        literal::shorthand::*, map::shorthand::*, not::shorthand::*, one_or_more::shorthand::*,
31        open_close::shorthand::*, optional::shorthand::*, pratt::shorthand::*,
32        predict::shorthand::*, regex::shorthand::*, repeat::shorthand::*, sequence::shorthand::*,
33        slot::shorthand::*, template::shorthand::*, zero_or_more::shorthand::*,
34    };
35
36    pub fn eos() -> ParserHandle {
37        EndOfSourceParser.into_handle()
38    }
39
40    pub fn source(parser: ParserHandle) -> ParserHandle {
41        SourceParser::new(parser).into_handle()
42    }
43
44    pub fn debug(id: impl ToString, parser: ParserHandle) -> ParserHandle {
45        DebugParser::new(id, parser).into_handle()
46    }
47
48    pub fn erase(parser: ParserHandle) -> ParserHandle {
49        EraseParser::new(parser).into_handle()
50    }
51
52    pub fn ignore() -> ParserHandle {
53        ().into_handle()
54    }
55}
56
57use intuicio_data::managed::DynamicManaged;
58use std::{
59    any::{Any, TypeId},
60    collections::HashMap,
61    error::Error,
62    sync::{Arc, RwLock},
63};
64
65pub type ParserOutput = DynamicManaged;
66pub type ParserHandle = Arc<dyn Parser>;
67pub type ParseResult<'a> = Result<(&'a str, ParserOutput), Box<dyn Error>>;
68
69pub struct ParserNoValue;
70
71pub trait Parser: Send + Sync {
72    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a>;
73
74    #[allow(unused_variables)]
75    fn extend(&self, parser: ParserHandle) {}
76}
77
78pub trait ParserExt: Sized {
79    fn into_handle(self) -> ParserHandle;
80}
81
82impl<T: Parser + 'static> ParserExt for T {
83    fn into_handle(self) -> ParserHandle {
84        Arc::new(self)
85    }
86}
87
88impl Parser for () {
89    fn parse<'a>(&self, _: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
90        Ok((input, ParserOutput::new(ParserNoValue).ok().unwrap()))
91    }
92}
93
94pub struct EndOfSourceParser;
95
96impl Parser for EndOfSourceParser {
97    fn parse<'a>(&self, _: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
98        if input.is_empty() {
99            Ok((input, ParserOutput::new(ParserNoValue).ok().unwrap()))
100        } else {
101            Err("Expected end of source".into())
102        }
103    }
104}
105
106pub struct EraseParser {
107    parser: ParserHandle,
108}
109
110impl EraseParser {
111    pub fn new(parser: ParserHandle) -> Self {
112        Self { parser }
113    }
114}
115
116impl Parser for EraseParser {
117    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
118        let (new_input, _) = self.parser.parse(registry, input)?;
119        Ok((new_input, ParserOutput::new(ParserNoValue).ok().unwrap()))
120    }
121}
122
123pub struct SourceParser {
124    parser: ParserHandle,
125}
126
127impl SourceParser {
128    pub fn new(parser: ParserHandle) -> Self {
129        Self { parser }
130    }
131}
132
133impl Parser for SourceParser {
134    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
135        let before = input.len();
136        let (new_input, _) = self.parser.parse(registry, input)?;
137        let after = new_input.len();
138        let size = before - after;
139        Ok((
140            new_input,
141            ParserOutput::new(input[0..size].to_string()).ok().unwrap(),
142        ))
143    }
144}
145
146pub struct DebugParser {
147    id: String,
148    parser: ParserHandle,
149}
150
151impl DebugParser {
152    pub fn new(id: impl ToString, parser: ParserHandle) -> Self {
153        Self {
154            id: id.to_string(),
155            parser,
156        }
157    }
158}
159
160impl Parser for DebugParser {
161    fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
162        static mut IDENT: usize = 0;
163        unsafe {
164            IDENT += 1;
165        }
166        let ident = " ".repeat(unsafe { IDENT });
167        println!("{}< DEBUG `{}` | Before: {:?}", ident, self.id, input);
168        match self.parser.parse(registry, input) {
169            Ok((input, result)) => {
170                println!("{}> DEBUG `{}` | OK After: {:?}", ident, self.id, input);
171                unsafe {
172                    IDENT -= 1;
173                }
174                Ok((input, result))
175            }
176            Err(error) => {
177                println!(
178                    "{}> DEBUG `{}` | ERR After: {:?} | ERROR: {:?}",
179                    ident, self.id, input, error
180                );
181                unsafe {
182                    IDENT -= 1;
183                }
184                Err(error)
185            }
186        }
187    }
188}
189
190#[derive(Default)]
191pub struct ParserRegistry {
192    parsers: RwLock<HashMap<String, ParserHandle>>,
193    extensions: RwLock<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>,
194}
195
196impl ParserRegistry {
197    pub fn with_parser(self, id: impl ToString, parser: ParserHandle) -> Self {
198        self.add_parser(id, parser);
199        self
200    }
201
202    pub fn with_extension<T: Send + Sync + 'static>(self, data: T) -> Self {
203        self.add_extension::<T>(data);
204        self
205    }
206
207    pub fn add_parser(&self, id: impl ToString, parser: ParserHandle) {
208        if let Ok(mut parsers) = self.parsers.try_write() {
209            parsers.insert(id.to_string(), parser);
210        }
211    }
212
213    pub fn remove_parser(&self, id: impl AsRef<str>) -> Option<ParserHandle> {
214        if let Ok(mut parsers) = self.parsers.try_write() {
215            parsers.remove(id.as_ref())
216        } else {
217            None
218        }
219    }
220
221    pub fn get_parser(&self, id: impl AsRef<str>) -> Option<ParserHandle> {
222        self.parsers.try_read().ok()?.get(id.as_ref()).cloned()
223    }
224
225    pub fn parse<'a>(&self, id: impl AsRef<str>, input: &'a str) -> ParseResult<'a> {
226        if let Some(parser) = self.get_parser(id.as_ref()) {
227            parser.parse(self, input)
228        } else {
229            Err(format!("Parser `{}` not found in registry", id.as_ref()).into())
230        }
231    }
232
233    pub fn extend(&self, id: impl AsRef<str>, parser: ParserHandle) -> Result<(), Box<dyn Error>> {
234        if let Some(extendable) = self.get_parser(id.as_ref()) {
235            extendable.extend(parser);
236            Ok(())
237        } else {
238            Err(format!("Parser '{}' not found in registry", id.as_ref()).into())
239        }
240    }
241
242    pub fn add_extension<T: Send + Sync + 'static>(&self, data: T) -> bool {
243        if let Ok(mut extensions) = self.extensions.try_write() {
244            extensions.insert(TypeId::of::<T>(), Arc::new(data));
245            true
246        } else {
247            false
248        }
249    }
250
251    pub fn remove_extension<T: 'static>(&self) -> bool {
252        if let Ok(mut extensions) = self.extensions.try_write() {
253            extensions.remove(&TypeId::of::<T>());
254            true
255        } else {
256            false
257        }
258    }
259
260    pub fn extension<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
261        self.extensions
262            .try_read()
263            .ok()?
264            .get(&TypeId::of::<T>())?
265            .clone()
266            .downcast::<T>()
267            .ok()
268    }
269}
270
271#[cfg(test)]
272mod tests {
273    use crate::{
274        EndOfSourceParser, ParserNoValue, ParserRegistry, SourceParser,
275        shorthand::{eos, erase, ignore, lit, number_int, seq, source},
276    };
277
278    fn is_async<T: Send + Sync>() {}
279
280    #[test]
281    fn test_end_of_source() {
282        is_async::<EndOfSourceParser>();
283
284        let registry = ParserRegistry::default();
285        let sentence = seq([lit("foo"), eos()]);
286        let (rest, _) = sentence.parse(&registry, "foo").unwrap();
287        assert_eq!(rest, "");
288        let sentence = eos();
289        assert!(sentence.parse(&registry, "foo").is_err());
290    }
291
292    #[test]
293    fn test_source() {
294        is_async::<SourceParser>();
295
296        let registry = ParserRegistry::default();
297        let sentence = source(number_int());
298        let (rest, result) = sentence.parse(&registry, "42 bar").unwrap();
299        assert_eq!(rest, " bar");
300        assert_eq!(result.read::<String>().unwrap().as_str(), "42");
301    }
302
303    #[test]
304    fn test_erase() {
305        is_async::<()>();
306
307        let registry = ParserRegistry::default();
308        let sentence = erase(number_int());
309        let (rest, result) = sentence.parse(&registry, "42 foo").unwrap();
310        assert_eq!(rest, " foo");
311        assert!(result.is::<ParserNoValue>());
312    }
313
314    #[test]
315    fn test_ignore() {
316        is_async::<()>();
317
318        let registry = ParserRegistry::default();
319        let sentence = ignore();
320        let (rest, _) = sentence.parse(&registry, "foo").unwrap();
321        assert_eq!(rest, "foo");
322    }
323}