summaryrefslogtreecommitdiff
path: root/pest_consume
diff options
context:
space:
mode:
Diffstat (limited to 'pest_consume')
-rw-r--r--pest_consume/src/lib.rs95
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(),
+ }
+ }
+}