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 ignore() -> ParserHandle {
49 ().into_handle()
50 }
51}
52
53use intuicio_data::managed::DynamicManaged;
54use std::{
55 any::{Any, TypeId},
56 collections::HashMap,
57 error::Error,
58 sync::Arc,
59};
60
61pub type ParserOutput = DynamicManaged;
62pub type ParserHandle = Arc<dyn Parser>;
63pub type ParseResult<'a> = Result<(&'a str, ParserOutput), Box<dyn Error>>;
64
65pub struct ParserNoValue;
66
67pub trait Parser: Send + Sync {
68 fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a>;
69
70 #[allow(unused_variables)]
71 fn extend(&self, parser: ParserHandle) {}
72}
73
74pub trait ParserExt: Sized {
75 fn into_handle(self) -> ParserHandle;
76}
77
78impl<T: Parser + 'static> ParserExt for T {
79 fn into_handle(self) -> ParserHandle {
80 Arc::new(self)
81 }
82}
83
84impl Parser for () {
85 fn parse<'a>(&self, _: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
86 Ok((input, ParserOutput::new(ParserNoValue).ok().unwrap()))
87 }
88}
89
90pub struct EndOfSourceParser;
91
92impl Parser for EndOfSourceParser {
93 fn parse<'a>(&self, _: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
94 if input.is_empty() {
95 Ok((input, ParserOutput::new(ParserNoValue).ok().unwrap()))
96 } else {
97 Err("Expected end of source".into())
98 }
99 }
100}
101
102pub struct SourceParser {
103 parser: ParserHandle,
104}
105
106impl SourceParser {
107 pub fn new(parser: ParserHandle) -> Self {
108 Self { parser }
109 }
110}
111
112impl Parser for SourceParser {
113 fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
114 let before = input.len();
115 let (new_input, _) = self.parser.parse(registry, input)?;
116 let after = new_input.len();
117 let size = before - after;
118 Ok((
119 new_input,
120 ParserOutput::new(input[0..size].to_string()).ok().unwrap(),
121 ))
122 }
123}
124
125pub struct DebugParser {
126 id: String,
127 parser: ParserHandle,
128}
129
130impl DebugParser {
131 pub fn new(id: impl ToString, parser: ParserHandle) -> Self {
132 Self {
133 id: id.to_string(),
134 parser,
135 }
136 }
137}
138
139impl Parser for DebugParser {
140 fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
141 static mut IDENT: usize = 0;
142 unsafe {
143 IDENT += 1;
144 }
145 let ident = " ".repeat(unsafe { IDENT });
146 println!("{}< DEBUG `{}` | Before: {:?}", ident, self.id, input);
147 match self.parser.parse(registry, input) {
148 Ok((input, result)) => {
149 println!("{}> DEBUG `{}` | OK After: {:?}", ident, self.id, input);
150 unsafe {
151 IDENT -= 1;
152 }
153 Ok((input, result))
154 }
155 Err(error) => {
156 println!(
157 "{}> DEBUG `{}` | ERR After: {:?} | ERROR: {:?}",
158 ident, self.id, input, error
159 );
160 unsafe {
161 IDENT -= 1;
162 }
163 Err(error)
164 }
165 }
166 }
167}
168
169#[derive(Default)]
170pub struct ParserRegistry {
171 parsers: HashMap<String, ParserHandle>,
172 extensions: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
173}
174
175impl ParserRegistry {
176 pub fn with_parser(mut self, id: impl ToString, parser: ParserHandle) -> Self {
177 self.add_parser(id, parser);
178 self
179 }
180
181 pub fn with_extension<T: Send + Sync + 'static>(mut self, data: T) -> Self {
182 self.add_extension::<T>(data);
183 self
184 }
185
186 pub fn add_parser(&mut self, id: impl ToString, parser: ParserHandle) {
187 self.parsers.insert(id.to_string(), parser);
188 }
189
190 pub fn remove_parser(&mut self, id: impl AsRef<str>) -> Option<ParserHandle> {
191 self.parsers.remove(id.as_ref())
192 }
193
194 pub fn get_parser(&self, id: impl AsRef<str>) -> Option<ParserHandle> {
195 self.parsers.get(id.as_ref()).cloned()
196 }
197
198 pub fn parse<'a>(&self, id: impl AsRef<str>, input: &'a str) -> ParseResult<'a> {
199 if let Some(parser) = self.get_parser(id.as_ref()) {
200 parser.parse(self, input)
201 } else {
202 Err(format!("Parser `{}` not found in registry", id.as_ref()).into())
203 }
204 }
205
206 pub fn extend(&self, id: impl AsRef<str>, parser: ParserHandle) -> Result<(), Box<dyn Error>> {
207 if let Some(extendable) = self.get_parser(id.as_ref()) {
208 extendable.extend(parser);
209 Ok(())
210 } else {
211 Err(format!("Parser '{}' not found in registry", id.as_ref()).into())
212 }
213 }
214
215 pub fn add_extension<T: Send + Sync + 'static>(&mut self, data: T) -> bool {
216 self.extensions.insert(TypeId::of::<T>(), Arc::new(data));
217 true
218 }
219
220 pub fn remove_extension<T: 'static>(&mut self) -> bool {
221 self.extensions.remove(&TypeId::of::<T>());
222 true
223 }
224
225 pub fn extension<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
226 self.extensions
227 .get(&TypeId::of::<T>())?
228 .clone()
229 .downcast::<T>()
230 .ok()
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use crate::{
237 shorthand::{eos, ignore, lit, number_int, seq, source},
238 EndOfSourceParser, ParserRegistry, SourceParser,
239 };
240
241 fn is_async<T: Send + Sync>() {}
242
243 #[test]
244 fn test_end_of_source() {
245 is_async::<EndOfSourceParser>();
246
247 let registry = ParserRegistry::default();
248 let sentence = seq([lit("foo"), eos()]);
249 let (rest, _) = sentence.parse(®istry, "foo").unwrap();
250 assert_eq!(rest, "");
251 let sentence = eos();
252 assert!(sentence.parse(®istry, "foo").is_err());
253 }
254
255 #[test]
256 fn test_source() {
257 is_async::<SourceParser>();
258
259 let registry = ParserRegistry::default();
260 let sentence = source(number_int());
261 let (rest, result) = sentence.parse(®istry, "42 bar").unwrap();
262 assert_eq!(rest, " bar");
263 assert_eq!(result.read::<String>().unwrap().as_str(), "42");
264 }
265
266 #[test]
267 fn test_ignore() {
268 is_async::<()>();
269
270 let registry = ParserRegistry::default();
271 let sentence = ignore();
272 let (rest, _) = sentence.parse(®istry, "foo").unwrap();
273 assert_eq!(rest, "foo");
274 }
275}