1use crate::input::{Pear, Input, Rewind, Token, Result};
2use crate::macros::parser;
3use crate::parsers::*;
4
5pub trait Collection<A>: Default + Extend<A> {
6 #[inline(always)]
7 fn push(&mut self, item: A) {
8 self.extend(Some(item))
9 }
10}
11
12impl<A, T: Default + Extend<A>> Collection<A> for T { }
13
14pub fn ok<I, P, O>(input: &mut Pear<I>, p: P) -> Option<O>
17 where I: Input, P: FnOnce(&mut Pear<I>) -> Result<O, I>
18{
19 let save = input.emit_error;
20 input.emit_error = false;
21 let ok = p(input).ok();
22 input.emit_error = save;
23 ok
24}
25
26pub fn succeeds<I, P, O>(input: &mut Pear<I>, p: P) -> bool
29 where I: Input, P: FnOnce(&mut Pear<I>) -> Result<O, I>
30{
31 ok(input, p).is_some()
32}
33
34#[parser(raw)]
36pub fn last_of_many<I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<O, I>
37 where I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
38{
39 loop {
40 let output = p()?;
41 if succeeds(input, eof) {
42 return Ok(output);
43 }
44 }
45}
46
47#[parser(raw)]
49pub fn surrounded<I, O, F, P>(input: &mut Pear<I>, mut p: P, mut f: F) -> Result<O, I>
50 where I: Input,
51 F: FnMut(&I::Token) -> bool,
52 P: FnMut(&mut Pear<I>) -> Result<O, I>
53{
54 skip_while(&mut f)?;
55 let output = p()?;
56 skip_while(&mut f)?;
57 Ok(output)
58}
59
60#[parser(raw)]
63pub fn collect<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
64 where C: Collection<O>, I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
65{
66 let mut collection = C::default();
67 loop {
68 if succeeds(input, eof) {
69 return Ok(collection);
70 }
71
72 collection.push(p()?);
73 }
74}
75
76#[parser(raw)]
79pub fn collect_some<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
80 where C: Collection<O>, I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
81{
82 let mut collection = C::default();
83 loop {
84 collection.push(p()?);
85 if succeeds(input, eof) {
86 return Ok(collection);
87 }
88 }
89}
90
91#[parser(raw)]
94pub fn try_collect<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
95 where C: Collection<O>, I: Input + Rewind, P: FnMut(&mut Pear<I>) -> Result<O, I>
96{
97 let mut collection = C::default();
98 loop {
99 if succeeds(input, eof) {
100 return Ok(collection);
101 }
102
103 let start = input.mark(&crate::input::ParserInfo {
105 name: "try_collect",
106 raw: true
107 });
108
109 match ok(input, |i| p(i)) {
110 Some(val) => collection.push(val),
111 None => {
112 input.rewind_to(start);
113 break;
114 }
115 }
116 }
117
118 Ok(collection)
119}
120
121#[parser(raw)]
126pub fn delimited_collect<C, I, T, S, O, P>(
127 input: &mut Pear<I>,
128 start: T,
129 mut item: P,
130 separator: S,
131 end: T,
132) -> Result<C, I>
133 where C: Collection<O>,
134 I: Input,
135 T: Token<I> + Clone,
136 S: Into<Option<T>>,
137 P: FnMut(&mut Pear<I>) -> Result<O, I>,
138{
139 eat(start)?;
140
141 let seperator = separator.into();
142 let mut collection = C::default();
143 loop {
144 if succeeds(input, |i| eat(i, end.clone())) {
145 break;
146 }
147
148 collection.push(item()?);
149
150 if let Some(ref separator) = seperator {
151 if !succeeds(input, |i| eat(i, separator.clone())) {
152 eat(end.clone())?;
153 break;
154 }
155 }
156 }
157
158 Ok(collection)
159}
160
161#[parser(raw)]
165pub fn series<C, I, S, O, P>(
166 input: &mut Pear<I>,
167 mut item: P,
168 seperator: S,
169) -> Result<C, I>
170 where C: Collection<O>,
171 I: Input,
172 S: Token<I> + Clone,
173 P: FnMut(&mut Pear<I>) -> Result<O, I>,
174{
175 let mut collection = C::default();
176 loop {
177 collection.push(item()?);
178 if !succeeds(input, |i| eat(i, seperator.clone())) {
179 break;
180 }
181 }
182
183 Ok(collection)
184}
185
186#[parser(raw)]
191pub fn trailing_series<C, I, S, O, P>(
192 input: &mut Pear<I>,
193 mut item: P,
194 seperator: S,
195) -> Result<C, I>
196 where C: Collection<O>,
197 I: Input,
198 S: Token<I> + Clone,
199 P: FnMut(&mut Pear<I>) -> Result<O, I>,
200{
201 let mut collection = C::default();
202 let mut have_some = false;
203 loop {
204 if have_some {
205 if let Some(item) = ok(input, |i| item(i)) {
206 collection.push(item);
207 } else {
208 break
209 }
210 } else {
211 collection.push(item()?);
212 have_some = true;
213 }
214
215 if !succeeds(input, |i| eat(i, seperator.clone())) {
216 break;
217 }
218 }
219
220 Ok(collection)
221}
222
223#[parser(raw)]
228pub fn prefixed_series<C, I, T, O, P>(
229 input: &mut Pear<I>,
230 prefix: T,
231 item: P,
232 seperator: T,
233) -> Result<C, I>
234 where C: Collection<O>,
235 I: Input,
236 T: Token<I> + Clone,
237 P: FnMut(&mut Pear<I>) -> Result<O, I>,
238{
239 if !succeeds(input, |i| eat(i, prefix)) {
240 return Ok(C::default());
241 }
242
243 series(input, item, seperator)
244}