use crate::{Cursor, Parse, Parser, Peek, Result, token_macros::Ident};
use bumpalo::collections::Vec;
pub trait FeatureConditionList<'a>: Sized + Parse<'a>
where
Self: 'a,
{
type FeatureCondition: Sized + Parse<'a>;
fn keyword_is_not<I>(p: &Parser<'a, I>, c: Cursor) -> bool
where
I: Iterator<Item = Cursor> + Clone;
fn keyword_is_or<I>(p: &Parser<'a, I>, c: Cursor) -> bool
where
I: Iterator<Item = Cursor> + Clone;
fn keyword_is_and<I>(p: &Parser<'a, I>, c: Cursor) -> bool
where
I: Iterator<Item = Cursor> + Clone;
fn build_is(feature: Self::FeatureCondition) -> Self;
fn build_not(keyword: Ident, feature: Self::FeatureCondition) -> Self;
fn build_and(features: Vec<'a, (Self::FeatureCondition, Option<Ident>)>) -> Self;
fn build_or(features: Vec<'a, (Self::FeatureCondition, Option<Ident>)>) -> Self;
fn parse_condition<I>(p: &mut Parser<'a, I>) -> Result<Self>
where
I: Iterator<Item = Cursor> + Clone,
{
let c = p.peek_n(1);
if Ident::peek(p, c) && Self::keyword_is_not(p, c) {
return Ok(Self::build_not(p.parse::<Ident>()?, p.parse::<Self::FeatureCondition>()?));
}
let mut feature = p.parse::<Self::FeatureCondition>()?;
let c = p.peek_n(1);
if Ident::peek(p, c) {
if Self::keyword_is_and(p, c) {
let mut features = Vec::new_in(p.bump());
let mut keyword = p.parse::<Ident>()?;
loop {
features.push((feature, Some(keyword)));
feature = p.parse::<Self::FeatureCondition>()?;
let c = p.peek_n(1);
if !(Ident::peek(p, c) && Self::keyword_is_and(p, c)) {
features.push((feature, None));
return Ok(Self::build_and(features));
}
keyword = p.parse::<Ident>()?
}
} else if Self::keyword_is_or(p, c) {
let mut features = Vec::new_in(p.bump());
let mut keyword = p.parse::<Ident>()?;
loop {
features.push((feature, Some(keyword)));
feature = p.parse::<Self::FeatureCondition>()?;
let c = p.peek_n(1);
if !(Ident::peek(p, c) && Self::keyword_is_or(p, c)) {
features.push((feature, None));
return Ok(Self::build_or(features));
}
keyword = p.parse::<Ident>()?
}
}
}
Ok(Self::build_is(feature))
}
}