diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/pest/src | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/pest/src')
-rw-r--r-- | vendor/pest/src/iterators/flat_pairs.rs | 43 | ||||
-rw-r--r-- | vendor/pest/src/iterators/line_index.rs | 91 | ||||
-rw-r--r-- | vendor/pest/src/iterators/mod.rs | 1 | ||||
-rw-r--r-- | vendor/pest/src/iterators/pair.rs | 26 | ||||
-rw-r--r-- | vendor/pest/src/iterators/pairs.rs | 60 | ||||
-rw-r--r-- | vendor/pest/src/lib.rs | 1 | ||||
-rw-r--r-- | vendor/pest/src/macros.rs | 2 | ||||
-rw-r--r-- | vendor/pest/src/parser_state.rs | 2 | ||||
-rw-r--r-- | vendor/pest/src/position.rs | 103 | ||||
-rw-r--r-- | vendor/pest/src/pratt_parser.rs | 26 |
10 files changed, 270 insertions, 85 deletions
diff --git a/vendor/pest/src/iterators/flat_pairs.rs b/vendor/pest/src/iterators/flat_pairs.rs index 6d310272e..52a207406 100644 --- a/vendor/pest/src/iterators/flat_pairs.rs +++ b/vendor/pest/src/iterators/flat_pairs.rs @@ -11,6 +11,7 @@ use alloc::rc::Rc; use alloc::vec::Vec; use core::fmt; +use super::line_index::LineIndex; use super::pair::{self, Pair}; use super::queueable_token::QueueableToken; use super::tokens::{self, Tokens}; @@ -28,6 +29,7 @@ pub struct FlatPairs<'i, R> { input: &'i str, start: usize, end: usize, + line_index: Rc<LineIndex>, } /// # Safety @@ -42,6 +44,7 @@ pub unsafe fn new<R: RuleType>( FlatPairs { queue, input, + line_index: Rc::new(LineIndex::new(input)), start, end, } @@ -107,8 +110,14 @@ impl<'i, R: RuleType> Iterator for FlatPairs<'i, R> { return None; } - let pair = unsafe { pair::new(Rc::clone(&self.queue), self.input, self.start) }; - + let pair = unsafe { + pair::new( + Rc::clone(&self.queue), + self.input, + Rc::clone(&self.line_index), + self.start, + ) + }; self.next_start(); Some(pair) @@ -123,7 +132,14 @@ impl<'i, R: RuleType> DoubleEndedIterator for FlatPairs<'i, R> { self.next_start_from_end(); - let pair = unsafe { pair::new(Rc::clone(&self.queue), self.input, self.end) }; + let pair = unsafe { + pair::new( + Rc::clone(&self.queue), + self.input, + Rc::clone(&self.line_index), + self.end, + ) + }; Some(pair) } @@ -142,6 +158,7 @@ impl<'i, R: Clone> Clone for FlatPairs<'i, R> { FlatPairs { queue: Rc::clone(&self.queue), input: self.input, + line_index: Rc::clone(&self.line_index), start: self.start, end: self.end, } @@ -177,4 +194,24 @@ mod tests { vec![Rule::c, Rule::b, Rule::a] ); } + + #[test] + fn test_line_col() { + let mut pairs = AbcParser::parse(Rule::a, "abcNe\nabcde").unwrap().flatten(); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "abc"); + assert_eq!(pair.line_col(), (1, 1)); + assert_eq!(pair.line_col(), pair.as_span().start_pos().line_col()); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "b"); + assert_eq!(pair.line_col(), (1, 2)); + assert_eq!(pair.line_col(), pair.as_span().start_pos().line_col()); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "e"); + assert_eq!(pair.line_col(), (1, 5)); + assert_eq!(pair.line_col(), pair.as_span().start_pos().line_col()); + } } diff --git a/vendor/pest/src/iterators/line_index.rs b/vendor/pest/src/iterators/line_index.rs new file mode 100644 index 000000000..54871e1bd --- /dev/null +++ b/vendor/pest/src/iterators/line_index.rs @@ -0,0 +1,91 @@ +//! `LineIndex` to make a line_offsets, each item is an byte offset (start from 0) of the beginning of the line. +//! +//! For example, the text: `"hello 你好\nworld"`, the line_offsets will store `[0, 13]`. +//! +//! Then `line_col` with a offset just need to find the line index by binary search. +//! +//! Inspired by rust-analyzer's `LineIndex`: +//! <https://github.com/rust-lang/rust/blob/1.67.0/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs> +use alloc::vec::Vec; + +#[derive(Clone)] +pub struct LineIndex { + /// Offset (bytes) the the beginning of each line, zero-based + line_offsets: Vec<usize>, +} + +impl LineIndex { + pub fn new(text: &str) -> LineIndex { + let mut line_offsets: Vec<usize> = alloc::vec![0]; + + let mut offset = 0; + + for c in text.chars() { + offset += c.len_utf8(); + if c == '\n' { + line_offsets.push(offset); + } + } + + LineIndex { line_offsets } + } + + /// Returns (line, col) of pos. + /// + /// The pos is a byte offset, start from 0, e.g. "ab" is 2, "你好" is 6 + pub fn line_col(&self, input: &str, pos: usize) -> (usize, usize) { + let line = self.line_offsets.partition_point(|&it| it <= pos) - 1; + let first_offset = self.line_offsets[line]; + + // Get line str from original input, then we can get column offset + let line_str = &input[first_offset..pos]; + let col = line_str.chars().count(); + + (line + 1, col + 1) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(clippy::zero_prefixed_literal)] + #[test] + fn test_line_index() { + let text = "hello 你好 A🎈C\nworld"; + let table = [ + (00, 1, 1, 'h'), + (01, 1, 2, 'e'), + (02, 1, 3, 'l'), + (03, 1, 4, 'l'), + (04, 1, 5, 'o'), + (05, 1, 6, ' '), + (06, 1, 7, '你'), + (09, 1, 8, '好'), + (12, 1, 9, ' '), + (13, 1, 10, 'A'), + (14, 1, 11, '🎈'), + (18, 1, 12, 'C'), + (19, 1, 13, '\n'), + (20, 2, 1, 'w'), + (21, 2, 2, 'o'), + (22, 2, 3, 'r'), + (23, 2, 4, 'l'), + (24, 2, 5, 'd'), + ]; + + let index = LineIndex::new(text); + for &(offset, line, col, c) in table.iter() { + let res = index.line_col(text, offset); + assert_eq!( + (res.0, res.1), + (line, col), + "Expected: ({}, {}, {}, {:?})", + offset, + line, + col, + c + ); + } + } +} diff --git a/vendor/pest/src/iterators/mod.rs b/vendor/pest/src/iterators/mod.rs index 1a7896371..7f81019ac 100644 --- a/vendor/pest/src/iterators/mod.rs +++ b/vendor/pest/src/iterators/mod.rs @@ -10,6 +10,7 @@ //! Types and iterators for parser output. mod flat_pairs; +mod line_index; mod pair; pub(crate) mod pairs; mod queueable_token; diff --git a/vendor/pest/src/iterators/pair.rs b/vendor/pest/src/iterators/pair.rs index 62c95e037..891b90595 100644 --- a/vendor/pest/src/iterators/pair.rs +++ b/vendor/pest/src/iterators/pair.rs @@ -20,6 +20,7 @@ use core::str; #[cfg(feature = "pretty-print")] use serde::ser::SerializeStruct; +use super::line_index::LineIndex; use super::pairs::{self, Pairs}; use super::queueable_token::QueueableToken; use super::tokens::{self, Tokens}; @@ -43,6 +44,7 @@ pub struct Pair<'i, R> { input: &'i str, /// Token index into `queue`. start: usize, + line_index: Rc<LineIndex>, } /// # Safety @@ -51,12 +53,14 @@ pub struct Pair<'i, R> { pub unsafe fn new<R: RuleType>( queue: Rc<Vec<QueueableToken<R>>>, input: &str, + line_index: Rc<LineIndex>, start: usize, ) -> Pair<'_, R> { Pair { queue, input, start, + line_index, } } @@ -202,7 +206,13 @@ impl<'i, R: RuleType> Pair<'i, R> { pub fn into_inner(self) -> Pairs<'i, R> { let pair = self.pair(); - pairs::new(self.queue, self.input, self.start + 1, pair) + pairs::new( + self.queue, + self.input, + Some(self.line_index), + self.start + 1, + pair, + ) } /// Returns the `Tokens` for the `Pair`. @@ -241,6 +251,12 @@ impl<'i, R: RuleType> Pair<'i, R> { ::serde_json::to_string_pretty(self).expect("Failed to pretty-print Pair to json.") } + /// Returns the `line`, `col` of this pair start. + pub fn line_col(&self) -> (usize, usize) { + let pos = self.pos(self.start); + self.line_index.line_col(self.input, pos) + } + fn pair(&self) -> usize { match self.queue[self.start] { QueueableToken::Start { @@ -263,7 +279,13 @@ impl<'i, R: RuleType> Pairs<'i, R> { /// Create a new `Pairs` iterator containing just the single `Pair`. pub fn single(pair: Pair<'i, R>) -> Self { let end = pair.pair(); - pairs::new(pair.queue, pair.input, pair.start, end) + pairs::new( + pair.queue, + pair.input, + Some(pair.line_index), + pair.start, + end, + ) } } diff --git a/vendor/pest/src/iterators/pairs.rs b/vendor/pest/src/iterators/pairs.rs index e478cebf2..c21a7fae1 100644 --- a/vendor/pest/src/iterators/pairs.rs +++ b/vendor/pest/src/iterators/pairs.rs @@ -20,6 +20,7 @@ use core::str; use serde::ser::SerializeStruct; use super::flat_pairs::{self, FlatPairs}; +use super::line_index::LineIndex; use super::pair::{self, Pair}; use super::queueable_token::QueueableToken; use super::tokens::{self, Tokens}; @@ -36,19 +37,27 @@ pub struct Pairs<'i, R> { input: &'i str, start: usize, end: usize, + line_index: Rc<LineIndex>, } pub fn new<R: RuleType>( queue: Rc<Vec<QueueableToken<R>>>, input: &str, + line_index: Option<Rc<LineIndex>>, start: usize, end: usize, ) -> Pairs<'_, R> { + let line_index = match line_index { + Some(line_index) => line_index, + None => Rc::new(LineIndex::new(input)), + }; + Pairs { queue, input, start, end, + line_index, } } @@ -181,7 +190,14 @@ impl<'i, R: RuleType> Pairs<'i, R> { #[inline] pub fn peek(&self) -> Option<Pair<'i, R>> { if self.start < self.end { - Some(unsafe { pair::new(Rc::clone(&self.queue), self.input, self.start) }) + Some(unsafe { + pair::new( + Rc::clone(&self.queue), + self.input, + Rc::clone(&self.line_index), + self.start, + ) + }) } else { None } @@ -226,6 +242,7 @@ impl<'i, R: RuleType> Iterator for Pairs<'i, R> { fn next(&mut self) -> Option<Self::Item> { let pair = self.peek()?; + self.start = self.pair() + 1; Some(pair) } @@ -239,7 +256,14 @@ impl<'i, R: RuleType> DoubleEndedIterator for Pairs<'i, R> { self.end = self.pair_from_end(); - let pair = unsafe { pair::new(Rc::clone(&self.queue), self.input, self.end) }; + let pair = unsafe { + pair::new( + Rc::clone(&self.queue), + self.input, + Rc::clone(&self.line_index), + self.end, + ) + }; Some(pair) } @@ -423,4 +447,36 @@ mod tests { vec![Rule::c, Rule::a] ); } + + #[test] + fn test_line_col() { + let mut pairs = AbcParser::parse(Rule::a, "abc\nefgh").unwrap(); + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "abc"); + assert_eq!(pair.line_col(), (1, 1)); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "e"); + assert_eq!(pair.line_col(), (2, 1)); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "fgh"); + assert_eq!(pair.line_col(), (2, 2)); + } + + #[test] + fn test_rev_iter_line_col() { + let mut pairs = AbcParser::parse(Rule::a, "abc\nefgh").unwrap().rev(); + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "fgh"); + assert_eq!(pair.line_col(), (2, 2)); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "e"); + assert_eq!(pair.line_col(), (2, 1)); + + let pair = pairs.next().unwrap(); + assert_eq!(pair.as_str(), "abc"); + assert_eq!(pair.line_col(), (1, 1)); + } } diff --git a/vendor/pest/src/lib.rs b/vendor/pest/src/lib.rs index 5cf2f9e26..fa4df2007 100644 --- a/vendor/pest/src/lib.rs +++ b/vendor/pest/src/lib.rs @@ -360,6 +360,7 @@ pub mod prec_climber; mod span; mod stack; mod token; + #[doc(hidden)] pub mod unicode; diff --git a/vendor/pest/src/macros.rs b/vendor/pest/src/macros.rs index 0ca6d9e0d..1b83f388b 100644 --- a/vendor/pest/src/macros.rs +++ b/vendor/pest/src/macros.rs @@ -329,6 +329,7 @@ pub mod tests { a, b, c, + d, } pub struct AbcParser; @@ -345,6 +346,7 @@ pub mod tests { .skip(1) }) .and_then(|s| s.skip(1).unwrap().rule(Rule::c, |s| s.match_string("e"))) + .and_then(|s| s.optional(|s| s.rule(Rule::d, |s| s.match_string("fgh")))) }) } } diff --git a/vendor/pest/src/parser_state.rs b/vendor/pest/src/parser_state.rs index 609de5557..f58de00c8 100644 --- a/vendor/pest/src/parser_state.rs +++ b/vendor/pest/src/parser_state.rs @@ -157,7 +157,7 @@ where match f(state) { Ok(state) => { let len = state.queue.len(); - Ok(pairs::new(Rc::new(state.queue), input, 0, len)) + Ok(pairs::new(Rc::new(state.queue), input, None, 0, len)) } Err(mut state) => { let variant = if state.reached_call_limit() { diff --git a/vendor/pest/src/position.rs b/vendor/pest/src/position.rs index f91f8291e..465ff9766 100644 --- a/vendor/pest/src/position.rs +++ b/vendor/pest/src/position.rs @@ -116,6 +116,9 @@ impl<'i> Position<'i> { /// Returns the line and column number of this `Position`. /// + /// This is an O(n) operation, where n is the number of chars in the input. + /// You better use [`pair.line_col()`](struct.Pair.html#method.line_col) instead. + /// /// # Examples /// /// ``` @@ -135,14 +138,43 @@ impl<'i> Position<'i> { if self.pos > self.input.len() { panic!("position out of bounds"); } - #[cfg(feature = "fast-line-col")] - { - fast_line_col(self.input, self.pos) - } - #[cfg(not(feature = "fast-line-col"))] - { - original_line_col(self.input, self.pos) + let mut pos = self.pos; + let slice = &self.input[..pos]; + let mut chars = slice.chars().peekable(); + + let mut line_col = (1, 1); + + while pos != 0 { + match chars.next() { + Some('\r') => { + if let Some(&'\n') = chars.peek() { + chars.next(); + + if pos == 1 { + pos -= 1; + } else { + pos -= 2; + } + + line_col = (line_col.0 + 1, 1); + } else { + pos -= 1; + line_col = (line_col.0, line_col.1 + 1); + } + } + Some('\n') => { + pos -= 1; + line_col = (line_col.0 + 1, 1); + } + Some(c) => { + pos -= c.len_utf8(); + line_col = (line_col.0, line_col.1 + 1); + } + None => unreachable!(), + } } + + line_col } /// Returns the entire line of the input that contains this `Position`. @@ -455,63 +487,6 @@ impl<'i> Hash for Position<'i> { } } -#[inline] -#[cfg(not(feature = "fast-line-col"))] -fn original_line_col(input: &str, mut pos: usize) -> (usize, usize) { - // Position's pos is always a UTF-8 border. - let slice = &input[..pos]; - let mut chars = slice.chars().peekable(); - - let mut line_col = (1, 1); - - while pos != 0 { - match chars.next() { - Some('\r') => { - if let Some(&'\n') = chars.peek() { - chars.next(); - - if pos == 1 { - pos -= 1; - } else { - pos -= 2; - } - - line_col = (line_col.0 + 1, 1); - } else { - pos -= 1; - line_col = (line_col.0, line_col.1 + 1); - } - } - Some('\n') => { - pos -= 1; - line_col = (line_col.0 + 1, 1); - } - Some(c) => { - pos -= c.len_utf8(); - line_col = (line_col.0, line_col.1 + 1); - } - None => unreachable!(), - } - } - - line_col -} - -#[inline] -#[cfg(feature = "fast-line-col")] -fn fast_line_col(input: &str, pos: usize) -> (usize, usize) { - // Position's pos is always a UTF-8 border. - let slice = &input[..pos]; - - let prec_ln = memchr::memrchr(b'\n', slice.as_bytes()); - if let Some(prec_nl_pos) = prec_ln { - let lines = bytecount::count(slice[..=prec_nl_pos].as_bytes(), b'\n') + 1; - (lines, slice[prec_nl_pos..].chars().count()) - } else { - (1, slice.chars().count() + 1) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/vendor/pest/src/pratt_parser.rs b/vendor/pest/src/pratt_parser.rs index be75f7fa4..76ffdf755 100644 --- a/vendor/pest/src/pratt_parser.rs +++ b/vendor/pest/src/pratt_parser.rs @@ -235,10 +235,10 @@ impl<R: RuleType> PrattParser<R> { } /// Maps primary expressions with a closure `primary`. - pub fn map_primary<'pratt, 'i, X, T>( + pub fn map_primary<'pratt, 'a, 'i, X, T>( &'pratt self, primary: X, - ) -> PrattParserMap<'pratt, 'i, R, X, T> + ) -> PrattParserMap<'pratt, 'a, 'i, R, X, T> where X: FnMut(Pair<'i, R>) -> T, R: 'pratt, @@ -254,29 +254,29 @@ impl<R: RuleType> PrattParser<R> { } } -type PrefixFn<'i, R, T> = Box<dyn FnMut(Pair<'i, R>, T) -> T + 'i>; -type PostfixFn<'i, R, T> = Box<dyn FnMut(T, Pair<'i, R>) -> T + 'i>; -type InfixFn<'i, R, T> = Box<dyn FnMut(T, Pair<'i, R>, T) -> T + 'i>; +type PrefixFn<'a, 'i, R, T> = Box<dyn FnMut(Pair<'i, R>, T) -> T + 'a>; +type PostfixFn<'a, 'i, R, T> = Box<dyn FnMut(T, Pair<'i, R>) -> T + 'a>; +type InfixFn<'a, 'i, R, T> = Box<dyn FnMut(T, Pair<'i, R>, T) -> T + 'a>; /// Product of calling [`map_primary`] on [`PrattParser`], defines how expressions should /// be mapped. /// /// [`map_primary`]: struct.PrattParser.html#method.map_primary /// [`PrattParser`]: struct.PrattParser.html -pub struct PrattParserMap<'pratt, 'i, R, F, T> +pub struct PrattParserMap<'pratt, 'a, 'i, R, F, T> where R: RuleType, F: FnMut(Pair<'i, R>) -> T, { pratt: &'pratt PrattParser<R>, primary: F, - prefix: Option<PrefixFn<'i, R, T>>, - postfix: Option<PostfixFn<'i, R, T>>, - infix: Option<InfixFn<'i, R, T>>, + prefix: Option<PrefixFn<'a, 'i, R, T>>, + postfix: Option<PostfixFn<'a, 'i, R, T>>, + infix: Option<InfixFn<'a, 'i, R, T>>, phantom: PhantomData<T>, } -impl<'pratt, 'i, R, F, T> PrattParserMap<'pratt, 'i, R, F, T> +impl<'pratt, 'a, 'i, R, F, T> PrattParserMap<'pratt, 'a, 'i, R, F, T> where R: RuleType + 'pratt, F: FnMut(Pair<'i, R>) -> T, @@ -284,7 +284,7 @@ where /// Maps prefix operators with closure `prefix`. pub fn map_prefix<X>(mut self, prefix: X) -> Self where - X: FnMut(Pair<'i, R>, T) -> T + 'i, + X: FnMut(Pair<'i, R>, T) -> T + 'a, { self.prefix = Some(Box::new(prefix)); self @@ -293,7 +293,7 @@ where /// Maps postfix operators with closure `postfix`. pub fn map_postfix<X>(mut self, postfix: X) -> Self where - X: FnMut(T, Pair<'i, R>) -> T + 'i, + X: FnMut(T, Pair<'i, R>) -> T + 'a, { self.postfix = Some(Box::new(postfix)); self @@ -302,7 +302,7 @@ where /// Maps infix operators with a closure `infix`. pub fn map_infix<X>(mut self, infix: X) -> Self where - X: FnMut(T, Pair<'i, R>, T) -> T + 'i, + X: FnMut(T, Pair<'i, R>, T) -> T + 'a, { self.infix = Some(Box::new(infix)); self |