Returning '.currentChar' method because this makes parsers cleaner (presumably without any performance loss); removed char returns from other methods and simplified some duplicated code

This commit is contained in:
Andrew Golovashevich 2025-11-26 19:14:34 +03:00
parent cb10fc8f83
commit 1c6f829c9f
5 changed files with 111 additions and 141 deletions

View File

@ -41,22 +41,18 @@ impl<
type P = W::WP; type P = W::WP;
type CS = W::WCS; type CS = W::WCS;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C> { fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> bool {
return self return self
._src ._src
.skipNext(&mut PredicateConverter::wrap(predicate, &self._converter)) .skipNext(&mut PredicateConverter::wrap(predicate, &self._converter));
.map(|c| self._converter.convertChar(c));
} }
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> (Self::CS, Option<Self::C>) { fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS {
let (cs, wrongChar) = self let cs = self
._src ._src
.collect(&mut PredicateConverter::wrap(predicate, &self._converter)); .collect(&mut PredicateConverter::wrap(predicate, &self._converter));
return ( return self._converter.convertSubstring(cs);
self._converter.convertSubstring(cs),
wrongChar.map(|c| self._converter.convertChar(c)),
);
} }
fn pos(&self) -> W::WP { fn pos(&self) -> W::WP {
@ -66,4 +62,8 @@ impl<
fn nextChar(&mut self) -> Option<W::WC> { fn nextChar(&mut self) -> Option<W::WC> {
return self._src.nextChar().map(|c| self._converter.convertChar(c)); return self._src.nextChar().map(|c| self._converter.convertChar(c));
} }
fn currentChar(&self) -> Option<Self::C> {
return self._src.currentChar().map(|c| self._converter.convertChar(c));
}
} }

View File

@ -30,47 +30,35 @@ impl<'source, C: Copy> CollectedSubstring for ArrayCollectedSubstring<'source, C
pub struct ArraySourceStream<'source, C: Copy, PC: PosCounter<C>> { pub struct ArraySourceStream<'source, C: Copy, PC: PosCounter<C>> {
_source: &'source [C], _source: &'source [C],
__iter: Iter<'source, C>, __iter: Iter<'source, C>,
_current: C, _current: Option<C>,
_posRaw: usize, _posRaw: usize,
_posHighlevel: PC, _posHighlevel: PC,
_isEnded: bool,
} }
impl<'source, C: Copy, PC: PosCounter<C>> ArraySourceStream<'source, C, PC> { impl<'source, C: Copy, PC: PosCounter<C>> ArraySourceStream<'source, C, PC> {
pub fn start(arr: &'source [C], pos: PC) -> Option<(Self, C)> { pub fn start(arr: &'source [C], pos: PC) -> Self {
let mut iter = arr.iter(); let mut iter = arr.iter();
let first = iter.next().copied(); let first = iter.next().copied();
match first {
None => None,
Some(c) => {
let stream = ArraySourceStream { let stream = ArraySourceStream {
_source: arr, _source: arr,
__iter: iter, __iter: iter,
_current: c, _current: first,
_posRaw: 0, _posRaw: 0,
_posHighlevel: pos, _posHighlevel: pos,
_isEnded: false,
}; };
return Some((stream, c)); return stream;
}
}
} }
} }
impl<'source, 'pos, C: Copy, PC: PosCounter<C>> ArraySourceStream<'source, C, PC> { impl<'source, 'pos, C: Copy, PC: PosCounter<C>> ArraySourceStream<'source, C, PC> {
fn _next(&mut self) -> Option<C> { fn _next(&mut self) -> Option<C> {
if !self._isEnded { if let Some(c) = self._current {
self._posHighlevel.update(self._current); self._posHighlevel.update(c);
self._posRaw += 1; self._posRaw += 1;
} }
match self.__iter.next() {
None => return None, self._current = self.__iter.next().copied();
Some(c) => { return self._current;
self._isEnded = true;
self._current = *c;
return Some(self._current);
}
}
} }
} }
@ -79,40 +67,13 @@ impl<'source, C: Copy, PC: PosCounter<C>> SourceStream for ArraySourceStream<'so
type P = PC::P; type P = PC::P;
type CS = ArrayCollectedSubstring<'source, C>; type CS = ArrayCollectedSubstring<'source, C>;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C> { fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS {
loop {
match self._next() {
None => return None,
Some(c) => match predicate.check(c) {
true => continue,
false => return Some(c),
},
}
}
}
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> (Self::CS, Option<Self::C>) {
let startPosRaw = self._posRaw; let startPosRaw = self._posRaw;
let wrongChar: Option<C>; self.skipNext(predicate);
loop {
match self._next() {
None => {
wrongChar = None;
break;
}
Some(c) => match predicate.check(c) {
true => continue,
false => {
wrongChar = Some(c);
break;
}
},
}
}
let slice = &self._source[startPosRaw..self._posRaw]; let slice = &self._source[startPosRaw..self._posRaw];
return (ArrayCollectedSubstring { slice: slice }, wrongChar); return ArrayCollectedSubstring { slice: slice };
} }
fn pos(&self) -> Self::P { fn pos(&self) -> Self::P {
@ -122,4 +83,8 @@ impl<'source, C: Copy, PC: PosCounter<C>> SourceStream for ArraySourceStream<'so
fn nextChar(&mut self) -> Option<Self::C> { fn nextChar(&mut self) -> Option<Self::C> {
return self._next(); return self._next();
} }
fn currentChar(&self) -> Option<Self::C> {
return self._current;
}
} }

