Fixed ambiguous iterator state when calling first .current() vs .next() and high-level pos counters fix

This commit is contained in:
Andrew Golovashevich 2025-11-12 20:50:17 +03:00
parent 28d44f907c
commit 04ec6f5acc
8 changed files with 81 additions and 113 deletions

View File

@ -1,25 +1,32 @@
use crate::iterators::StrSourceIterator; use crate::iterators::StrSourceIterator;
use crate::pos::{NewLinePosCounter, PosLineCol}; use crate::pos::{IndexPosCounter, NewLinePosCounter, PosLineCol};
use crate::{_CollectScopeContext, SourceIterator}; use crate::{_CollectScopeContext, SourceIterator};
#[test] #[test]
fn sandbox() { fn sandbox() {
let mut z: StrSourceIterator<'_, '_, PosLineCol, NewLinePosCounter> = let mut z: StrSourceIterator<'_, '_, usize, IndexPosCounter> =
StrSourceIterator::start("12\n34"); StrSourceIterator::start("12\n34");
println!("{}", z.pos().col); println!("{}", z.pos());
z.next(); z.next();
println!("{}", z.pos().col); println!("{} ", z.pos());
z.next(); z.next();
println!("{}", z.pos().col); println!("{}", z.pos());
z.next(); z.next();
println!("{}", z.pos().col); println!("{} ", z.pos());
z.next(); z.next();
println!("{}", z.pos().col); println!("{} ", z.pos());
z.next(); z.next();
println!("{}", z.pos().col); println!("{} ", z.pos());
z.next(); z.next();
println!("{}", z.pos().col); println!("{} ", z.pos());
z.next(); z.next();
println!("{} ", z.pos());
z.next();
println!("{} ", z.pos());
z.next();
println!("{} ", z.pos());
z.next();
return; return;
} }

View File

@ -1,7 +1,7 @@
use source_stream_0::{CollectResult, CollectedSubstring, Pos}; use source_stream_0::{CollectResult, CollectedSubstring, Pos};
pub trait PosCounter<'pos, C, P: Pos<'pos>> { pub trait PosCounter<'pos, C, P: Pos<'pos>> {
fn update(&mut self, c: Option<C>); fn update(&mut self, c: C);
fn export(&self) -> P; fn export(&self) -> P;
@ -9,7 +9,7 @@ pub trait PosCounter<'pos, C, P: Pos<'pos>> {
} }
pub trait _CollectScopeContext<'source, C> { pub trait _CollectScopeContext<'source, C> {
fn next(&mut self) -> Option<C>; fn next(&mut self) -> Option<C>;
fn current(&mut self) -> Option<C>; fn current(&self) -> Option<C>;
} }
pub trait SourceIterator<'source, 'pos, C, P: Pos<'pos>, CS: CollectedSubstring<'source, C>>: pub trait SourceIterator<'source, 'pos, C, P: Pos<'pos>, CS: CollectedSubstring<'source, C>>:

View File

