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::fmt::Debug;
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
|
|
||||||
use super::{InputIter, Offsetable, Span, SpanRange};
|
use super::{InputIter, Offsetable, Span, SpanRange, TextPositionTracker};
|
||||||
|
|
||||||
/// Implements `InputIter` for any slice of T.
|
/// Implements `InputIter` for any slice of T.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -86,6 +86,8 @@ impl<'a, T: Debug> From<&'a Vec<T>> for SliceIter<'a, T> {
|
|||||||
pub struct StrIter<'a> {
|
pub struct StrIter<'a> {
|
||||||
source: &'a str,
|
source: &'a str,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
line: usize,
|
||||||
|
column: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StrIter<'a> {
|
impl<'a> StrIter<'a> {
|
||||||
@ -94,6 +96,8 @@ impl<'a> StrIter<'a> {
|
|||||||
StrIter {
|
StrIter {
|
||||||
source: source,
|
source: source,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
line: 1,
|
||||||
|
column: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,8 +107,15 @@ impl<'a> Iterator for StrIter<'a> {
|
|||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.source.as_bytes().get(self.offset) {
|
match self.source.as_bytes().get(self.offset) {
|
||||||
|
// TODO count lines and columns.
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
self.offset += 1;
|
self.offset += 1;
|
||||||
|
if *item == b'\n' {
|
||||||
|
self.line += 1;
|
||||||
|
self.column = 1;
|
||||||
|
} else {
|
||||||
|
self.column += 1;
|
||||||
|
}
|
||||||
Some(item)
|
Some(item)
|
||||||
}
|
}
|
||||||
None => None,
|
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> {
|
impl<'a> Clone for StrIter<'a> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
StrIter {
|
StrIter {
|
||||||
source: self.source,
|
source: self.source,
|
||||||
offset: self.offset,
|
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 {
|
pub enum SpanRange {
|
||||||
Range(std::ops::Range<usize>),
|
Range(std::ops::Range<usize>),
|
||||||
RangeTo(std::ops::RangeTo<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);
|
let result = ascii_ws(iter);
|
||||||
assert!(result.is_complete());
|
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