use crate::item::Node;
use crate::parser::combinators::list::separated_list1;
use crate::parser::combinators::map::{map, map_with_state};
use crate::parser::combinators::pair::pair;
use crate::parser::combinators::tag::tag;
use crate::parser::combinators::tuple::{tuple3, tuple5, tuple6, tuple10};
use crate::parser::combinators::whitespace::xpwhitespace;
use crate::parser::xpath::nodetests::qualname_test;
use crate::parser::xpath::support::get_nt_localname;
use crate::parser::xpath::{expr_single_wrapper, expr_wrapper};
use crate::parser::{ParseError, ParseInput, StaticState};
use crate::transform::{Transform, in_scope_namespaces};
use qualname::{NamespacePrefix, NamespaceUri};
pub(crate) fn if_expr<'a, N: Node + 'a, L>() -> Box<
dyn Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<(ParseInput<'a, N>, Transform<N>), ParseError>
+ 'a,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
{
Box::new(map(
pair(
tuple10(
tag("if"),
xpwhitespace(),
tag("("),
xpwhitespace(),
expr_wrapper::<N, L>(true),
xpwhitespace(),
tag(")"),
xpwhitespace(),
tag("then"),
xpwhitespace(),
),
tuple5(
expr_single_wrapper::<N, L>(true),
xpwhitespace(),
tag("else"),
xpwhitespace(),
expr_single_wrapper::<N, L>(true),
),
),
|((_, _, _, _, i, _, _, _, _, _), (t, _, _, _, e))| {
Transform::Switch(vec![(i, t)], Box::new(e))
},
))
}
pub(crate) fn for_expr<'a, N: Node + 'a, L>() -> Box<
dyn Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<(ParseInput<'a, N>, Transform<N>), ParseError>
+ 'a,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
{
Box::new(map(
tuple3(
simple_for_clause::<N, L>(),
tuple3(xpwhitespace(), tag("return"), xpwhitespace()),
expr_single_wrapper::<N, L>(true),
),
|(f, _, e)| Transform::Loop(f, Box::new(e)), ))
}
fn simple_for_clause<'a, N: Node + 'a, L>() -> Box<
dyn Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<(ParseInput<'a, N>, Vec<(String, Transform<N>)>), ParseError>
+ 'a,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
{
Box::new(map(
tuple3(
tag("for"),
xpwhitespace(),
separated_list1(
map(tuple3(xpwhitespace(), tag(","), xpwhitespace()), |_| ()),
map(
tuple6(
tag("$"),
qualname_test(),
xpwhitespace(),
tag("in"),
xpwhitespace(),
expr_single_wrapper::<N, L>(true),
),
|(_, qn, _, _, _, e)| (get_nt_localname(&qn), e),
),
),
),
|(_, _, v)| v,
))
}
pub(crate) fn let_expr<'a, N: Node + 'a, L>() -> Box<
dyn Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<(ParseInput<'a, N>, Transform<N>), ParseError>
+ 'a,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
{
Box::new(map_with_state(
tuple3(
simple_let_clause::<N, L>(),
tuple3(xpwhitespace(), tag("return"), xpwhitespace()),
expr_single_wrapper::<N, L>(true),
),
|(mut v, _, e), state, _ss| {
let (qn, f) = v.pop().unwrap();
let mut result = Transform::VariableDeclaration(
qn,
Box::new(f),
Box::new(e),
in_scope_namespaces(state.cur.clone()),
);
loop {
if v.is_empty() {
break;
} else {
let (qn, f) = v.pop().unwrap();
let inter = Transform::VariableDeclaration(
qn,
Box::new(f),
Box::new(result),
in_scope_namespaces(state.cur.clone()),
);
result = inter;
}
}
result
},
))
}
fn simple_let_clause<'a, N: Node + 'a, L>() -> Box<
dyn Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<(ParseInput<'a, N>, Vec<(String, Transform<N>)>), ParseError>
+ 'a,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
{
Box::new(map(
tuple3(
tag("let"),
xpwhitespace(),
separated_list1(
map(tuple3(xpwhitespace(), tag(","), xpwhitespace()), |_| ()),
map(
tuple6(
tag("$"),
qualname_test(),
xpwhitespace(),
tag(":="),
xpwhitespace(),
expr_single_wrapper::<N, L>(true),
),
|(_, qn, _, _, _, e)| (get_nt_localname(&qn), e),
),
),
),
|(_, _, v)| v,
))
}