use std::cmp::Ordering;
use crate::item::Node;
use crate::parser::combinators::alt::alt4;
use crate::parser::combinators::many::{many0, many1};
use crate::parser::combinators::map::map;
use crate::parser::combinators::tag::tag;
use crate::parser::combinators::tuple::tuple3;
use crate::parser::{ParseError, ParseInput, StaticState};
use qualname::{NamespacePrefix, NamespaceUri};
pub fn whitespace0<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, ()), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
many0(alt4(tag(" "), tag("\t"), tag("\r"), tag("\n"))),
|_| (),
)
}
pub(crate) fn whitespace1<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, ()), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
many1(alt4(tag(" "), tag("\t"), tag("\r"), tag("\n"))),
|_| (),
)
}
pub(crate) fn xpwhitespace<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, ()), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
tuple3(
whitespace0(),
take_until_balanced("(:", ":)"),
whitespace0(),
),
|_| (),
)
}
fn take_until_balanced<'a, N: Node, L>(
open: &'static str,
close: &'static str,
) -> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, ()), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
move |(input, state), _ss| {
let mut pos = 0;
let mut counter = 0;
let mut bracket_counter = 0;
loop {
counter += 1;
if counter > 1000 {
return Err(ParseError::EntityDepth {
row: 0,
col: counter,
});
}
match (input[pos..].find(open), input[pos..].find(close)) {
(Some(0), _) => {
bracket_counter += 1;
pos += open.len();
match (input[pos..].find(open), input[pos..].find(close)) {
(_, None) => {
return Err(ParseError::Unbalanced);
}
(Some(o), Some(c)) => {
if o > c {
if bracket_counter == 1 {
pos += c + close.len();
return Ok(((&input[pos..], state), ()));
} else {
return Err(ParseError::Unbalanced);
}
} else {
bracket_counter += 1;
pos += o + close.len();
}
}
(_, Some(c)) => {
match bracket_counter.cmp(&1) {
Ordering::Greater => {
bracket_counter -= 1;
pos += c + close.len();
}
Ordering::Equal => {
pos += c + close.len();
return Ok(((&input[pos..], state), ()));
}
Ordering::Less => {
return Err(ParseError::Unbalanced);
}
}
}
}
}
(None, Some(c)) => {
match bracket_counter.cmp(&1) {
Ordering::Greater => {
bracket_counter -= 1;
pos += c + close.len();
}
Ordering::Equal => {
pos += c + close.len();
return Ok(((&input[pos..], state), ()));
}
Ordering::Less => {
return Err(ParseError::Unbalanced);
}
}
}
_ => return Ok(((&input[pos..], state), ())),
}
}
}
}