View File

@ -1,16 +1,18 @@
use std::marker::PhantomData; use crate::pos::PosCounter;
use crate::pos::{PosCounter};
use crate::{CollectedSubstring, Predicate, SourceStream}; use crate::{CollectedSubstring, Predicate, SourceStream};
use std::marker::PhantomData;
pub struct EmptySourceStream<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> { pub struct EmptySourceStream<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> {
_pos: PC, _pos: PC,
__phantom: PhantomData<(C, CS)> __phantom: PhantomData<(C, CS)>,
} }
impl<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> EmptySourceStream<C, CS, PC> { impl<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> EmptySourceStream<C, CS, PC> {
pub fn start(pos: PC) -> (Self, Option<C>) { pub fn start(pos: PC) -> Self {
let stream = EmptySourceStream { _pos: pos, __phantom: PhantomData::default() }; return EmptySourceStream {
return (stream, None); _pos: pos,
__phantom: PhantomData::default(),
};
} }
} }
@ -21,11 +23,15 @@ impl<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> SourceStream
type P = PC::P; type P = PC::P;
type CS = CS; type CS = CS;
fn skipNext(&mut self, _: &mut impl Predicate<Self::C>) -> Option<Self::C> { fn skipCurrent(&mut self, _: &mut impl Predicate<Self::C>) -> bool {
return None; return true;
} }
fn collect(&mut self, _: &mut impl Predicate<Self::C>) -> (Self::CS, Option<Self::C>) { fn skipNext(&mut self, _: &mut impl Predicate<Self::C>) -> bool {
return true;
}
fn collect(&mut self, _: &mut impl Predicate<Self::C>) -> Self::CS {
panic!("How about to check first char of substring being collected first"); panic!("How about to check first char of substring being collected first");
} }
@ -36,4 +42,8 @@ impl<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> SourceStream
fn nextChar(&mut self) -> Option<Self::C> { fn nextChar(&mut self) -> Option<Self::C> {
return None; return None;
} }
fn currentChar(&self) -> Option<Self::C> {
return None;
}
} }

View File

