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 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
._src
.skipNext(&mut PredicateConverter::wrap(predicate, &self._converter))
.map(|c| self._converter.convertChar(c));
.skipNext(&mut PredicateConverter::wrap(predicate, &self._converter));
}
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> (Self::CS, Option<Self::C>) {
let (cs, wrongChar) = self
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS {
let cs = self
._src
.collect(&mut PredicateConverter::wrap(predicate, &self._converter));
return (
self._converter.convertSubstring(cs),
wrongChar.map(|c| self._converter.convertChar(c)),
);
return self._converter.convertSubstring(cs);
}
fn pos(&self) -> W::WP {
@ -66,4 +62,8 @@ impl<
fn nextChar(&mut self) -> Option<W::WC> {
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>> {
_source: &'source [C],
__iter: Iter<'source, C>,
_current: C,
_current: Option<C>,
_posRaw: usize,
_posHighlevel: PC,
_isEnded: bool,
}
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 first = iter.next().copied();
match first {
None => None,
Some(c) => {
let stream = ArraySourceStream {
_source: arr,
__iter: iter,
_current: c,
_current: first,
_posRaw: 0,
_posHighlevel: pos,
_isEnded: false,
};
return Some((stream, c));
}
}
return stream;
}
}
impl<'source, 'pos, C: Copy, PC: PosCounter<C>> ArraySourceStream<'source, C, PC> {
fn _next(&mut self) -> Option<C> {
if !self._isEnded {
self._posHighlevel.update(self._current);
if let Some(c) = self._current {
self._posHighlevel.update(c);
self._posRaw += 1;
}
match self.__iter.next() {
None => return None,
Some(c) => {
self._isEnded = true;
self._current = *c;
return Some(self._current);
}
}
self._current = self.__iter.next().copied();
return self._current;
}
}
@ -79,40 +67,13 @@ impl<'source, C: Copy, PC: PosCounter<C>> SourceStream for ArraySourceStream<'so
type P = PC::P;
type CS = ArrayCollectedSubstring<'source, C>;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C> {
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>) {
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS {
let startPosRaw = self._posRaw;
let wrongChar: Option<C>;
loop {
match self._next() {
None => {
wrongChar = None;
break;
}
Some(c) => match predicate.check(c) {
true => continue,
false => {
wrongChar = Some(c);
break;
}
},
}
}
self.skipNext(predicate);
let slice = &self._source[startPosRaw..self._posRaw];
return (ArrayCollectedSubstring { slice: slice }, wrongChar);
return ArrayCollectedSubstring { slice: slice };
}
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> {
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 std::marker::PhantomData;
pub struct EmptySourceStream<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> {
_pos: PC,
__phantom: PhantomData<(C, CS)>
__phantom: PhantomData<(C, CS)>,
}
impl<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> EmptySourceStream<C, CS, PC> {
pub fn start(pos: PC) -> (Self, Option<C>) {
let stream = EmptySourceStream { _pos: pos, __phantom: PhantomData::default() };
return (stream, None);
pub fn start(pos: PC) -> Self {
return EmptySourceStream {
_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 CS = CS;
fn skipNext(&mut self, _: &mut impl Predicate<Self::C>) -> Option<Self::C> {
return None;
fn skipCurrent(&mut self, _: &mut impl Predicate<Self::C>) -> bool {
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");
}
@ -36,4 +42,8 @@ impl<C: Copy, CS: CollectedSubstring<C = C>, PC: PosCounter<C>> SourceStream
fn nextChar(&mut self) -> Option<Self::C> {
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>> {
_source: &'source str,
__iter: CharIndices<'source>,
_current: char,
_current: Option<char>,
_posRaw: usize,
_posCodePoints: usize,
_posHighlevel: PC,
_isEnded: bool,
}
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 first = it.next();
match first {
None => return None,
Some((p, c)) => {
let stream = StrSourceStream {
let mut stream = StrSourceStream {
_source: s,
__iter: it,
_current: c,
_posRaw: p,
_current: None,
_posRaw: s.len(),
_posCodePoints: 0,
_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> {
fn _next(&mut self) -> Option<char> {
if !self._isEnded {
self._posHighlevel.update(self._current);
if let Some(c) = self._current {
self._posHighlevel.update(c);
self._posCodePoints += 1;
}
match self.__iter.next() {
None => return None,
None => {
self._posRaw = self._source.len();
self._current = None;
}
Some((p, c)) => {
self._isEnded = true;
self._posRaw = p;
self._current = c;
return Some(self._current);
self._current = Some(c);
}
}
return self._current;
}
}
@ -83,47 +88,17 @@ impl<'source, PC: PosCounter<char>> SourceStream for StrSourceStream<'source, PC
type P = PC::P;
type CS = StrCollectedSubstring<'source>;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C> {
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>) {
fn collect(&mut self, predicate: &mut impl Predicate<Self::C>) -> Self::CS {
let startPosRaw = self._posRaw;
let startPosCP = self._posCodePoints;
let wrongChar: Option<char>;
loop {
match self._next() {
None => {
wrongChar = None;
break;
}
Some(c) => match predicate.check(c) {
true => continue,
false => {
wrongChar = Some(c);
break;
}
},
}
}
self.skipNext(predicate);
let slice = &self._source[startPosRaw..self._posRaw];
return (
StrCollectedSubstring {
return StrCollectedSubstring {
slice: slice,
size: self._posCodePoints - startPosCP,
},
wrongChar,
);
};
}
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> {
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 CS: CollectedSubstring<C = Self::C>;
fn skipNext(&mut self, predicate: &mut impl Predicate<Self::C>) -> Option<Self::C>;
fn skipCurrent(
&mut self,
current: Self::C,
predicate: &mut impl Predicate<Self::C>,
) -> Option<Self::C> {
if !predicate.check(current) {
return Some(current);
) -> bool {
match self.currentChar() {
None => return true,
Some(c) => {
if !predicate.check(c) {
return false;
}
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
@ -36,9 +50,11 @@ pub trait SourceStream {
* Calling this method on ended stream (previous `nextChar` returned `None`)
* 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 nextChar(&mut self) -> Option<Self::C>;
fn currentChar(&self) -> Option<Self::C>;
}