From 2ff14448863ac1a1dd9533461708e29aae170c2d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:06:31 +0200 Subject: Adding debian version 1.65.0+dfsg1-2. Signed-off-by: Daniel Baumann --- vendor/pest/src/prec_climber.rs | 171 ++++++++++++++++++++++++++++++++++------ 1 file changed, 149 insertions(+), 22 deletions(-) (limited to 'vendor/pest/src/prec_climber.rs') diff --git a/vendor/pest/src/prec_climber.rs b/vendor/pest/src/prec_climber.rs index d8bf0a08a..d35bd52db 100644 --- a/vendor/pest/src/prec_climber.rs +++ b/vendor/pest/src/prec_climber.rs @@ -9,12 +9,96 @@ //! Constructs useful in infix operator parsing with the precedence climbing method. -use std::collections::HashMap; -use std::iter::Peekable; -use std::ops::BitOr; +use alloc::borrow::Cow; +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::iter::Peekable; +use core::ops::BitOr; -use iterators::Pair; -use RuleType; +use crate::iterators::Pair; +use crate::RuleType; + +/// Macro for more convenient const fn definition of `prec_climber::PrecClimber`. +/// +/// # Examples +/// +/// ``` +/// # use pest::prec_climber::{Assoc, PrecClimber}; +/// # use pest::prec_climber; +/// # #[allow(non_camel_case_types)] +/// # #[allow(dead_code)] +/// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +/// # enum Rule { +/// # plus, +/// # minus, +/// # times, +/// # divide, +/// # power +/// # } +/// static CLIMBER: PrecClimber = prec_climber![ +/// L plus | minus, +/// L times | divide, +/// R power, +/// ]; +/// ``` +#[cfg(feature = "const_prec_climber")] +#[macro_export] +macro_rules! prec_climber { + ( + $( $assoc:ident $rule:ident $( | $rules:ident )* ),+ $(,)? + ) => {{ + prec_climber!( + @precedences { 1u32 } + $( [ $rule $( $rules )* ] )* + ); + + $crate::prec_climber::PrecClimber::new_const( + prec_climber!( + @array + $( $assoc $rule $(, $assoc $rules )* ),* + ) + ) + }}; + + ( @assoc L ) => { $crate::prec_climber::Assoc::Left }; + ( @assoc R ) => { $crate::prec_climber::Assoc::Right }; + + ( + @array + $( + $assoc:ident $rule:ident + ),* + ) => { + &[ + $( + ( + Rule::$rule, + $rule, + prec_climber!( @assoc $assoc ), + ) + ),* + ] + }; + + ( + @precedences { $precedence:expr } + ) => {}; + + ( + @precedences { $precedence:expr } + [ $( $rule:ident )* ] + $( [ $( $rules:ident )* ] )* + ) => { + $( + #[allow(non_upper_case_globals)] + const $rule: u32 = $precedence; + )* + prec_climber!( + @precedences { 1u32 + $precedence } + $( [ $( $rules )* ] )* + ); + }; +} /// Associativity of an [`Operator`]. /// @@ -86,11 +170,54 @@ impl BitOr for Operator { /// [1]: https://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method /// [`Pairs`]: ../iterators/struct.Pairs.html #[derive(Debug)] -pub struct PrecClimber { - ops: HashMap, +pub struct PrecClimber { + ops: Cow<'static, [(R, u32, Assoc)]>, +} + +#[cfg(feature = "const_prec_climber")] +impl PrecClimber { + /// Creates a new `PrecClimber` directly from a static slice of + /// `(rule: Rule, precedence: u32, associativity: Assoc)` tuples. + /// + /// Precedence starts from `1`. Entries don't have to be ordered in any way, but it's easier to read when + /// sorted. + /// + /// # Examples + /// + /// ``` + /// # use pest::prec_climber::{Assoc, PrecClimber}; + /// # #[allow(non_camel_case_types)] + /// # #[allow(dead_code)] + /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + /// # enum Rule { + /// # plus, + /// # minus, + /// # times, + /// # divide, + /// # power + /// # } + /// static CLIMBER: PrecClimber = PrecClimber::new_const(&[ + /// (Rule::plus, 1, Assoc::Left), (Rule::minus, 1, Assoc::Left), + /// (Rule::times, 2, Assoc::Left), (Rule::divide, 2, Assoc::Left), + /// (Rule::power, 3, Assoc::Right) + /// ]); + /// ``` + pub const fn new_const(ops: &'static [(R, u32, Assoc)]) -> PrecClimber { + PrecClimber { + ops: Cow::Borrowed(ops), + } + } } impl PrecClimber { + // find matching operator by `rule` + fn get(&self, rule: &R) -> Option<(u32, Assoc)> { + self.ops + .iter() + .find(|(r, _, _)| r == rule) + .map(|(_, precedence, assoc)| (*precedence, *assoc)) + } + /// Creates a new `PrecClimber` from the `Operator`s contained in `ops`. Every entry in the /// `Vec` has precedence *index + 1*. In order to have operators with same precedence, they need /// to be chained with `|` between them. @@ -119,26 +246,26 @@ impl PrecClimber { let ops = ops .into_iter() .zip(1..) - .fold(HashMap::new(), |mut map, (op, prec)| { + .fold(Vec::new(), |mut vec, (op, prec)| { let mut next = Some(op); while let Some(op) = next.take() { - match op { - Operator { - rule, - assoc, - next: op_next, - } => { - map.insert(rule, (prec, assoc)); - next = op_next.map(|op| *op); - } - } + let Operator { + rule, + assoc, + next: op_next, + } = op; + + vec.push((rule, prec, assoc)); + next = op_next.map(|op| *op); } - map + vec }); - PrecClimber { ops } + PrecClimber { + ops: Cow::Owned(ops), + } } /// Performs the precedence climbing algorithm on the `pairs` in a similar manner to map-reduce. @@ -198,7 +325,7 @@ impl PrecClimber { { while pairs.peek().is_some() { let rule = pairs.peek().unwrap().as_rule(); - if let Some(&(prec, _)) = self.ops.get(&rule) { + if let Some((prec, _)) = self.get(&rule) { if prec >= min_prec { let op = pairs.next().unwrap(); let mut rhs = primary(pairs.next().expect( @@ -208,7 +335,7 @@ impl PrecClimber { while pairs.peek().is_some() { let rule = pairs.peek().unwrap().as_rule(); - if let Some(&(new_prec, assoc)) = self.ops.get(&rule) { + if let Some((new_prec, assoc)) = self.get(&rule) { if new_prec > prec || assoc == Assoc::Right && new_prec == prec { rhs = self.climb_rec(rhs, new_prec, pairs, primary, infix); } else { -- cgit v1.2.3