@ -31,50 +31,55 @@ impl<'source> CollectedSubstring for StrCollectedSubstring<'source> {
pub struct StrSourceStream<'source, PC: PosCounter<char>> { pub struct StrSourceStream<'source, PC: PosCounter<char>> {
_source: &'source str, _source: &'source str,
__iter: CharIndices<'source>, __iter: CharIndices<'source>,
_current: char, _current: Option<char>,
_posRaw: usize, _posRaw: usize,
_posCodePoints: usize, _posCodePoints: usize,
_posHighlevel: PC, _posHighlevel: PC,
_isEnded: bool,
} }
impl<'source, PC: PosCounter<char>> StrSourceStream<'source, PC> { impl<'source, PC: PosCounter<char>> StrSourceStream<'source, PC> {
pub fn start(s: &'source str, pos: PC) -> Option<(Self, char)> { pub fn start(s: &'source str, pos: PC) -> Self {
let mut it = s.char_indices(); let mut it = s.char_indices();
let first = it.next(); let first = it.next();
match first {
None => return None, let mut stream = StrSourceStream {
Some((p, c)) => {
let stream = StrSourceStream {
_source: s, _source: s,
__iter: it, __iter: it,
_current: c, _current: None,
_posRaw: p, _posRaw: s.len(),
_posCodePoints: 0, _posCodePoints: 0,
_posHighlevel: pos, _posHighlevel: pos,
_isEnded: false,
}; };
return Some((stream, c));
match first {
None => {}
Some((p, c)) => {
stream._current = Some(c);
stream._posRaw = p
} }
} }
return stream;
} }
} }
impl<'source, PC: PosCounter<char>> StrSourceStream<'source, PC> { impl<'source, PC: PosCounter<char>> StrSourceStream<'source, PC> {
fn _next(&mut self) -> Option<char> { fn _next(&mut self) -> Option<char> {
if !self._isEnded { if let Some(c) = self._current {
self._posHighlevel.update(self._current); self._posHighlevel.update(c);
self._posCodePoints += 1; self._posCodePoints += 1;
} }
match self.__iter.next() { match self.__iter.next() {
None => return None, None => {
self._posRaw = self._source.len();
self._current = None;
}
Some((p, c)) => { Some((p, c)) => {
self._isEnded = true;
self._posRaw = p; self._posRaw = p;
self._current = c; self._current = Some(c);
return Some(self._current);
} }
} }
return self._current;
} }
} }
@ -83,47 +88,17 @@ impl<'source, PC: PosCounter<char>> SourceStream for StrSourceStream<'source, PC
type P = PC::P; type P = PC::P;
type CS = StrCollectedSubstring<'source>; type CS = StrCollectedSubstring<'source>;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C> { fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS {
loop {
match self._next() {
None => return None,
Some(c) => match predicate.check(c) {
true => continue,
false => return Some(c),
},
}
}
}
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> (Self::CS, Option<Self::C>) {
let startPosRaw = self._posRaw; let startPosRaw = self._posRaw;
let startPosCP = self._posCodePoints; let startPosCP = self._posCodePoints;
let wrongChar: Option<char>; self.skipNext(predicate);
loop {
match self._next() {
None => {
wrongChar = None;
break;
}
Some(c) => match predicate.check(c) {
true => continue,
false => {
wrongChar = Some(c);
break;
}
},
}
}
let slice = &self._source[startPosRaw..self._posRaw]; let slice = &self._source[startPosRaw..self._posRaw];
return ( return StrCollectedSubstring {
StrCollectedSubstring {
slice: slice, slice: slice,
size: self._posCodePoints - startPosCP, size: self._posCodePoints - startPosCP,
}, };
wrongChar,
);
} }
fn pos(&self) -> Self::P { fn pos(&self) -> Self::P {
@ -133,4 +108,8 @@ impl<'source, PC: PosCounter<char>> SourceStream for StrSourceStream<'source, PC
fn nextChar(&mut self) -> Option<Self::C> { fn nextChar(&mut self) -> Option<Self::C> {
return self._next(); return self._next();
} }
fn currentChar(&self) -> Option<Self::C> {
return self._current;
}
} }

View File

@ -10,19 +10,33 @@ pub trait SourceStream {
type P: Pos; type P: Pos;
type CS: CollectedSubstring<C = Self::C>; type CS: CollectedSubstring<C = Self::C>;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C>;
fn skipCurrent( fn skipCurrent(
&mut self, &mut self,
current: Self::C,
predicate: &mut impl Predicate<Self::C>, predicate: &mut impl Predicate<Self::C>,
) -> Option<Self::C> { ) -> bool {
if !predicate.check(current) { match self.currentChar() {
return Some(current); None => return true,
Some(c) => {
if !predicate.check(c) {
return false;
} }
return self.skipNext(predicate); return self.skipNext(predicate);
} }
}
}
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> bool {
loop {
match self.nextChar() {
None => return true,
Some(c) => match predicate.check(c) {
true => continue,
false => return false,
},
}
}
}
/** /**
* Returns reference to a slice of the source which can be used for comparations * Returns reference to a slice of the source which can be used for comparations
@ -36,9 +50,11 @@ pub trait SourceStream {
* Calling this method on ended stream (previous `nextChar` returned `None`) * Calling this method on ended stream (previous `nextChar` returned `None`)
* is undefined behavior. * is undefined behavior.
*/ */
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> (Self::CS, Option<Self::C>); fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS;
fn pos(&self) -> Self::P; fn pos(&self) -> Self::P;
fn nextChar(&mut self) -> Option<Self::C>; fn nextChar(&mut self) -> Option<Self::C>;
fn currentChar(&self) -> Option<Self::C>;
} }