1use crate::iter::LCChars;
2use crate::ptrait::*;
3
4pub struct String2P<A: Parser, B: Parser> {
5 a: A,
6 b: B,
7}
8
9impl<A, B> Parser for String2P<A, B>
10where
11 A: Parser,
12 B: Parser,
13 A::Out: Into<String>,
14 B::Out: AsRef<str>,
15{
16 type Out = String;
17 fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, String> {
18 let (it2, av, c1) = self.a.parse(it)?;
19 let (itres, bv, c2) = self.b.parse(&it2).map_err(|e| e.join_op(c1))?;
20 let mut s: String = av.into();
21 s.push_str(bv.as_ref());
22 Ok((itres, s, c2))
23 }
24}
25
26pub fn strings_plus_until<A: Parser<Out = String>, B: Parser>(
27 a: A,
28 b: B,
29) -> StringsPlusUntil<A, B> {
30 StringsPlusUntil { a, b }
31}
32
33pub struct StringsPlusUntil<A: Parser<Out = String>, B> {
34 a: A,
35 b: B,
36}
37
38pub fn do_strings_until<'a, A: Parser<Out = String>, B: Parser>(
39 it: &LCChars<'a>,
40 a: &A,
41 b: &B,
42 min: usize,
43) -> ParseRes<'a, (String, B::Out)> {
44 let mut res = String::new();
45 let mut it = it.clone();
46 let mut done = 0;
47 loop {
48 let b_err = if done >= min {
49 match b.parse(&it) {
50 Ok((nit, v, e)) => return Ok((nit, (res, v), e)),
51 Err(e) => Some(e),
52 }
53 } else {
54 None
55 };
56 match a.parse(&it) {
57 Ok((nit, v, _e)) => {
58 res.push_str(&v);
59 it = nit;
60 done += 1;
61 }
62 Err(e) => {
63 if let Some(berr) = b_err {
64 return Err(e.join(berr));
65 }
66 }
67 }
68 }
69}
70
71impl<A: Parser<Out = String>, B: Parser> Parser for StringsPlusUntil<A, B> {
72 type Out = (String, B::Out);
73 fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, Self::Out> {
74 do_strings_until(it, &self.a, &self.b, 1)
75 }
76}
77
78pub fn string_2_parts<A, B>(a: A, b: B) -> String2P<A, B>
79where
80 A: Parser,
81 B: Parser,
82 A::Out: Into<String>,
83 B::Out: AsRef<str>,
84{
85 String2P { a, b }
86}
87
88pub fn string<A: Parser>(a: A) -> AsString<A> {
91 AsString { a }
92}
93
94pub struct AsString<A: Parser> {
95 a: A,
96}
97
98impl<A: Parser> Parser for AsString<A> {
99 type Out = String;
100 fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, String> {
101 self.a
102 .parse(it)
103 .map(|(nit, _, ct)| match (it.index(), nit.index()) {
104 (Some(s), Some(f)) => (nit, it.as_str()[0..(f - s)].to_string(), ct),
105 _ => (nit, it.as_str().to_string(), ct),
106 })
107 }
108}