diff options
Diffstat (limited to '')
-rw-r--r-- | pest_consume/src/lib.rs | 302 |
1 files changed, 159 insertions, 143 deletions
diff --git a/pest_consume/src/lib.rs b/pest_consume/src/lib.rs index 62361f2..701fbba 100644 --- a/pest_consume/src/lib.rs +++ b/pest_consume/src/lib.rs @@ -1,183 +1,199 @@ -use pest::error::{Error, ErrorVariant}; -use pest::iterators::{Pair, Pairs}; +use pest::error::Error; use pest::Parser as PestParser; -use pest::{RuleType, Span}; +use pest::RuleType; -pub use pest_consume_macros::make_parser; #[proc_macro_hack::proc_macro_hack] pub use pest_consume_macros::match_inputs; +pub use pest_consume_macros::parser; static UNIT: () = (); -/// Carries a pest Pair alongside custom user data. -#[derive(Debug)] -pub struct ParseInput<'input, 'data, Rule: RuleType, Data> { - pair: Pair<'input, Rule>, - user_data: &'data Data, -} - -/// Iterator over `ParseInput`s. It is created by `ParseInput::children` or `ParseInputs::new`. -#[derive(Debug)] -pub struct ParseInputs<'input, 'data, Rule: RuleType, Data> { - pairs: Pairs<'input, Rule>, - span: Span<'input>, - user_data: &'data Data, -} +mod node { + use super::Parser; + use pest::error::{Error, ErrorVariant}; + use pest::iterators::{Pair, Pairs}; + use pest::Parser as PestParser; + use pest::{RuleType, Span}; -impl<'i, 'd, R: RuleType, D> ParseInput<'i, 'd, R, D> { - pub fn new(pair: Pair<'i, R>, user_data: &'d D) -> Self { - ParseInput { pair, user_data } + /// Carries a pest Pair alongside custom user data. + #[derive(Debug)] + pub struct Node<'input, 'data, Rule: RuleType, Data> { + pair: Pair<'input, Rule>, + user_data: &'data Data, } - /// Create an error that points to the span of the input. - pub fn error(&self, message: String) -> Error<R> { - Error::new_from_span( - ErrorVariant::CustomError { message }, - self.as_span(), - ) + + /// Iterator over `Node`s. It is created by `Node::children` or `Nodes::new`. + #[derive(Debug)] + pub struct Nodes<'input, 'data, Rule: RuleType, Data> { + pairs: Pairs<'input, Rule>, + span: Span<'input>, + user_data: &'data Data, } - /// Reconstruct the input with a new pair, passing the user data along. - pub fn with_pair(&self, new_pair: Pair<'i, R>) -> Self { - ParseInput { - pair: new_pair, - user_data: self.user_data, + + impl<'i, 'd, R: RuleType, D> Node<'i, 'd, R, D> { + pub fn new(pair: Pair<'i, R>, user_data: &'d D) -> Self { + Node { pair, user_data } } - } - /// If the contained pair has exactly one child, return a new Self containing it. - pub fn single_child(&self) -> Option<Self> { - let mut children = self.pair.clone().into_inner(); - if let Some(child) = children.next() { - if children.next().is_none() { - return Some(self.with_pair(child)); + /// Create an error that points to the span of the input. + pub fn error(&self, message: String) -> Error<R> { + Error::new_from_span( + ErrorVariant::CustomError { message }, + self.as_span(), + ) + } + /// Reconstruct the input with a new pair, passing the user data along. + pub fn with_pair(&self, new_pair: Pair<'i, R>) -> Self { + Node { + pair: new_pair, + user_data: self.user_data, } } - 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<'i, 'd, R, D> { - ParseInputs { - pairs: self.as_pair().clone().into_inner(), - span: self.as_span(), - user_data: self.user_data(), + /// If the contained pair has exactly one child, return a new Self containing it. + pub fn single_child(&self) -> Option<Self> { + let mut children = self.pair.clone().into_inner(); + if let Some(child) = children.next() { + if children.next().is_none() { + return Some(self.with_pair(child)); + } + } + 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) -> Nodes<'i, 'd, R, D> { + Nodes { + pairs: self.as_pair().clone().into_inner(), + span: self.as_span(), + user_data: self.user_data(), + } } - } - pub fn user_data(&self) -> &'d D { - self.user_data - } - pub fn as_pair(&self) -> &Pair<'i, R> { - &self.pair - } - pub fn as_span(&self) -> Span<'i> { - self.pair.as_span() - } - pub fn as_str(&self) -> &'i str { - self.pair.as_str() - } - pub fn as_rule(&self) -> R { - self.pair.as_rule() + pub fn user_data(&self) -> &'d D { + self.user_data + } + pub fn as_pair(&self) -> &Pair<'i, R> { + &self.pair + } + pub fn as_span(&self) -> Span<'i> { + self.pair.as_span() + } + pub fn as_str(&self) -> &'i str { + self.pair.as_str() + } + pub fn as_rule(&self) -> R { + self.pair.as_rule() + } + pub fn as_aliased_rule<C>(&self) -> C::AliasedRule + where + C: Parser<Rule = R>, + <C as Parser>::Parser: PestParser<R>, + { + C::rule_alias(self.as_rule()) + } } - pub fn as_rule_alias<C>(&self) -> C::AliasedRule - where - C: PestConsumer<Rule = R>, - <C as PestConsumer>::Parser: PestParser<R>, - { - C::rule_alias(self.as_rule()) + + impl<'i, 'd, R: RuleType, D> Nodes<'i, 'd, R, D> { + /// `input` must be the _original_ input that `pairs` is pointing to. + pub fn new( + input: &'i str, + pairs: Pairs<'i, R>, + user_data: &'d D, + ) -> Self { + let span = Span::new(input, 0, input.len()).unwrap(); + Nodes { + pairs, + span, + user_data, + } + } + /// Create an error that points to the span of the input. + pub fn error(&self, message: String) -> Error<R> { + Error::new_from_span( + ErrorVariant::CustomError { message }, + self.span.clone(), + ) + } + pub fn aliased_rules<C>(&self) -> Vec<C::AliasedRule> + where + C: Parser<Rule = R>, + <C as Parser>::Parser: PestParser<R>, + { + self.clone().map(|p| p.as_aliased_rule::<C>()).collect() + } + /// Reconstruct the input with a new pair, passing the user data along. + fn with_pair(&self, new_pair: Pair<'i, R>) -> Node<'i, 'd, R, D> { + Node::new(new_pair, self.user_data) + } } -} -impl<'i, 'd, R: RuleType, D> ParseInputs<'i, 'd, R, D> { - /// `input` must be the _original_ input that `pairs` is pointing to. - pub fn new(input: &'i str, pairs: Pairs<'i, R>, user_data: &'d D) -> Self { - let span = Span::new(input, 0, input.len()).unwrap(); - ParseInputs { - pairs, - span, - user_data, + impl<'i, 'd, R: RuleType, D> Iterator for Nodes<'i, 'd, R, D> { + type Item = Node<'i, 'd, R, D>; + + fn next(&mut self) -> Option<Self::Item> { + let child_pair = self.pairs.next()?; + let child = self.with_pair(child_pair); + Some(child) } } - /// Create an error that points to the span of the input. - pub fn error(&self, message: String) -> Error<R> { - Error::new_from_span( - ErrorVariant::CustomError { message }, - self.span.clone(), - ) + + impl<'i, 'd, R: RuleType, D> DoubleEndedIterator for Nodes<'i, 'd, R, D> { + fn next_back(&mut self) -> Option<Self::Item> { + let child_pair = self.pairs.next_back()?; + let child = self.with_pair(child_pair); + Some(child) + } } - pub fn aliased_rules<C>(&self) -> Vec<C::AliasedRule> - where - C: PestConsumer<Rule = R>, - <C as PestConsumer>::Parser: PestParser<R>, - { - self.clone().map(|p| p.as_rule_alias::<C>()).collect() + + // Manual impl to avoid stupid `D: Clone` trait bound + impl<'i, 'd, R: RuleType, D> Clone for Node<'i, 'd, R, D> { + fn clone(&self) -> Self { + Node { + pair: self.pair.clone(), + user_data: self.user_data, + } + } } - /// Reconstruct the input with a new pair, passing the user data along. - fn with_pair(&self, new_pair: Pair<'i, R>) -> ParseInput<'i, 'd, R, D> { - ParseInput::new(new_pair, self.user_data) + + // Manual impl to avoid stupid `D: Clone` trait bound + impl<'i, 'd, R: RuleType, D> Clone for Nodes<'i, 'd, R, D> { + fn clone(&self) -> Self { + Nodes { + pairs: self.pairs.clone(), + span: self.span.clone(), + user_data: self.user_data, + } + } } } +pub use node::{Node, Nodes}; + /// Used by the macros. -pub trait PestConsumer { +/// Do not implement manually. +pub trait Parser { type Rule: RuleType; type AliasedRule: RuleType; type Parser: PestParser<Self::Rule>; + fn rule_alias(rule: Self::Rule) -> Self::AliasedRule; fn allows_shortcut(rule: Self::Rule) -> bool; - fn parse_with_userdata<'i, 'd, D>( - rule: Self::Rule, - input_str: &'i str, - user_data: &'d D, - ) -> Result<ParseInputs<'i, 'd, Self::Rule, D>, Error<Self::Rule>> { - let pairs = Self::Parser::parse(rule, input_str)?; - Ok(ParseInputs::new(input_str, pairs, user_data)) - } - + /// Parses a `&str` starting from `rule` fn parse<'i>( rule: Self::Rule, input_str: &'i str, - ) -> Result<ParseInputs<'i, 'static, Self::Rule, ()>, Error<Self::Rule>> - { + ) -> Result<Nodes<'i, 'static, Self::Rule, ()>, Error<Self::Rule>> { Self::parse_with_userdata(rule, input_str, &UNIT) } -} - -impl<'i, 'd, R: RuleType, D> Iterator for ParseInputs<'i, 'd, R, D> { - type Item = ParseInput<'i, 'd, R, D>; - - fn next(&mut self) -> Option<Self::Item> { - let child_pair = self.pairs.next()?; - let child = self.with_pair(child_pair); - Some(child) - } -} - -impl<'i, 'd, R: RuleType, D> DoubleEndedIterator for ParseInputs<'i, 'd, R, D> { - fn next_back(&mut self) -> Option<Self::Item> { - let child_pair = self.pairs.next_back()?; - let child = self.with_pair(child_pair); - Some(child) - } -} - -// Manual impl to avoid stupid `D: Clone` trait bound -impl<'i, 'd, R: RuleType, D> Clone for ParseInput<'i, 'd, R, D> { - fn clone(&self) -> Self { - ParseInput { - pair: self.pair.clone(), - user_data: self.user_data, - } - } -} -// Manual impl to avoid stupid `D: Clone` trait bound -impl<'i, 'd, R: RuleType, D> Clone for ParseInputs<'i, 'd, R, D> { - fn clone(&self) -> Self { - ParseInputs { - pairs: self.pairs.clone(), - span: self.span.clone(), - user_data: self.user_data, - } + /// Parses a `&str` starting from `rule`, carrying `user_data` through the parser methods. + fn parse_with_userdata<'i, 'd, D>( + rule: Self::Rule, + input_str: &'i str, + user_data: &'d D, + ) -> Result<Nodes<'i, 'd, Self::Rule, D>, Error<Self::Rule>> { + let pairs = Self::Parser::parse(rule, input_str)?; + Ok(Nodes::new(input_str, pairs, user_data)) } } |