summaryrefslogtreecommitdiff
path: root/src/span.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/span.rs')
-rw-r--r--src/span.rs114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/span.rs b/src/span.rs
index 7603c43..bf7b12b 100644
--- a/src/span.rs
+++ b/src/span.rs
@@ -212,6 +212,27 @@ impl<'i> Span<'i> {
&self.input[self.start..self.end]
}
+ /// Returns the input string of the `Span`.
+ ///
+ /// This function returns the input string of the `Span` as a `&str`. This is the source string
+ /// from which the `Span` was created. The returned `&str` can be used to examine the contents of
+ /// the `Span` or to perform further processing on the string.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use pest;
+ /// # use pest::Span;
+ ///
+ /// // Example: Get input string from a span
+ /// let input = "abc\ndef\nghi";
+ /// let span = Span::new(input, 1, 7).unwrap();
+ /// assert_eq!(span.get_input(), input);
+ /// ```
+ pub fn get_input(&self) -> &'i str {
+ self.input
+ }
+
/// Iterates over all lines (partially) covered by this span. Yielding a `&str` for each line.
///
/// # Examples
@@ -288,6 +309,61 @@ impl<'i> Hash for Span<'i> {
}
}
+/// Merges two spans into one.
+///
+/// This function merges two spans that are contiguous or overlapping into a single span
+/// that covers the entire range of the two input spans. This is useful when you want to
+/// aggregate information from multiple spans into a single entity.
+///
+/// The function checks if the input spans are overlapping or contiguous by comparing their
+/// start and end positions. If they are, a new span is created with the minimum start position
+/// and the maximum end position of the two input spans.
+///
+/// If the input spans are neither overlapping nor contiguous, the function returns None,
+/// indicating that a merge operation was not possible.
+///
+/// # Examples
+///
+/// ```
+/// # use pest;
+/// # use pest::Span;
+/// # use pest::merge_spans;
+///
+/// // Example 1: Contiguous spans
+/// let input = "abc\ndef\nghi";
+/// let span1 = Span::new(input, 1, 7).unwrap();
+/// let span2 = Span::new(input, 7, 11).unwrap();
+/// let merged = merge_spans(&span1, &span2).unwrap();
+/// assert_eq!(merged, Span::new(input, 1, 11).unwrap());
+///
+/// // Example 2: Overlapping spans
+/// let input = "abc\ndef\nghi";
+/// let span1 = Span::new(input, 1, 7).unwrap();
+/// let span2 = Span::new(input, 5, 11).unwrap();
+/// let merged = merge_spans(&span1, &span2).unwrap();
+/// assert_eq!(merged, Span::new(input, 1, 11).unwrap());
+///
+/// // Example 3: Non-contiguous spans
+/// let input = "abc\ndef\nghi";
+/// let span1 = Span::new(input, 1, 7).unwrap();
+/// let span2 = Span::new(input, 8, 11).unwrap();
+/// let merged = merge_spans(&span1, &span2);
+/// assert!(merged.is_none());
+/// ```
+pub fn merge_spans<'i>(a: &Span<'i>, b: &Span<'i>) -> Option<Span<'i>> {
+ if a.end() >= b.start() && a.start() <= b.end() {
+ // The spans overlap or are contiguous, so they can be merged.
+ Span::new(
+ a.get_input(),
+ core::cmp::min(a.start(), b.start()),
+ core::cmp::max(a.end(), b.end()),
+ )
+ } else {
+ // The spans don't overlap and aren't contiguous, so they can't be merged.
+ None
+ }
+}
+
/// Line iterator for Spans, created by [`Span::lines_span()`].
///
/// Iterates all lines that are at least _partially_ covered by the span. Yielding a `Span` for each.
@@ -447,4 +523,42 @@ mod tests {
lines
);
}
+
+ #[test]
+ fn get_input_of_span() {
+ let input = "abc\ndef\nghi";
+ let span = Span::new(input, 1, 7).unwrap();
+
+ assert_eq!(span.get_input(), input);
+ }
+
+ #[test]
+ fn merge_contiguous() {
+ let input = "abc\ndef\nghi";
+ let span1 = Span::new(input, 1, 7).unwrap();
+ let span2 = Span::new(input, 7, 11).unwrap();
+ let merged = merge_spans(&span1, &span2).unwrap();
+
+ assert_eq!(merged, Span::new(input, 1, 11).unwrap());
+ }
+
+ #[test]
+ fn merge_overlapping() {
+ let input = "abc\ndef\nghi";
+ let span1 = Span::new(input, 1, 7).unwrap();
+ let span2 = Span::new(input, 5, 11).unwrap();
+ let merged = merge_spans(&span1, &span2).unwrap();
+
+ assert_eq!(merged, Span::new(input, 1, 11).unwrap());
+ }
+
+ #[test]
+ fn merge_non_contiguous() {
+ let input = "abc\ndef\nghi";
+ let span1 = Span::new(input, 1, 7).unwrap();
+ let span2 = Span::new(input, 8, 11).unwrap();
+ let merged = merge_spans(&span1, &span2);
+
+ assert!(merged.is_none());
+ }
}