Skip to main content

tokora/parser/many/delim/repeated/
bounded.rs

1use crate::{
2  container::Container as ContainerT,
3  emitter::{TooFewEmitter, TooManyEmitter},
4  error::syntax::TooFew,
5};
6
7use super::*;
8
9impl<
10  'inp,
11  L,
12  P,
13  O,
14  Container,
15  Ctx,
16  Delim,
17  Lang: ?Sized,
18  Cmpl: crate::input::SurfaceIncomplete<'inp, L, Ctx, Lang>,
19> ParseInput<'inp, L, Container, Ctx, Lang, Cmpl>
20  for Collect<
21    DelimitedBy<Bounded<Repeated<P, O, L, Ctx, Lang, Cmpl>>, Delim>,
22    Container,
23    Ctx,
24    Lang,
25    Cmpl,
26  >
27where
28  Delim: Delimiter<'inp, L, Lang>,
29  L: Lexer<'inp>,
30  P: TryParseInput<'inp, L, O, Ctx, Lang, Cmpl>,
31  Ctx::Emitter: FullContainerEmitter<'inp, L, Lang>
32    + TooManyEmitter<'inp, L, Lang>
33    + TooFewEmitter<'inp, L, Lang>
34    + UnclosedEmitter<'inp, L, Lang>,
35  Ctx: ParseContext<'inp, L, Lang>,
36  <Ctx::Emitter as Emitter<'inp, L, Lang>>::Error: From<UnexpectedEot<L::Offset, Lang>>,
37  Container: Default + ContainerT<O> + DelimiterHandler<'inp, L>,
38{
39  fn parse_input(
40    &mut self,
41    inp: &mut InputRef<'inp, '_, L, Ctx, Lang, Cmpl>,
42  ) -> Result<Container, <Ctx::Emitter as Emitter<'inp, L, Lang>>::Error>
43  where
44    L: Lexer<'inp>,
45    Ctx: ParseContext<'inp, L, Lang>,
46  {
47    let limits = self.parser.parser.to_with();
48    let min = self.parser.parser.minimum().get();
49
50    self
51      .attempt(|c| {
52        let Collect {
53          parser, container, ..
54        } = c;
55        DelimitedBy::<_, Delim>::new(parser.parser.parser_mut()).parse_repeated(
56          inp,
57          container,
58          &limits,
59          // The minimum is end-detected and stays here; the maximum is settled at the element that
60          // broke it, from inside `many::admit_element`. See this file's `at_most` sibling.
61          |nums, inp, span| {
62            if min > nums {
63              inp
64                .emitter()
65                .emit_too_few(TooFew::of(span.clone(), nums, min))?;
66            }
67            Ok(())
68          },
69        )
70      })
71      .map(|(_, collected)| collected)
72  }
73}
74
75/// The **spanned owning** destination: the container and the construct's span together.
76///
77/// One of the two contracts this family did not implement until
78/// [#259](https://github.com/al8n/tokora/issues/259)'s stage 3.
79///
80/// Spelled on `With<Collect<..>, PhantomSpan>`, uniformly with every other repetition driver.
81/// [`Collect`]'s "Why the spanned destination wears a wrapper" is why it cannot be written onto
82/// `Collect<..>` itself.
83impl<
84  'inp,
85  L,
86  P,
87  O,
88  Container,
89  Ctx,
90  Delim,
91  Lang: ?Sized,
92  Cmpl: crate::input::SurfaceIncomplete<'inp, L, Ctx, Lang>,
93> ParseInput<'inp, L, Spanned<Container, L::Span>, Ctx, Lang, Cmpl>
94  for With<
95    Collect<
96      DelimitedBy<Bounded<Repeated<P, O, L, Ctx, Lang, Cmpl>>, Delim>,
97      Container,
98      Ctx,
99      Lang,
100      Cmpl,
101    >,
102    PhantomSpan,
103  >
104where
105  Delim: Delimiter<'inp, L, Lang>,
106  L: Lexer<'inp>,
107  P: TryParseInput<'inp, L, O, Ctx, Lang, Cmpl>,
108  Ctx: ParseContext<'inp, L, Lang>,
109  Ctx::Emitter: FullContainerEmitter<'inp, L, Lang>
110    + TooManyEmitter<'inp, L, Lang>
111    + TooFewEmitter<'inp, L, Lang>
112    + UnclosedEmitter<'inp, L, Lang>,
113  <Ctx::Emitter as Emitter<'inp, L, Lang>>::Error: From<UnexpectedEot<L::Offset, Lang>>,
114  Container: Default + ContainerT<O> + DelimiterHandler<'inp, L>,
115{
116  fn parse_input(
117    &mut self,
118    inp: &mut InputRef<'inp, '_, L, Ctx, Lang, Cmpl>,
119  ) -> Result<Spanned<Container, L::Span>, <Ctx::Emitter as Emitter<'inp, L, Lang>>::Error>
120  where
121    L: Lexer<'inp>,
122    Ctx: ParseContext<'inp, L, Lang>,
123  {
124    let limits = self.primary().parser.parser.to_with();
125    let min = self.primary().parser.parser.minimum().get();
126
127    self
128      .primary_mut()
129      .attempt(|c| {
130        let Collect {
131          parser, container, ..
132        } = c;
133        DelimitedBy::<_, Delim>::new(parser.parser.parser_mut()).parse_repeated(
134          inp,
135          container,
136          &limits,
137          |nums, inp, span| {
138            if min > nums {
139              inp
140                .emitter()
141                .emit_too_few(TooFew::of(span.clone(), nums, min))?;
142            }
143
144            Ok(())
145          },
146        )
147      })
148      .map(|(span, collected)| Spanned::new(span, collected))
149  }
150}
151
152/// The **borrowed** destination: the caller keeps the storage, so it can read what the construct
153/// admitted on the **failure** arm too, which the owning form cannot expose.
154///
155/// The second contract this family did not implement until
156/// [#259](https://github.com/al8n/tokora/issues/259)'s stage 3.
157impl<
158  'inp,
159  'c,
160  L,
161  P,
162  O,
163  Container,
164  Ctx,
165  Delim,
166  Lang: ?Sized,
167  Cmpl: crate::input::SurfaceIncomplete<'inp, L, Ctx, Lang>,
168> ParseInput<'inp, L, L::Span, Ctx, Lang, Cmpl>
169  for Collect<
170    &'c mut DelimitedBy<Bounded<Repeated<P, O, L, Ctx, Lang, Cmpl>>, Delim>,
171    &'c mut Container,
172    Ctx,
173    Lang,
174    Cmpl,
175  >
176where
177  Delim: Delimiter<'inp, L, Lang>,
178  L: Lexer<'inp>,
179  P: TryParseInput<'inp, L, O, Ctx, Lang, Cmpl>,
180  Ctx: ParseContext<'inp, L, Lang>,
181  Ctx::Emitter: FullContainerEmitter<'inp, L, Lang>
182    + TooManyEmitter<'inp, L, Lang>
183    + TooFewEmitter<'inp, L, Lang>
184    + UnclosedEmitter<'inp, L, Lang>,
185  <Ctx::Emitter as Emitter<'inp, L, Lang>>::Error: From<UnexpectedEot<L::Offset, Lang>>,
186  Container: ContainerT<O> + DelimiterHandler<'inp, L>,
187{
188  fn parse_input(
189    &mut self,
190    inp: &mut InputRef<'inp, '_, L, Ctx, Lang, Cmpl>,
191  ) -> Result<L::Span, <Ctx::Emitter as Emitter<'inp, L, Lang>>::Error>
192  where
193    L: Lexer<'inp>,
194    Ctx: ParseContext<'inp, L, Lang>,
195  {
196    let limits = self.parser.parser.to_with();
197    let min = self.parser.parser.minimum().get();
198
199    DelimitedBy::<_, Delim>::new(self.parser.parser.parser_mut()).parse_repeated(
200      inp,
201      &mut self.container,
202      &limits,
203      |nums, inp, span| {
204        if min > nums {
205          inp
206            .emitter()
207            .emit_too_few(TooFew::of(span.clone(), nums, min))?;
208        }
209
210        Ok(())
211      },
212    )
213  }
214}