diff options
Diffstat (limited to '')
-rw-r--r-- | pest_consume/src/lib.rs | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/pest_consume/src/lib.rs b/pest_consume/src/lib.rs index 6e4b2e3..70aee56 100644 --- a/pest_consume/src/lib.rs +++ b/pest_consume/src/lib.rs @@ -5,7 +5,7 @@ use pest::Span; pub use pest_consume_macros::{make_parser, parse_children}; /// Carries a pest Pair alongside custom user data. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct ParseInput<'input, 'data, Rule, Data> where Rule: pest::RuleType, @@ -14,6 +14,16 @@ where user_data: &'data Data, } +/// Iterator over `ParseInput`s. It is created by `ParseInput::children`. +#[derive(Debug)] +pub struct ParseInputs<'input, 'data, Rule, Data> +where + Rule: pest::RuleType, +{ + input: ParseInput<'input, 'data, Rule, Data>, + pairs: pest::iterators::Pairs<'input, Rule>, +} + impl<'input, 'data, Rule, Data> ParseInput<'input, 'data, Rule, Data> where Rule: pest::RuleType, @@ -50,6 +60,15 @@ where } None } + /// Return an iterator over the children of this input + // Can't use `-> impl Iterator` because of weird lifetime limitations + // (see https://github.com/rust-lang/rust/issues/61997). + pub fn children(&self) -> ParseInputs<'input, 'data, Rule, Data> { + ParseInputs { + input: self.clone(), + pairs: self.as_pair().clone().into_inner(), + } + } pub fn user_data(&self) -> &'data Data { self.user_data @@ -66,6 +85,28 @@ where pub fn as_rule(&self) -> Rule { self.pair.as_rule() } + pub fn as_rule_alias<T>(&self) -> String + where + T: PestConsumer<Rule = Rule>, + { + T::rule_alias(self.as_rule()) + } +} + +impl<'input, 'data, Rule, Data> ParseInputs<'input, 'data, Rule, Data> +where + Rule: pest::RuleType, +{ + /// Create an error that points to the span of the input. + pub fn error(&self, message: String) -> Error<Rule> { + self.input.error(message) + } + pub fn aliased_rules<T>(&self) -> Vec<String> + where + T: PestConsumer<Rule = Rule>, + { + self.clone().map(|p| p.as_rule_alias::<T>()).collect() + } } /// Used by the macros. @@ -121,3 +162,55 @@ fn debug_pair<Rule: pest::RuleType>(pair: Pair<Rule>) -> String { aux(&mut s, 0, "".into(), pair); s } + +impl<'input, 'data, Rule, Data> Iterator + for ParseInputs<'input, 'data, Rule, Data> +where + Rule: pest::RuleType, +{ + type Item = ParseInput<'input, 'data, Rule, Data>; + + fn next(&mut self) -> Option<Self::Item> { + let child_pair = self.pairs.next()?; + let child = self.input.with_pair(child_pair); + Some(child) + } +} + +impl<'input, 'data, Rule, Data> DoubleEndedIterator + for ParseInputs<'input, 'data, Rule, Data> +where + Rule: pest::RuleType, +{ + fn next_back(&mut self) -> Option<Self::Item> { + let child_pair = self.pairs.next_back()?; + let child = self.input.with_pair(child_pair); + Some(child) + } +} + +// Manual impl to avoid stupid `Data: Clone` trait bound +impl<'input, 'data, Rule, Data> Clone for ParseInput<'input, 'data, Rule, Data> +where + Rule: pest::RuleType, +{ + fn clone(&self) -> Self { + ParseInput { + pair: self.pair.clone(), + user_data: self.user_data, + } + } +} + +// Manual impl to avoid stupid `Data: Clone` trait bound +impl<'input, 'data, Rule, Data> Clone for ParseInputs<'input, 'data, Rule, Data> +where + Rule: pest::RuleType, +{ + fn clone(&self) -> Self { + ParseInputs { + input: self.input.clone(), + pairs: self.pairs.clone(), + } + } +} |