rusty_parser/leaf/
stringeq.rs

1use std::iter::Iterator;
2
3use crate::core::into_parser::IntoParser;
4use crate::core::iterator_bound::InputIteratorTrait;
5use crate::core::parser::Parser;
6use crate::core::result::ParseResult;
7
8/// This Parser will compare the input string starts with the given &str.
9/// for borrowing-safety, the lifetime of str must be 'static.
10/// for non-static string, use StringEqualParser
11#[derive(Debug, Clone, Copy)]
12pub struct StrEqualParser<'a> {
13    string: &'a str,
14}
15impl<'a> StrEqualParser<'a> {
16    pub fn new(string: &'a str) -> Self {
17        StrEqualParser { string }
18    }
19}
20impl<'a, It> Parser<It> for StrEqualParser<'a>
21where
22    It: InputIteratorTrait,
23    <It as Iterator>::Item: PartialEq<char>,
24{
25    type Output = ();
26
27    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
28        let i0 = it.clone();
29        let mut it = it;
30        // use take?
31        for ch in self.string.chars() {
32            match it.next() {
33                Some(ch2) => {
34                    if ch2 == ch {
35                        continue;
36                    } else {
37                        return ParseResult {
38                            output: None,
39                            it: i0,
40                        };
41                    }
42                }
43                None => {
44                    return ParseResult {
45                        output: None,
46                        it: i0,
47                    }
48                }
49            }
50        }
51        ParseResult {
52            output: Some(()),
53            it,
54        }
55    }
56}
57impl<'a> IntoParser for StrEqualParser<'a> {
58    type Into = Self;
59    fn into_parser(self) -> Self::Into {
60        self
61    }
62}
63impl IntoParser for &'static str {
64    type Into = StrEqualParser<'static>;
65    fn into_parser(self) -> Self::Into {
66        StrEqualParser::new(self)
67    }
68}
69
70#[derive(Debug, Clone)]
71pub struct StringEqualParser {
72    string: String,
73}
74
75impl StringEqualParser {
76    pub fn new(string: String) -> Self {
77        StringEqualParser { string }
78    }
79}
80
81impl<It> Parser<It> for StringEqualParser
82where
83    It: InputIteratorTrait,
84    <It as Iterator>::Item: PartialEq<char>,
85{
86    type Output = ();
87
88    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
89        StrEqualParser::new(&self.string).parse(it)
90    }
91}
92
93impl IntoParser for StringEqualParser {
94    type Into = Self;
95    fn into_parser(self) -> Self::Into {
96        self
97    }
98}
99
100impl IntoParser for String {
101    type Into = StringEqualParser;
102    fn into_parser(self) -> Self::Into {
103        StringEqualParser::new(self)
104    }
105}
106
107#[derive(Debug)]
108pub struct StrEqualByParser<'a, Predicate, ItemType>
109where
110    Predicate: Fn(ItemType, char) -> bool,
111{
112    string: &'a str,
113    predicate: Predicate,
114    _phantom: std::marker::PhantomData<ItemType>,
115}
116impl<'a, Predicate, ItemType> Clone for StrEqualByParser<'a, Predicate, ItemType>
117where
118    Predicate: Fn(ItemType, char) -> bool + Clone,
119{
120    fn clone(&self) -> Self {
121        Self {
122            string: self.string,
123            predicate: self.predicate.clone(),
124            _phantom: std::marker::PhantomData,
125        }
126    }
127}
128impl<'a, Predicate, ItemType> Copy for StrEqualByParser<'a, Predicate, ItemType> where
129    Predicate: Fn(ItemType, char) -> bool + Copy
130{
131}
132impl<'a, Predicate, ItemType> StrEqualByParser<'a, Predicate, ItemType>
133where
134    Predicate: Fn(ItemType, char) -> bool,
135{
136    pub fn new(string: &'a str, predicate: Predicate) -> Self {
137        Self {
138            string,
139            predicate,
140            _phantom: std::marker::PhantomData,
141        }
142    }
143}
144impl<'a, Predicate, ItemType, It> Parser<It> for StrEqualByParser<'a, Predicate, ItemType>
145where
146    Predicate: Fn(ItemType, char) -> bool,
147    It: InputIteratorTrait + Iterator<Item = ItemType>,
148{
149    type Output = ();
150
151    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
152        let i0 = it.clone();
153        let mut it = it;
154        // use take?
155        for ch in self.string.chars() {
156            match it.next() {
157                Some(ch2) => {
158                    if (self.predicate)(ch2, ch) {
159                        continue;
160                    } else {
161                        return ParseResult {
162                            output: None,
163                            it: i0,
164                        };
165                    }
166                }
167                None => {
168                    return ParseResult {
169                        output: None,
170                        it: i0,
171                    }
172                }
173            }
174        }
175        ParseResult {
176            output: Some(()),
177            it,
178        }
179    }
180}
181impl<'a, Predicate, ItemType> IntoParser for StrEqualByParser<'a, Predicate, ItemType>
182where
183    Predicate: Fn(ItemType, char) -> bool,
184{
185    type Into = Self;
186    fn into_parser(self) -> Self::Into {
187        self
188    }
189}
190
191#[derive(Debug)]
192pub struct StringEqualByParser<Predicate, ItemType>
193where
194    Predicate: Fn(ItemType, char) -> bool,
195{
196    string: String,
197    predicate: Predicate,
198    _phantom: std::marker::PhantomData<ItemType>,
199}
200
201impl<Predicate, ItemType> Clone for StringEqualByParser<Predicate, ItemType>
202where
203    Predicate: Fn(ItemType, char) -> bool + Clone,
204{
205    fn clone(&self) -> Self {
206        Self {
207            string: self.string.clone(),
208            predicate: self.predicate.clone(),
209            _phantom: std::marker::PhantomData,
210        }
211    }
212}
213
214impl<Predicate, ItemType> StringEqualByParser<Predicate, ItemType>
215where
216    Predicate: Fn(ItemType, char) -> bool,
217{
218    pub fn new(string: String, predicate: Predicate) -> Self {
219        Self {
220            string,
221            predicate,
222            _phantom: std::marker::PhantomData,
223        }
224    }
225}
226
227impl<Predicate, ItemType, It> Parser<It> for StringEqualByParser<Predicate, ItemType>
228where
229    It: InputIteratorTrait + Iterator<Item = ItemType>,
230    Predicate: Fn(ItemType, char) -> bool,
231{
232    type Output = ();
233
234    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
235        let i0 = it.clone();
236        let mut it = it;
237        // use take?
238        for ch in self.string.chars() {
239            match it.next() {
240                Some(ch2) => {
241                    if (self.predicate)(ch2, ch) {
242                        continue;
243                    } else {
244                        return ParseResult {
245                            output: None,
246                            it: i0,
247                        };
248                    }
249                }
250                None => {
251                    return ParseResult {
252                        output: None,
253                        it: i0,
254                    }
255                }
256            }
257        }
258        ParseResult {
259            output: Some(()),
260            it,
261        }
262    }
263}
264
265impl<Predicate, ItemType> IntoParser for StringEqualByParser<Predicate, ItemType>
266where
267    Predicate: Fn(ItemType, char) -> bool,
268{
269    type Into = Self;
270    fn into_parser(self) -> Self::Into {
271        self
272    }
273}
274
275/// This Parser will compare the input string starts with the given string.
276/// 'string' must be a iterator of slice &[U] or &str.chars()
277#[derive(Debug, Clone, Copy)]
278pub struct SliceEqualParser<'a, T: 'a> {
279    slice: &'a [T],
280}
281
282impl<'a, T: 'a> SliceEqualParser<'a, T> {
283    pub fn new(slice: &'a [T]) -> Self {
284        SliceEqualParser { slice }
285    }
286}
287
288impl<'a, T: 'a, It> Parser<It> for SliceEqualParser<'a, T>
289where
290    It: InputIteratorTrait,
291    <It as Iterator>::Item: PartialEq<T>,
292{
293    type Output = ();
294
295    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
296        let i0 = it.clone();
297        let mut it = it;
298        // use take?
299        for ch in self.slice.iter() {
300            match it.next() {
301                Some(ch2) => {
302                    if ch2 == *ch {
303                        continue;
304                    } else {
305                        return ParseResult {
306                            output: None,
307                            it: i0,
308                        };
309                    }
310                }
311                None => {
312                    return ParseResult {
313                        output: None,
314                        it: i0,
315                    }
316                }
317            }
318        }
319        ParseResult {
320            output: Some(()),
321            it,
322        }
323    }
324}
325
326impl<'a, T: 'a> IntoParser for SliceEqualParser<'a, T> {
327    type Into = Self;
328    fn into_parser(self) -> Self::Into {
329        self
330    }
331}
332
333impl<T: 'static> IntoParser for &'static [T] {
334    type Into = SliceEqualParser<'static, T>;
335    fn into_parser(self) -> Self::Into {
336        SliceEqualParser::new(self)
337    }
338}
339
340#[derive(Debug, Clone)]
341pub struct VecEqualParser<T> {
342    vec: Vec<T>,
343}
344
345impl<T> VecEqualParser<T> {
346    pub fn new(vec: Vec<T>) -> Self {
347        VecEqualParser { vec }
348    }
349}
350
351impl<T, It> Parser<It> for VecEqualParser<T>
352where
353    It: InputIteratorTrait,
354    <It as Iterator>::Item: PartialEq<T>,
355{
356    type Output = ();
357
358    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
359        SliceEqualParser::new(&self.vec).parse(it)
360    }
361}
362
363impl<T> IntoParser for VecEqualParser<T> {
364    type Into = Self;
365    fn into_parser(self) -> Self::Into {
366        self
367    }
368}
369
370impl<T> IntoParser for Vec<T> {
371    type Into = VecEqualParser<T>;
372    fn into_parser(self) -> Self::Into {
373        VecEqualParser::new(self)
374    }
375}
376
377#[derive(Debug)]
378pub struct SliceEqualByParser<'a, T: 'a, Predicate, ItemType>
379where
380    Predicate: Fn(ItemType, &T) -> bool,
381{
382    slice: &'a [T],
383    predicate: Predicate,
384    _phantom: std::marker::PhantomData<ItemType>,
385}
386
387impl<'a, T: 'a, Predicate, ItemType> Clone for SliceEqualByParser<'a, T, Predicate, ItemType>
388where
389    Predicate: Fn(ItemType, &T) -> bool + Clone,
390{
391    fn clone(&self) -> Self {
392        Self {
393            slice: self.slice,
394            predicate: self.predicate.clone(),
395            _phantom: std::marker::PhantomData,
396        }
397    }
398}
399
400impl<'a, T: 'a, Predicate, ItemType> Copy for SliceEqualByParser<'a, T, Predicate, ItemType> where
401    Predicate: Fn(ItemType, &T) -> bool + Copy
402{
403}
404
405impl<'a, T: 'a, Predicate, ItemType> SliceEqualByParser<'a, T, Predicate, ItemType>
406where
407    Predicate: Fn(ItemType, &T) -> bool,
408{
409    pub fn new(slice: &'a [T], predicate: Predicate) -> Self {
410        Self {
411            slice,
412            predicate,
413            _phantom: std::marker::PhantomData,
414        }
415    }
416}
417
418impl<'a, T: 'a, Predicate, ItemType, It> Parser<It>
419    for SliceEqualByParser<'a, T, Predicate, ItemType>
420where
421    It: InputIteratorTrait + Iterator<Item = ItemType>,
422    Predicate: Fn(ItemType, &T) -> bool,
423{
424    type Output = ();
425
426    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
427        let i0 = it.clone();
428        let mut it = it;
429        // use take?
430        for ch in self.slice.iter() {
431            match it.next() {
432                Some(ch2) => {
433                    if (self.predicate)(ch2, ch) {
434                        continue;
435                    } else {
436                        return ParseResult {
437                            output: None,
438                            it: i0,
439                        };
440                    }
441                }
442                None => {
443                    return ParseResult {
444                        output: None,
445                        it: i0,
446                    }
447                }
448            }
449        }
450        ParseResult {
451            output: Some(()),
452            it,
453        }
454    }
455}
456
457impl<'a, T: 'a, Predicate, ItemType> IntoParser for SliceEqualByParser<'a, T, Predicate, ItemType>
458where
459    Predicate: Fn(ItemType, &T) -> bool,
460{
461    type Into = Self;
462    fn into_parser(self) -> Self::Into {
463        self
464    }
465}
466
467#[derive(Debug)]
468pub struct VecEqualByParser<T, Predicate, ItemType>
469where
470    Predicate: Fn(ItemType, &T) -> bool,
471{
472    vec: Vec<T>,
473    predicate: Predicate,
474    _phantom: std::marker::PhantomData<ItemType>,
475}
476
477impl<T, Predicate, ItemType> Clone for VecEqualByParser<T, Predicate, ItemType>
478where
479    Predicate: Fn(ItemType, &T) -> bool + Clone,
480    Vec<T>: Clone,
481{
482    fn clone(&self) -> Self {
483        Self {
484            vec: self.vec.clone(),
485            predicate: self.predicate.clone(),
486            _phantom: std::marker::PhantomData,
487        }
488    }
489}
490
491impl<T, Predicate, ItemType> VecEqualByParser<T, Predicate, ItemType>
492where
493    Predicate: Fn(ItemType, &T) -> bool,
494{
495    pub fn new(vec: Vec<T>, predicate: Predicate) -> Self {
496        VecEqualByParser {
497            vec,
498            predicate,
499            _phantom: std::marker::PhantomData,
500        }
501    }
502}
503
504impl<T, Predicate, ItemType, It> Parser<It> for VecEqualByParser<T, Predicate, ItemType>
505where
506    It: InputIteratorTrait + Iterator<Item = ItemType>,
507    Predicate: Fn(ItemType, &T) -> bool,
508{
509    type Output = ();
510
511    fn parse(&self, it: It) -> ParseResult<Self::Output, It> {
512        let i0 = it.clone();
513        let mut it = it;
514        // use take?
515        for ch in self.vec.iter() {
516            match it.next() {
517                Some(ch2) => {
518                    if (self.predicate)(ch2, ch) {
519                        continue;
520                    } else {
521                        return ParseResult {
522                            output: None,
523                            it: i0,
524                        };
525                    }
526                }
527                None => {
528                    return ParseResult {
529                        output: None,
530                        it: i0,
531                    }
532                }
533            }
534        }
535        ParseResult {
536            output: Some(()),
537            it,
538        }
539    }
540}
541
542impl<T, Predicate, ItemType> IntoParser for VecEqualByParser<T, Predicate, ItemType>
543where
544    Predicate: Fn(ItemType, &T) -> bool,
545{
546    type Into = Self;
547    fn into_parser(self) -> Self::Into {
548        self
549    }
550}
551
552#[cfg(test)]
553mod test {
554    use super::*;
555
556    #[test]
557    fn success1() {
558        let parser = StrEqualParser::new("hello");
559
560        let res = parser.parse("hello_world!!".chars());
561        assert_eq!(res.output, Some(()));
562        let rest: String = res.it.collect();
563        assert_eq!(&rest, "_world!!");
564    }
565
566    #[test]
567    fn success2() {
568        let parser = StrEqualByParser::new("hello", |a: char, b: char| a.to_ascii_lowercase() == b);
569
570        let res = parser.parse("HeLlo_world!!".chars());
571        assert_eq!(res.output, Some(()));
572        let rest: String = res.it.collect();
573        assert_eq!(&rest, "_world!!");
574    }
575
576    #[test]
577    fn fail1() {
578        let parser = StrEqualParser::new("hello");
579
580        let res = parser.parse("hell_world!!".chars());
581        assert_eq!(res.output, None);
582        let rest: String = res.it.collect();
583        assert_eq!(&rest, "hell_world!!");
584    }
585}