use core::ops::{Deref, DerefMut};
use crate::{
predefined_node::{restore_on_none, Skipped},
tracker::Tracker,
wrapper::BoundWrapper,
Input, NeverFailedTypedNode, RuleType, Span, Stack, TypedNode,
};
use alloc::vec::Vec;
type Iter<'n, T, IGNORED, const SKIP: usize> = core::iter::Map<
alloc::slice::Iter<'n, Skipped<T, IGNORED, SKIP>>,
fn(&'n Skipped<T, IGNORED, SKIP>) -> &'n T,
>;
type IntoIter<T, IGNORED, const SKIP: usize> = core::iter::Map<
alloc::vec::IntoIter<Skipped<T, IGNORED, SKIP>>,
fn(Skipped<T, IGNORED, SKIP>) -> T,
>;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct AtomicRep<T> {
pub content: Vec<T>,
}
impl<T> Default for AtomicRep<T> {
fn default() -> Self {
let content = Vec::new();
Self { content }
}
}
impl<'i, R: RuleType, T: TypedNode<'i, R>> NeverFailedTypedNode<'i, R> for AtomicRep<T> {
fn parse_with<I: Input<'i>>(mut input: I, stack: &mut Stack<Span<'i>>) -> (I, Self) {
let mut vec = Vec::new();
let mut tracker = Tracker::new(input);
for _ in 0usize.. {
match restore_on_none(stack, |stack| {
T::try_parse_partial_with(input, stack, &mut tracker)
}) {
Some((next, matched)) => {
input = next;
vec.push(matched);
}
None => break,
}
}
(input, Self { content: vec })
}
}
impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for AtomicRep<T> {
#[inline]
fn try_parse_partial_with<I: Input<'i>>(
input: I,
stack: &mut Stack<Span<'i>>,
_tracker: &mut Tracker<'i, R>,
) -> Option<(I, Self)> {
Some(Self::parse_with(input, stack))
}
}
impl<T> Deref for AtomicRep<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.content
}
}
impl<T> DerefMut for AtomicRep<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.content
}
}
impl<T: Clone + PartialEq> BoundWrapper for AtomicRep<T> {
const MIN: usize = 0;
const MAX: usize = usize::MAX;
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RepMin<T, const MIN: usize> {
pub content: Vec<T>,
}
impl<
'i,
R: RuleType,
T: TypedNode<'i, R>,
Skip: NeverFailedTypedNode<'i, R>,
const SKIP: usize,
> NeverFailedTypedNode<'i, R> for RepMin<Skipped<T, Skip, SKIP>, 0>
{
fn parse_with<I: Input<'i>>(mut input: I, stack: &mut Stack<Span<'i>>) -> (I, Self) {
let mut vec = Vec::new();
let mut tracker = Tracker::new(input);
for i in 0usize.. {
match restore_on_none(stack, |stack| try_parse_unit(input, stack, &mut tracker, i)) {
Some((next, matched)) => {
input = next;
vec.push(matched);
}
None => break,
}
}
(input, Self { content: vec })
}
}
impl<T> Default for RepMin<T, 0> {
fn default() -> Self {
let content = Vec::new();
Self { content }
}
}
impl<
'i,
R: RuleType,
T: TypedNode<'i, R>,
Skip: NeverFailedTypedNode<'i, R>,
const SKIP: usize,
const MIN: usize,
> TypedNode<'i, R> for RepMin<Skipped<T, Skip, SKIP>, MIN>
{
#[inline]
fn try_parse_partial_with<I: Input<'i>>(
mut input: I,
stack: &mut Stack<Span<'i>>,
tracker: &mut Tracker<'i, R>,
) -> Option<(I, Self)> {
let mut vec = Vec::new();
for i in 0usize.. {
match restore_on_none(stack, |stack| try_parse_unit(input, stack, tracker, i)) {
Some((next, matched)) => {
input = next;
vec.push(matched);
}
None => {
if i < MIN {
return None;
} else {
break;
}
}
}
}
Some((input, Self { content: vec }))
}
}
impl<T, IGNORED, const SKIP: usize, const MIN: usize> RepMin<Skipped<T, IGNORED, SKIP>, MIN> {
pub fn iter_matched(&'_ self) -> Iter<'_, T, IGNORED, SKIP> {
self.content.iter().map(|s| &s.matched)
}
pub fn into_iter_matched(self) -> IntoIter<T, IGNORED, SKIP> {
self.content.into_iter().map(|s| s.matched)
}
}
impl<T, const MIN: usize> RepMin<T, MIN> {
pub fn iter_all(&'_ self) -> alloc::slice::Iter<'_, T> {
self.content.iter()
}
pub fn into_iter_all(self) -> alloc::vec::IntoIter<T> {
self.content.into_iter()
}
}
impl<T: Clone + PartialEq, const MIN: usize> BoundWrapper for RepMin<T, MIN> {
const MIN: usize = MIN;
const MAX: usize = usize::MAX;
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RepMinMax<T, const MIN: usize, const MAX: usize> {
pub content: Vec<T>,
}
impl<T, const MAX: usize> Default for RepMinMax<T, 0, MAX> {
fn default() -> Self {
Self {
content: Vec::new(),
}
}
}
impl<
'i,
R: RuleType,
T: TypedNode<'i, R>,
Skip: NeverFailedTypedNode<'i, R>,
const SKIP: usize,
const MAX: usize,
> NeverFailedTypedNode<'i, R> for RepMinMax<Skipped<T, Skip, SKIP>, 0, MAX>
{
#[inline]
fn parse_with<I: Input<'i>>(mut input: I, stack: &mut Stack<Span<'i>>) -> (I, Self) {
let mut vec = Vec::new();
let mut tracker = Tracker::new(input);
for i in 0..MAX {
match restore_on_none(stack, |stack| try_parse_unit(input, stack, &mut tracker, i)) {
Some((next, matched)) => {
input = next;
vec.push(matched);
}
None => {
break;
}
}
}
(input, Self { content: vec })
}
}
impl<
'i,
R: RuleType,
T: TypedNode<'i, R>,
Skip: NeverFailedTypedNode<'i, R>,
const SKIP: usize,
const MIN: usize,
const MAX: usize,
> TypedNode<'i, R> for RepMinMax<Skipped<T, Skip, SKIP>, MIN, MAX>
{
#[inline]
fn try_parse_partial_with<I: Input<'i>>(
mut input: I,
stack: &mut Stack<Span<'i>>,
tracker: &mut Tracker<'i, R>,
) -> Option<(I, Self)> {
let mut vec = Vec::new();
for i in 0..MAX {
match restore_on_none(stack, |stack| try_parse_unit(input, stack, tracker, i)) {
Some((next, matched)) => {
input = next;
vec.push(matched);
}
None => {
if i < MIN {
return None;
} else {
break;
}
}
}
}
Some((input, Self { content: vec }))
}
}
impl<T, IGNORED, const SKIP: usize, const MIN: usize, const MAX: usize>
RepMinMax<Skipped<T, IGNORED, SKIP>, MIN, MAX>
{
pub fn iter_matched(&'_ self) -> Iter<'_, T, IGNORED, SKIP> {
self.content.iter().map(|s| &s.matched)
}
pub fn into_iter_matched(self) -> IntoIter<T, IGNORED, SKIP> {
self.content.into_iter().map(|s| s.matched)
}
}
impl<T, const MIN: usize, const MAX: usize> RepMinMax<T, MIN, MAX> {
pub fn iter_all(&'_ self) -> alloc::slice::Iter<'_, T> {
self.content.iter()
}
pub fn into_iter_all(self) -> alloc::vec::IntoIter<T> {
self.content.into_iter()
}
}
impl<T: Clone + PartialEq, const MIN: usize, const MAX: usize> BoundWrapper
for RepMinMax<T, MIN, MAX>
{
const MIN: usize = MIN;
const MAX: usize = MAX;
}
pub type Rep<T, IGNORED, const SKIP: usize> = RepMin<Skipped<T, IGNORED, SKIP>, 0>;
pub type RepOnce<T, IGNORED, const SKIP: usize> = RepMin<Skipped<T, IGNORED, SKIP>, 1>;
fn try_parse_unit<
'i,
I: Input<'i>,
R: RuleType,
T: TypedNode<'i, R>,
Skip: NeverFailedTypedNode<'i, R>,
const SKIP: usize,
>(
mut input: I,
stack: &mut Stack<Span<'i>>,
tracker: &mut Tracker<'i, R>,
i: usize,
) -> Option<(I, Skipped<T, Skip, SKIP>)> {
let skipped = core::array::from_fn(|_| {
if i == 0 {
Skip::default()
} else {
let (next, skipped) = Skip::parse_with(input, stack);
input = next;
skipped
}
});
let (next, matched) = T::try_parse_partial_with(input, stack, tracker)?;
input = next;
let res = Skipped { skipped, matched };
Some((input, res))
}