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::pos::{NewLinePosCounter, PosLineCol};
use crate::pos::{IndexPosCounter, NewLinePosCounter, PosLineCol};
use crate::{_CollectScopeContext, SourceIterator};
#[test]
fn sandbox() {
let mut z: StrSourceIterator<'_, '_, PosLineCol, NewLinePosCounter> =
let mut z: StrSourceIterator<'_, '_, usize, IndexPosCounter> =
StrSourceIterator::start("12\n34");
println!("{}", z.pos().col);
println!("{}", z.pos());
z.next();
println!("{}", z.pos().col);
println!("{} ", z.pos());
z.next();
println!("{}", z.pos().col);
println!("{}", z.pos());
z.next();
println!("{}", z.pos().col);
println!("{} ", z.pos());
z.next();
println!("{}", z.pos().col);
println!("{} ", z.pos());
z.next();
println!("{}", z.pos().col);
println!("{} ", z.pos());
z.next();
println!("{}", z.pos().col);
println!("{} ", z.pos());
z.next();
println!("{} ", z.pos());
z.next();
println!("{} ", z.pos());
z.next();
println!("{} ", z.pos());
z.next();
return;
}

View File

@ -1,7 +1,7 @@
use source_stream_0::{CollectResult, CollectedSubstring, 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;
@ -9,7 +9,7 @@ pub trait PosCounter<'pos, C, P: Pos<'pos>> {
}
pub trait _CollectScopeContext<'source, 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>>:

View File

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

View File

@ -5,7 +5,7 @@ pub struct 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;
}

View File

@ -14,19 +14,14 @@ pub struct NewLinePosCounter {
}
impl NewLinePosCounter {
pub fn _update<C: PartialEq>(&mut self, actual: Option<C>, expected: C) {
match actual {
None => {}
Some(c) => {
if c == expected {
pub fn _update<C: PartialEq>(&mut self, actual: C, expected: C) {
if actual == expected {
self.row += 1;
self.col = 0;
} else {
self.col += 1;
}
}
}
}
pub fn _export(&self) -> PosLineCol {
return PosLineCol {
@ -41,7 +36,7 @@ impl 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')
}
@ -55,7 +50,7 @@ impl PosCounter<'static, char, 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')
}

View File

@ -96,7 +96,7 @@ impl<
return self._iter.pos();
}
fn currentChar(&mut self) -> Option<C> {
fn currentChar(&self) -> Option<C> {
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 currentChar(&mut self) -> Option<C>;
fn currentChar(&self) -> Option<C>;
fn nextChar(&mut self) -> Option<C>;
fn isEnded(&mut self) -> bool {