mirror of
https://github.com/zaphar/abortable_parser.git
synced 2025-07-21 20:29:49 -04:00
FEATURE: Add a trait for tracking lines and columns in text.
This commit is contained in:
parent
e833730fbb
commit
2089897ab5
@ -759,3 +759,12 @@ macro_rules! make_fn {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pos {
|
||||
($i:expr) => {{
|
||||
let _i = $i.clone();
|
||||
use $crate::TextPositionTracker;
|
||||
$crate::Result::Complete($i, (_i.line(), _i.column()))
|
||||
}}
|
||||
}
|
25
src/iter.rs
25
src/iter.rs
@ -2,7 +2,7 @@
|
||||
use std::fmt::Debug;
|
||||
use std::iter::Iterator;
|
||||
|
||||
use super::{InputIter, Offsetable, Span, SpanRange};
|
||||
use super::{InputIter, Offsetable, Span, SpanRange, TextPositionTracker};
|
||||
|
||||
/// Implements `InputIter` for any slice of T.
|
||||
#[derive(Debug)]
|
||||
@ -86,6 +86,8 @@ impl<'a, T: Debug> From<&'a Vec<T>> for SliceIter<'a, T> {
|
||||
pub struct StrIter<'a> {
|
||||
source: &'a str,
|
||||
offset: usize,
|
||||
line: usize,
|
||||
column: usize,
|
||||
}
|
||||
|
||||
impl<'a> StrIter<'a> {
|
||||
@ -94,6 +96,8 @@ impl<'a> StrIter<'a> {
|
||||
StrIter {
|
||||
source: source,
|
||||
offset: 0,
|
||||
line: 1,
|
||||
column: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,8 +107,15 @@ impl<'a> Iterator for StrIter<'a> {
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.source.as_bytes().get(self.offset) {
|
||||
// TODO count lines and columns.
|
||||
Some(item) => {
|
||||
self.offset += 1;
|
||||
if *item == b'\n' {
|
||||
self.line += 1;
|
||||
self.column = 1;
|
||||
} else {
|
||||
self.column += 1;
|
||||
}
|
||||
Some(item)
|
||||
}
|
||||
None => None,
|
||||
@ -118,11 +129,23 @@ impl<'a> Offsetable for StrIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TextPositionTracker for StrIter<'a> {
|
||||
fn line(&self) -> usize {
|
||||
self.line
|
||||
}
|
||||
|
||||
fn column(&self) -> usize {
|
||||
self.column
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Clone for StrIter<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
StrIter {
|
||||
source: self.source,
|
||||
offset: self.offset,
|
||||
line: self.line,
|
||||
column: self.column,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,12 @@ impl Offsetable for usize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for Inputs that can track lines and columns in a text input.
|
||||
pub trait TextPositionTracker {
|
||||
fn line(&self) -> usize;
|
||||
fn column(&self) -> usize;
|
||||
}
|
||||
|
||||
pub enum SpanRange {
|
||||
Range(std::ops::Range<usize>),
|
||||
RangeTo(std::ops::RangeTo<usize>),
|
||||
|
18
src/test.rs
18
src/test.rs
@ -462,3 +462,21 @@ fn test_ascii_ws_carriage_return() {
|
||||
let result = ascii_ws(iter);
|
||||
assert!(result.is_complete());
|
||||
}
|
||||
|
||||
use super::TextPositionTracker;
|
||||
#[test]
|
||||
fn test_position_tracking_striter() {
|
||||
let input_str = "\n";
|
||||
let mut iter = StrIter::new(input_str);
|
||||
assert_eq!(iter.line(), 1);
|
||||
assert_eq!(iter.column(), 1);
|
||||
iter.next();
|
||||
assert_eq!(iter.line(), 2);
|
||||
assert_eq!(iter.column(), 1);
|
||||
let pos_result = pos!(iter);
|
||||
assert!(pos_result.is_complete());
|
||||
if let Result::Complete(_, (line, column)) = pos_result {
|
||||
assert_eq!(line, 2);
|
||||
assert_eq!(column, 1);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user