pom/
parser.rs

1use super::{Error, Result};
2use crate::{
3	range::RangeArgument,
4	set::Set,
5};
6use std::{
7	fmt::{Debug, Display},
8	ops::{Add, BitOr, Mul, Neg, Not, Shr, Sub},
9	ops::Bound::{Included, Excluded, Unbounded},
10};
11
12type Parse<'a, I, O> = dyn Fn(&'a [I], usize) -> Result<(O, usize)> + 'a;
13
14/// Parser combinator.
15pub struct Parser<'a, I, O> {
16	pub method: Box<Parse<'a, I, O>>,
17}
18
19impl<'a, I, O> Parser<'a, I, O> {
20	/// Create new parser.
21	pub fn new<P>(parse: P) -> Self
22	where
23		P: Fn(&'a [I], usize) -> Result<(O, usize)> + 'a,
24	{
25		Self {
26			method: Box::new(parse),
27		}
28	}
29
30	/// Apply the parser to parse input.
31	pub fn parse(&self, input: &'a [I]) -> Result<O> {
32		(self.method)(input, 0).map(|(out, _)| out)
33	}
34
35	/// Parse input at specified position.
36	pub fn parse_at(&self, input: &'a [I], start: usize) -> Result<(O, usize)> {
37		(self.method)(input, start)
38	}
39
40	/// Convert parser result to desired value.
41	pub fn map<U, F>(self, f: F) -> Parser<'a, I, U>
42	where
43		F: Fn(O) -> U + 'a,
44		I: 'a,
45		O: 'a,
46		U: 'a,
47	{
48		Parser::new(move |input: &'a [I], start: usize| {
49			(self.method)(input, start).map(|(out, pos)| (f(out), pos))
50		})
51	}
52
53	/// Convert parser result to desired value, fail in case of conversion error.
54	pub fn convert<U, E, F>(self, f: F) -> Parser<'a, I, U>
55	where
56		F: Fn(O) -> ::std::result::Result<U, E> + 'a,
57		E: Debug,
58		O: 'a,
59		U: 'a,
60	{
61		Parser::new(move |input: &'a [I], start: usize| {
62			(self.method)(input, start).and_then(|(res, pos)| match f(res) {
63				Ok(out) => Ok((out, pos)),
64				Err(err) => Err(Error::Conversion {
65					message: format!("Conversion error: {:?}", err),
66					position: start,
67				}),
68			})
69		})
70	}
71
72	/// Cache parser output result to speed up backtracking.
73	pub fn cache(self) -> Self
74	where
75		O: Clone + 'a,
76	{
77		use std::{cell::RefCell, collections::HashMap};
78		let results = RefCell::new(HashMap::new());
79		Self::new(move |input: &'a [I], start: usize| {
80			let key = (start, format!("{:p}", &self.method));
81			results
82				.borrow_mut()
83				.entry(key)
84				.or_insert_with(|| (self.method)(input, start))
85				.clone()
86		})
87	}
88
89	/// Get input position after matching parser.
90	pub fn pos(self) -> Parser<'a, I, usize>
91	where
92		O: 'a,
93	{
94		Parser::new(move |input: &'a [I], start: usize| {
95			(self.method)(input, start).map(|(_, pos)| (pos, pos))
96		})
97	}
98
99	/// Collect all matched input symbols.
100	pub fn collect(self) -> Parser<'a, I, &'a [I]>
101	where
102		O: 'a,
103	{
104		Parser::new(move |input: &'a [I], start: usize| {
105			(self.method)(input, start).map(|(_, end)| (&input[start..end], end))
106		})
107	}
108
109	/// Discard parser output.
110	pub fn discard(self) -> Parser<'a, I, ()>
111	where
112		O: 'a,
113	{
114		Parser::new(move |input: &'a [I], start: usize| {
115			(self.method)(input, start).map(|(_, end)| ((), end))
116		})
117	}
118
119	/// Make parser optional.
120	pub fn opt(self) -> Parser<'a, I, Option<O>>
121	where
122		O: 'a,
123	{
124		Parser::new(
125			move |input: &'a [I], start: usize| match (self.method)(input, start) {
126				Ok((out, pos)) => Ok((Some(out), pos)),
127				Err(_) => Ok((None, start)),
128			},
129		)
130	}
131
132	/// `p.repeat(5)` repeat p exactly 5 times
133	/// `p.repeat(0..)` repeat p zero or more times
134	/// `p.repeat(1..)` repeat p one or more times
135	/// `p.repeat(1..4)` match p at least 1 and at most 3 times
136	pub fn repeat<R>(self, range: R) -> Parser<'a, I, Vec<O>>
137	where
138		R: RangeArgument<usize> + Debug + 'a,
139		O: 'a,
140	{
141		Parser::new(move |input: &'a [I], start: usize| {
142			let mut items = vec![];
143			let mut pos = start;
144			loop {
145				match range.end() {
146					Included(&max_count) => {
147						if items.len() >= max_count {
148							break;
149						}
150					}
151					Excluded(&max_count) => {
152						if items.len() + 1 >= max_count {
153							break;
154						}
155					}
156					Unbounded => (),
157				}
158
159				let Ok((item, item_pos)) = (self.method)(input, pos) else { break };
160				items.push(item);
161				pos = item_pos;
162			}
163			if let Included(&min_count) = range.start() {
164				if items.len() < min_count {
165					return Err(Error::Mismatch {
166						message: format!(
167							"expect repeat at least {} times, found {} times",
168							min_count,
169							items.len()
170						),
171						position: start,
172					});
173				}
174			}
175			Ok((items, pos))
176		})
177	}
178
179	#[cfg(not(feature = "trace"))]
180	/// Give parser a name to identify parsing errors.
181	pub fn name(self, name: &'a str) -> Self
182	where
183		O: 'a,
184	{
185		Parser::new(
186			move |input: &'a [I], start: usize| match (self.method)(input, start) {
187				res @ Ok(_) => res,
188				Err(err) => match err {
189					Error::Custom { .. } => Err(err),
190					_ => Err(Error::Custom {
191						message: format!("failed to parse {}", name),
192						position: start,
193						inner: Some(Box::new(err)),
194					}),
195				},
196			},
197		)
198	}
199
200	#[cfg(feature = "trace")]
201	/// Trace parser calls and results. Similar to name
202	pub fn name(self, name: &'a str) -> Self
203	where
204		O: 'a,
205	{
206		Parser::new(
207			move |input: &'a [I], start: usize| {
208				println!("parse: {} ({})", name, start);
209				match (self.method)(input, start) {
210					res @ Ok(_) => {
211						println!("       {} ({}): ok", name, start);
212						res
213					},
214					Err(err) => {
215						println!("       {} ({}): error", name, start);
216						match err {
217							Error::Custom { .. } => Err(err),
218							_ => Err(Error::Custom {
219								message: format!("failed to parse {}", name),
220								position: start,
221								inner: Some(Box::new(err)),
222							}),
223						}
224					},
225				}
226			},
227		)
228	}
229
230	/// Mark parser as expected, abort early when failed in ordered choice.
231	pub fn expect(self, name: &'a str) -> Self
232	where
233		O: 'a,
234	{
235		Parser::new(
236			move |input: &'a [I], start: usize| match (self.method)(input, start) {
237				res @ Ok(_) => res,
238				Err(err) => Err(Error::Expect {
239					message: format!("Expect {}", name),
240					position: start,
241					inner: Box::new(err),
242				}),
243			},
244		)
245	}
246}
247
248/// Always succeeds, consume no input.
249pub fn empty<'a, I>() -> Parser<'a, I, ()> {
250	Parser::new(|_: &[I], start: usize| Ok(((), start)))
251}
252
253/// Match any symbol.
254pub fn any<'a, I>() -> Parser<'a, I, I>
255where
256	I: Clone,
257{
258	Parser::new(|input: &[I], start: usize| {
259		let Some(s) = input.get(start) else {
260			return Err(Error::Mismatch {
261				message: "end of input reached".to_owned(),
262				position: start,
263			})
264		};
265		Ok((s.clone(), start + 1))
266	})
267}
268
269/// Success when current input symbol equals `t`.
270pub fn sym<'a, I>(t: I) -> Parser<'a, I, I>
271where
272	I: Clone + PartialEq + Display,
273{
274	Parser::new(move |input: &'a [I], start: usize| {
275		let Some(s) = input.get(start) else { return Err(Error::Incomplete) };
276		if t != *s {
277			return Err(Error::Mismatch {
278				message: format!("expect: {}, found: {}", t, s),
279				position: start,
280			});
281		}
282		Ok((s.clone(), start + 1))
283	})
284}
285
286/// Success when sequence of symbols matches current input.
287pub fn seq<'a, 'b: 'a, I>(tag: &'b [I]) -> Parser<'a, I, &'a [I]>
288where
289	I: PartialEq + Debug,
290{
291	Parser::new(move |input: &'a [I], start: usize| {
292		let mut index = 0;
293		loop {
294			let pos = start + index;
295			if index == tag.len() {
296				return Ok((tag, pos));
297			}
298			let Some(s) = input.get(pos) else { return Err(Error::Incomplete) };
299			if tag[index] != *s {
300				return Err(Error::Mismatch {
301					message: format!("seq {:?} expect: {:?}, found: {:?}", tag, tag[index], s),
302					position: pos,
303				});
304			}
305			index += 1;
306		}
307	})
308}
309
310/// Success when tag matches current input.
311pub fn tag<'a, 'b: 'a>(tag: &'b str) -> Parser<'a, char, &'a str> {
312	Parser::new(move |input: &'a [char], start: usize| {
313		let mut pos = start;
314		for c in tag.chars() {
315			let Some(&s) = input.get(pos) else { return Err(Error::Incomplete) };
316			if c != s {
317				return Err(Error::Mismatch {
318					message: format!("tag {:?} expect: {:?}, found: {}", tag, c, s),
319					position: pos,
320				});
321			}
322			pos += 1;
323		}
324		Ok((tag, pos))
325	})
326}
327
328/// Parse separated list.
329pub fn list<'a, I, O, U>(
330	parser: Parser<'a, I, O>,
331	separator: Parser<'a, I, U>,
332) -> Parser<'a, I, Vec<O>>
333where
334	O: 'a,
335	U: 'a,
336{
337	Parser::new(move |input: &'a [I], start: usize| {
338		let mut items = vec![];
339		let mut pos = start;
340		if let Ok((first_item, first_pos)) = (parser.method)(input, pos) {
341			items.push(first_item);
342			pos = first_pos;
343			while let Ok((_, sep_pos)) = (separator.method)(input, pos) {
344				match (parser.method)(input, sep_pos) {
345					Ok((more_item, more_pos)) => {
346						items.push(more_item);
347						pos = more_pos;
348					}
349					Err(_) => break,
350				}
351			}
352		}
353		Ok((items, pos))
354	})
355}
356
357/// Success when current input symbol is one of the set.
358pub fn one_of<'a, I, S>(set: &'a S) -> Parser<'a, I, I>
359where
360	I: Clone + PartialEq + Display + Debug,
361	S: Set<I> + ?Sized,
362{
363	Parser::new(move |input: &'a [I], start: usize| {
364		let Some(s) = input.get(start) else {return  Err(Error::Incomplete) };
365		if !set.contains(s) {
366			return Err(Error::Mismatch {
367				message: format!("expect one of: {}, found: {}", set.to_str(), s),
368				position: start,
369			});
370		};
371		Ok((s.clone(), start + 1))
372	})
373}
374
375/// Success when current input symbol is none of the set.
376pub fn none_of<'a, I, S>(set: &'static S) -> Parser<'a, I, I>
377where
378	I: Clone + PartialEq + Display + Debug,
379	S: Set<I> + ?Sized,
380{
381	Parser::new(move |input: &'a [I], start: usize| {
382		let Some(s) = input.get(start) else {return Err(Error::Incomplete) };
383		if set.contains(s) {
384			return Err(Error::Mismatch {
385				message: format!("expect none of: {}, found: {}", set.to_str(), s),
386				position: start,
387			});
388		}
389		Ok((s.clone(), start + 1))
390	})
391}
392
393/// Success when predicate returns true on current input symbol.
394pub fn is_a<'a, I, F>(predicate: F) -> Parser<'a, I, I>
395where
396	I: Clone + PartialEq + Display + Debug,
397	F: Fn(I) -> bool + 'a,
398{
399	Parser::new(move |input: &'a [I], start: usize| {
400		let Some(s) = input.get(start) else { return Err(Error::Incomplete) };
401		if !predicate(s.clone()) {
402			return Err(Error::Mismatch {
403				message: format!("is_a predicate failed on: {}", s),
404				position: start,
405			});
406		}
407		Ok((s.clone(), start + 1))
408	})
409}
410
411/// Success when predicate returns false on current input symbol.
412pub fn not_a<'a, I, F>(predicate: F) -> Parser<'a, I, I>
413where
414	I: Clone + PartialEq + Display + Debug,
415	F: Fn(I) -> bool + 'a,
416{
417	Parser::new(move |input: &'a [I], start: usize| {
418		let Some(s) = input.get(start) else { return Err(Error::Incomplete) };
419		if predicate(s.clone()) {
420			return Err(Error::Mismatch {
421				message: format!("not_a predicate failed on: {}", s),
422				position: start,
423			});
424		}
425		Ok((s.clone(), start + 1))
426	})
427}
428
429/// Read n symbols.
430pub fn take<'a, I>(n: usize) -> Parser<'a, I, &'a [I]> {
431	Parser::new(move |input: &'a [I], start: usize| {
432		let pos = start + n;
433		if input.len() < pos {
434			return Err(Error::Incomplete);
435		}
436		Ok((&input[start..pos], pos))
437	})
438}
439
440/// Skip n symbols.
441pub fn skip<'a, I>(n: usize) -> Parser<'a, I, ()> {
442	Parser::new(move |input: &'a [I], start: usize| {
443		let pos = start + n;
444		if input.len() < pos {
445			return Err(Error::Incomplete);
446		}
447		Ok(((), pos))
448	})
449}
450
451/// Call a parser factory, can be used to create recursive parsers.
452pub fn call<'a, I, O, F>(parser_factory: F) -> Parser<'a, I, O>
453where
454	O: 'a,
455	F: Fn() -> Parser<'a, I, O> + 'a,
456{
457	Parser::new(move |input: &'a [I], start: usize| {
458		let parser = parser_factory();
459		(parser.method)(input, start)
460	})
461}
462
463/// Success when end of input is reached.
464pub fn end<'a, I>() -> Parser<'a, I, ()>
465where
466	I: Display,
467{
468	Parser::new(|input: &'a [I], start: usize| {
469		if let Some(s) = input.get(start) {
470			return Err(Error::Mismatch {
471				message: format!("expect end of input, found: {}", s),
472				position: start,
473			});
474		}
475		Ok(((), start))
476	})
477}
478
479/// Sequence reserve value
480impl<'a, I, O: 'a, U: 'a> Add<Parser<'a, I, U>> for Parser<'a, I, O> {
481	type Output = Parser<'a, I, (O, U)>;
482
483	fn add(self, other: Parser<'a, I, U>) -> Self::Output {
484		Parser::new(move |input: &'a [I], start: usize| {
485			(self.method)(input, start).and_then(|(out1, pos1)| {
486				(other.method)(input, pos1).map(|(out2, pos2)| ((out1, out2), pos2))
487			})
488		})
489	}
490}
491
492/// Sequence discard second value
493impl<'a, I, O: 'a, U: 'a> Sub<Parser<'a, I, U>> for Parser<'a, I, O> {
494	type Output = Parser<'a, I, O>;
495
496	fn sub(self, other: Parser<'a, I, U>) -> Self::Output {
497		Parser::new(move |input: &'a [I], start: usize| {
498			(self.method)(input, start)
499				.and_then(|(out1, pos1)| (other.method)(input, pos1).map(|(_, pos2)| (out1, pos2)))
500		})
501	}
502}
503
504/// Sequence discard first value
505impl<'a, I: 'a, O: 'a, U: 'a> Mul<Parser<'a, I, U>> for Parser<'a, I, O> {
506	type Output = Parser<'a, I, U>;
507
508	fn mul(self, other: Parser<'a, I, U>) -> Self::Output {
509		Parser::new(move |input: &'a [I], start: usize| {
510			(self.method)(input, start)
511				.and_then(|(_, pos1)| (other.method)(input, pos1).map(|(out2, pos2)| (out2, pos2)))
512		})
513	}
514}
515
516/// Chain two parsers where the second parser depends on the first's result.
517impl<'a, I, O: 'a, U: 'a, F: Fn(O) -> Parser<'a, I, U> + 'a> Shr<F> for Parser<'a, I, O> {
518	type Output = Parser<'a, I, U>;
519
520	fn shr(self, other: F) -> Self::Output {
521		Parser::new(move |input: &'a [I], start: usize| {
522			(self.method)(input, start).and_then(|(out, pos)| (other(out).method)(input, pos))
523		})
524	}
525}
526
527/// Ordered choice
528impl<'a, I, O: 'a> BitOr for Parser<'a, I, O> {
529	type Output = Parser<'a, I, O>;
530
531	fn bitor(self, other: Parser<'a, I, O>) -> Self::Output {
532		Parser::new(
533			move |input: &'a [I], start: usize| match (self.method)(input, start) {
534				Ok(out) => Ok(out),
535				Err(err) => match err {
536					Error::Expect { .. } => Err(err),
537					_ => (other.method)(input, start),
538				},
539			},
540		)
541	}
542}
543
544/// And predicate
545impl<'a, I, O: 'a> Neg for Parser<'a, I, O> {
546	type Output = Parser<'a, I, bool>;
547
548	fn neg(self) -> Self::Output {
549		Parser::new(move |input: &'a [I], start: usize| {
550			(self.method)(input, start).map(|_| (true, start))
551		})
552	}
553}
554
555/// Not predicate
556impl<'a, I, O: 'a> Not for Parser<'a, I, O> {
557	type Output = Parser<'a, I, bool>;
558
559	fn not(self) -> Self::Output {
560		Parser::new(
561			move |input: &'a [I], start: usize| match (self.method)(input, start) {
562				Ok(_) => Err(Error::Mismatch {
563					message: "not predicate failed".to_string(),
564					position: start,
565				}),
566				Err(_) => Ok((true, start)),
567			},
568		)
569	}
570}
571
572#[cfg(test)]
573mod tests {
574	use crate::parser::*;
575	use crate::Error;
576
577	#[test]
578	fn byte_works() {
579		let input = b"abcde";
580		let parser = sym(b'a') + one_of(b"ab") - sym(b'C');
581		let output = parser.parse(input);
582		assert_eq!(
583			output,
584			Err(Error::Mismatch {
585				message: "expect: 67, found: 99".to_string(),
586				position: 2
587			})
588		);
589
590		let parser = sym(b'a') * none_of(b"AB") - sym(b'c') + seq(b"de");
591		let output = parser.parse(input);
592		assert_eq!(output, Ok((b'b', &b"de"[..])));
593		assert_eq!(parser.pos().parse(input), Ok(5));
594
595		let parser = sym(b'e') | sym(b'd').expect("d") | empty().map(|_| b'0');
596		let output = parser.parse(input);
597		assert_eq!(
598			output,
599			Err(Error::Expect {
600				message: "Expect d".to_owned(),
601				position: 0,
602				inner: Box::new(Error::Mismatch {
603					message: "expect: 100, found: 97".to_string(),
604					position: 0
605				})
606			})
607		);
608	}
609
610	#[test]
611	fn char_works() {
612		let input = "abcd".chars().collect::<Vec<char>>();
613		let parser = tag("ab") + sym('c') | sym('d').map(|_| ("", '0'));
614		let output = parser.parse(&input);
615		assert_eq!(output, Ok(("ab", 'c')));
616	}
617
618	#[test]
619	fn recursive_parser() {
620		#[derive(Debug, PartialEq)]
621		enum Expr {
622			Empty,
623			Group(Box<Expr>),
624		}
625		fn expr() -> Parser<'static, u8, Expr> {
626			(sym(b'(') + call(expr) - sym(b')')).map(|(_, e)| Expr::Group(Box::new(e)))
627				| empty().map(|_| Expr::Empty)
628		}
629		let input = b"(())";
630		let parser = expr();
631		let output = parser.parse(input);
632		assert_eq!(
633			output,
634			Ok(Expr::Group(Box::new(Expr::Group(Box::new(Expr::Empty)))))
635		);
636	}
637
638	#[test]
639	fn chain_parser() {
640		let input = b"5oooooooo";
641		{
642			let parser = one_of(b"0123456789").map(|c| c - b'0')
643				>> |n| take(n as usize) + sym(b'o').repeat(0..);
644			assert_eq!(parser.parse(input), Ok((&b"ooooo"[..], vec![b'o'; 3])));
645		}
646		{
647			let parser =
648				skip(1) * take(3) >> |v: &'static [u8]| take(v.len() + 2).map(move |u| (u, v));
649			assert_eq!(parser.parse(input), Ok((&b"ooooo"[..], &b"ooo"[..])));
650		}
651		{
652			let parser = Parser::new(move |input, start| {
653				(skip(1) * take(3))
654					.parse_at(input, start)
655					.and_then(|(v, pos)| {
656						take(v.len() + 2)
657							.parse_at(input, pos)
658							.map(|(u, end)| ((u, v), end))
659					})
660			});
661			assert_eq!(parser.parse(input), Ok((&b"ooooo"[..], &b"ooo"[..])));
662		}
663	}
664
665	#[test]
666	fn repeat_at_least() {
667		let input = b"xxxooo";
668
669		{
670			let parser = sym(b'x').repeat(1..2);
671			let output = parser.parse(input);
672			assert_eq!(output, Ok(vec![b'x'; 1]))
673		}
674
675		{
676			let parser = sym(b'x').repeat(1..);
677			let output = parser.parse(input);
678			assert_eq!(output, Ok(vec![b'x'; 3]))
679		}
680
681		{
682			let parser = sym(b'x').repeat(0..);
683			let output = parser.parse(input);
684			assert_eq!(output, Ok(vec![b'x'; 3]))
685		}
686
687		{
688			let parser = sym(b'y').repeat(0..);
689			let output = parser.parse(input);
690			assert_eq!(output, Ok(vec![]))
691		}
692
693		{
694			let parser = sym(b'y').repeat(1..);
695			let output = parser.parse(input);
696			assert!(output.is_err());
697		}
698
699		{
700			let parser = sym(b'x').repeat(10..);
701			let output = parser.parse(input);
702			assert!(output.is_err());
703		}
704	}
705
706	#[test]
707	fn repeat_up_to() {
708		let input = b"xxxooo";
709
710		{
711			let parser = sym(b'x').repeat(..2);
712			let output = parser.parse(input);
713			assert_eq!(output, Ok(vec![b'x'; 1]))
714		}
715
716		{
717			let parser = sym(b'x').repeat(..4);
718			let output = parser.parse(input);
719			assert_eq!(output, Ok(vec![b'x'; 3]))
720		}
721
722		{
723			let parser = sym(b'x').repeat(..);
724			let output = parser.parse(input);
725			assert_eq!(output, Ok(vec![b'x'; 3]))
726		}
727
728		{
729			let parser = sym(b'x').repeat(..0);
730			let output = parser.parse(input);
731			assert_eq!(output, Ok(vec![]))
732		}
733
734		{
735			let parser = sym(b'x').repeat(..10);
736			let output = parser.parse(input);
737			assert_eq!(output, Ok(vec![b'x'; 3]))
738		}
739	}
740
741	#[test]
742	fn repeat_up_to_inclusive() {
743		let input = b"xxxooo";
744
745		{
746			let parser = sym(b'x').repeat(..=2);
747			let output = parser.parse(input);
748			assert_eq!(output, Ok(vec![b'x'; 2]))
749		}
750
751		{
752			let parser = sym(b'x').repeat(..=4);
753			let output = parser.parse(input);
754			assert_eq!(output, Ok(vec![b'x'; 3]))
755		}
756
757		{
758			let parser = sym(b'x').repeat(..=0);
759			let output = parser.parse(input);
760			assert_eq!(output, Ok(vec![]))
761		}
762
763		{
764			let parser = sym(b'x').repeat(..=10);
765			let output = parser.parse(input);
766			assert_eq!(output, Ok(vec![b'x'; 3]))
767		}
768	}
769
770	#[test]
771	fn repeat_from_to_inclusive() {
772		let input = b"xxxooo";
773
774		{
775			let parser = sym(b'x').repeat(1..=2);
776			let output = parser.parse(input);
777			assert_eq!(output, Ok(vec![b'x'; 2]))
778		}
779
780		{
781			let parser = sym(b'x').repeat(1..=4);
782			let output = parser.parse(input);
783			assert_eq!(output, Ok(vec![b'x'; 3]))
784		}
785
786		{
787			let parser = sym(b'x').repeat(0..=0);
788			let output = parser.parse(input);
789			assert_eq!(output, Ok(vec![]))
790		}
791
792		{
793			let parser = sym(b'x').repeat(3..=10);
794			let output = parser.parse(input);
795			assert_eq!(output, Ok(vec![b'x'; 3]))
796		}
797
798		{
799			let parser = sym(b'x').repeat(4..=10);
800			let output = parser.parse(input);
801			assert!(output.is_err())
802		}
803	}
804
805	#[test]
806	fn repeat_exactly() {
807		let input = b"xxxooo";
808
809		{
810			let parser = sym(b'x').repeat(0);
811			let output = parser.parse(input);
812			assert_eq!(output, Ok(vec![]))
813		}
814
815		{
816			let parser = sym(b'x').repeat(1);
817			let output = parser.parse(input);
818			assert_eq!(output, Ok(vec![b'x'; 1]))
819		}
820
821		{
822			let parser = sym(b'x').repeat(2);
823			let output = parser.parse(input);
824			assert_eq!(output, Ok(vec![b'x'; 2]))
825		}
826
827		{
828			let parser = sym(b'x').repeat(3);
829			let output = parser.parse(input);
830			assert_eq!(output, Ok(vec![b'x'; 3]))
831		}
832
833		{
834			let parser = sym(b'x').repeat(4);
835			let output = parser.parse(input);
836			assert!(output.is_err())
837		}
838	}
839
840	#[cfg(not(feature = "trace"))]
841	#[test]
842	fn named() {
843		let input = b"xxxooo";
844
845		{
846			let parser = sym(b'x').repeat(3);
847			let output = parser.name("name_test_ok").parse(input);
848			assert_eq!(output, Ok(vec![b'x'; 3]))
849		}
850
851		{
852			let parser = sym(b'x').repeat(4);
853			let output = parser.name("name_test_err").parse(input);
854			assert_eq!(output, Err(
855				Error::Custom {
856					message: "failed to parse name_test_err".into(),
857					position: 0,
858					inner: Some(Box::new(Error::Mismatch {
859						message: "expect repeat at least 4 times, found 3 times".into(),
860						position: 0 
861					}))
862				}
863			))
864		}
865	} 
866
867	#[cfg(feature = "trace")]
868	#[test]
869	// Note: this doesn't test the tracing per se, just that the `name()` method executes
870	// in the same way when the feature is turned on.
871	fn named() {
872		let input = b"xxxooo";
873
874		{
875			let parser = sym(b'x').repeat(3);
876			let output = parser.name("name_test_ok").parse(input);
877			assert_eq!(output, Ok(vec![b'x'; 3]))
878		}
879
880		{
881			let parser = sym(b'x').repeat(4);
882			let output = parser.name("name_test_err").parse(input);
883			assert_eq!(output, Err(
884				Error::Custom {
885					message: "failed to parse name_test_err".into(),
886					position: 0,
887					inner: Some(Box::new(Error::Mismatch {
888						message: "expect repeat at least 4 times, found 3 times".into(),
889						position: 0 
890					}))
891				}
892			))
893		}
894	} 
895}