@ -3,12 +3,6 @@ use source_stream_0::{CollectResult, CollectedSubstring, Keyword, KeywordCompara
use std::marker::PhantomData; use std::marker::PhantomData;
use std::slice::Iter; use std::slice::Iter;
enum _CurrentChar<C> {
UNINITIALIZED,
EOF,
Got(C),
}
pub struct ArrayCollectedSubstring<'source, C> { pub struct ArrayCollectedSubstring<'source, C> {
pub slice: &'source [C], pub slice: &'source [C],
} }
@ -34,7 +28,7 @@ impl<'source, C: Copy> CollectedSubstring<'source, C> for ArrayCollectedSubstrin
pub struct ArraySourceIterator<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>> { pub struct ArraySourceIterator<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>> {
_source: &'source [C], _source: &'source [C],
_iter: Iter<'source, C>, _iter: Iter<'source, C>,
_current: _CurrentChar<&'source C>, _current: Option<&'source C>,
_posRaw: usize, _posRaw: usize,
_posHighlevel: PC, _posHighlevel: PC,
__phantom1: PhantomData<&'pos ()>, __phantom1: PhantomData<&'pos ()>,
@ -45,10 +39,12 @@ impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
ArraySourceIterator<'source, 'pos, C, P, PC> ArraySourceIterator<'source, 'pos, C, P, PC>
{ {
pub fn start(arr: &'source [C]) -> ArraySourceIterator<'source, 'pos, C, P, PC> { pub fn start(arr: &'source [C]) -> ArraySourceIterator<'source, 'pos, C, P, PC> {
let mut it = arr.iter();
let first = it.next();
return ArraySourceIterator { return ArraySourceIterator {
_source: arr, _source: arr,
_iter: arr.iter(), _iter: it,
_current: _CurrentChar::UNINITIALIZED, _current: first,
_posRaw: 0, _posRaw: 0,
_posHighlevel: PC::init(), _posHighlevel: PC::init(),
__phantom1: PhantomData::default(), __phantom1: PhantomData::default(),
@ -61,32 +57,16 @@ impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
_CollectScopeContext<'source, C> for ArraySourceIterator<'source, 'pos, C, P, PC> _CollectScopeContext<'source, C> for ArraySourceIterator<'source, 'pos, C, P, PC>
{ {
fn next(&mut self) -> Option<C> { fn next(&mut self) -> Option<C> {
match self._iter.next() { if let Some(c) = self._current {
None => { self._posHighlevel.update(*c);
if let _CurrentChar::Got(_) = self._current { self._posRaw += 1;
self._posHighlevel.update(None); self._current = self._iter.next();
self._posRaw += 1;
}
self._current = _CurrentChar::EOF;
return None;
}
Some(c) => {
self._posHighlevel.update(Some(*c));
if let _CurrentChar::Got(_) = self._current {
self._posRaw += 1;
}
self._current = _CurrentChar::Got(c);
return Some(*c);
}
} }
return self._current.map(|c| *c);
} }
fn current(&mut self) -> Option<C> { fn current(&self) -> Option<C> {
match self._current { return self._current.map(|c| *c);
_CurrentChar::UNINITIALIZED => return self.next(),
_CurrentChar::EOF => return None,
_CurrentChar::Got(c) => return Some(*c),
}
} }
} }
@ -104,10 +84,8 @@ impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
&mut self, &mut self,
scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool, scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool,
) -> CollectResult<ArrayCollectedSubstring<'source, C>> { ) -> CollectResult<ArrayCollectedSubstring<'source, C>> {
match self._current { if self._current.is_none() {
_CurrentChar::EOF => return CollectResult::EOF, return CollectResult::EOF;
_CurrentChar::UNINITIALIZED => {}
_CurrentChar::Got(_) => {}
} }
let startPosRaw = self._posRaw; let startPosRaw = self._posRaw;
@ -117,9 +95,8 @@ impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
true => { true => {
let slice: &'source [C]; let slice: &'source [C];
match self._current { match self._current {
_CurrentChar::EOF => slice = &self._source[startPosRaw..], None => slice = &self._source[startPosRaw..],
_CurrentChar::UNINITIALIZED => slice = &[], Some(_) => slice = &self._source[startPosRaw..self._posRaw],
_CurrentChar::Got(_) => slice = &self._source[startPosRaw..self._posRaw],
} }
return CollectResult::Matches(ArrayCollectedSubstring { slice: slice }); return CollectResult::Matches(ArrayCollectedSubstring { slice: slice });
} }

View File

@ -3,12 +3,6 @@ use source_stream_0::{CollectResult, CollectedSubstring, Keyword, KeywordCompara
use std::marker::PhantomData; use std::marker::PhantomData;
use std::str::CharIndices; use std::str::CharIndices;
enum _CurrentChar {
UNINITIALIZED,
EOF,
Got(char),
}
pub struct StrCollectedSubstring<'source> { pub struct StrCollectedSubstring<'source> {
pub slice: &'source str, pub slice: &'source str,
pub size: usize, pub size: usize,
@ -35,7 +29,7 @@ impl<'source> CollectedSubstring<'source, char> for StrCollectedSubstring<'sourc
pub struct StrSourceIterator<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>> { pub struct StrSourceIterator<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>> {
_source: &'source str, _source: &'source str,
_iter: CharIndices<'source>, _iter: CharIndices<'source>,
_current: _CurrentChar, _current: Option<char>,
_posRaw: usize, _posRaw: usize,
_posCodePoints: usize, _posCodePoints: usize,
_posHighlevel: PC, _posHighlevel: PC,
@ -47,11 +41,13 @@ impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>>
StrSourceIterator<'source, 'pos, P, PC> StrSourceIterator<'source, 'pos, P, PC>
{ {
pub fn start(s: &'source str) -> StrSourceIterator<'source, 'pos, P, PC> { pub fn start(s: &'source str) -> StrSourceIterator<'source, 'pos, P, PC> {
let mut it = s.char_indices();
let first = it.next();
return StrSourceIterator { return StrSourceIterator {
_source: s, _source: s,
_iter: s.char_indices(), _iter: it,
_current: _CurrentChar::UNINITIALIZED, _current: first.map(|(_, c)| c),
_posRaw: 0, _posRaw: first.map_or(s.len(), |(p, _)| p),
_posCodePoints: 0, _posCodePoints: 0,
_posHighlevel: PC::init(), _posHighlevel: PC::init(),
__phantom1: PhantomData::default(), __phantom1: PhantomData::default(),
@ -64,34 +60,30 @@ impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>> _CollectScopeCo
for StrSourceIterator<'source, 'pos, P, PC> for StrSourceIterator<'source, 'pos, P, PC>
{ {
fn next(&mut self) -> Option<char> { fn next(&mut self) -> Option<char> {
match self._iter.next() { match self._current {
None => { None => return None,
if let _CurrentChar::Got(_) = self._current { Some(prev) => {
self._posHighlevel.update(None); self._posHighlevel.update(prev);
self._posCodePoints += 1; self._posCodePoints += 1;
self._posRaw = self._source.len();
match self._iter.next() {
None => {
self._posRaw = self._source.len();
self._current = None;
return None;
}
Some((p, c)) => {
self._posRaw = p;
self._current = Some(c);
return Some(c);
}
} }
self._current = _CurrentChar::EOF;
return None;
}
Some((p, c)) => {
self._posRaw = p;
if let _CurrentChar::Got(_) = self._current {
self._posCodePoints += 1;
}
self._posHighlevel.update(Some(c));
self._current = _CurrentChar::Got(c);
return Some(c);
} }
} }
} }
fn current(&mut self) -> Option<char> { fn current(&self) -> Option<char> {
match self._current { return self._current;
_CurrentChar::UNINITIALIZED => return self.next(),
_CurrentChar::EOF => return None,
_CurrentChar::Got(c) => return Some(c),
}
} }
} }
@ -109,10 +101,8 @@ impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>>
&mut self, &mut self,
scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool, scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool,
) -> CollectResult<StrCollectedSubstring<'source>> { ) -> CollectResult<StrCollectedSubstring<'source>> {
match self._current { if self._current.is_none() {
_CurrentChar::EOF => return CollectResult::EOF, return CollectResult::EOF;
_CurrentChar::UNINITIALIZED => {}
_CurrentChar::Got(_) => {}
} }
let startPosRaw = self._posRaw; let startPosRaw = self._posRaw;
@ -123,9 +113,8 @@ impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>>
true => { true => {
let slice: &'source str; let slice: &'source str;
match self._current { match self._current {
_CurrentChar::EOF => slice = &self._source[startPosRaw..], None => slice = &self._source[startPosRaw..],
_CurrentChar::UNINITIALIZED => slice = "", Some(_) => slice = &self._source[startPosRaw..self._posRaw],
_CurrentChar::Got(_) => slice = &self._source[startPosRaw..self._posRaw],
} }
return CollectResult::Matches(StrCollectedSubstring { return CollectResult::Matches(StrCollectedSubstring {
slice: slice, slice: slice,

View File

@ -5,7 +5,7 @@ pub struct IndexPosCounter {
} }
impl<C> PosCounter<'static, C, usize> for IndexPosCounter { impl<C> PosCounter<'static, C, usize> for IndexPosCounter {
fn update(&mut self, c: Option<C>) { fn update(&mut self, c: C) {
self.index += 1; self.index += 1;
} }

View File

@ -14,17 +14,12 @@ pub struct NewLinePosCounter {
} }
impl NewLinePosCounter { impl NewLinePosCounter {
pub fn _update<C: PartialEq>(&mut self, actual: Option<C>, expected: C) { pub fn _update<C: PartialEq>(&mut self, actual: C, expected: C) {
match actual { if actual == expected {
None => {} self.row += 1;
Some(c) => { self.col = 0;
if c == expected { } else {
self.row += 1; self.col += 1;
self.col = 0;
} else {
self.col += 1;
}
}
} }
} }
@ -41,7 +36,7 @@ impl NewLinePosCounter {
} }
impl PosCounter<'static, char, PosLineCol> for NewLinePosCounter { impl PosCounter<'static, char, PosLineCol> for NewLinePosCounter {
fn update(&mut self, c: Option<char>) { fn update(&mut self, c: char) {
self._update(c, '\n') self._update(c, '\n')
} }
@ -55,7 +50,7 @@ impl PosCounter<'static, char, PosLineCol> for NewLinePosCounter {
} }
impl PosCounter<'static, u8, PosLineCol> for NewLinePosCounter { impl PosCounter<'static, u8, PosLineCol> for NewLinePosCounter {
fn update(&mut self, c: Option<u8>) { fn update(&mut self, c: u8) {
self._update(c, b'\n') self._update(c, b'\n')
} }

View File

@ -96,7 +96,7 @@ impl<
return self._iter.pos(); return self._iter.pos();
} }
fn currentChar(&mut self) -> Option<C> { fn currentChar(&self) -> Option<C> {
return self._iter.current(); return self._iter.current();
} }

View File

@ -38,7 +38,7 @@ pub trait SourceStream<'source, 'pos, C, P: Pos<'pos>, CS: CollectedSubstring<'s
fn pos(&self) -> P; fn pos(&self) -> P;
fn currentChar(&mut self) -> Option<C>; fn currentChar(&self) -> Option<C>;
fn nextChar(&mut self) -> Option<C>; fn nextChar(&mut self) -> Option<C>;
fn isEnded(&mut self) -> bool { fn isEnded(&mut self) -> bool {