use crate::item::{Item, Node};
use crate::parser::combinators::alt::alt2;
use crate::parser::combinators::many::{many0, many1};
use crate::parser::combinators::map::map;
use crate::parser::{
ParseError, ParseInput, ParserState, ParserStateBuilder, StaticState, StaticStateBuilder,
};
use crate::value::Value;
use crate::xdmerror::{Error, ErrorKind};
use std::rc::Rc;
use crate::parser::combinators::support::none_of;
use crate::parser::xpath::expr;
use crate::transform::Transform;
use qualname::{NamespacePrefix, NamespaceUri};
pub fn parse<N: Node>(input: &str, n: Option<N>) -> Result<Transform<N>, Error> {
let state = n.map_or_else(
|| ParserState::new(),
|m| ParserStateBuilder::new().doc(m).build(),
);
let mut static_state = StaticStateBuilder::new()
.namespace(|_| {
NamespaceUri::try_from("urn:xrust").map_err(|_| ParseError::MissingNameSpace)
})
.build();
match avt_expr((input, state), &mut static_state) {
Ok((_, x)) => Ok(x),
Err(err) => match err {
ParseError::Combinator(f) => Result::Err(Error::new(
ErrorKind::ParseError,
format!("Unrecoverable parser error ({})", f),
)),
ParseError::NotWellFormed(e) => Result::Err(Error::new(
ErrorKind::ParseError,
format!("Unrecognised extra characters: \"{}\"", e),
)),
ParseError::Notimplemented => Result::Err(Error::new(
ErrorKind::ParseError,
"Unimplemented feature.".to_string(),
)),
_ => Err(Error::new(ErrorKind::Unknown, "Unknown error".to_string())),
},
}
}
fn avt_expr<'a, N: Node + 'a, L>(
input: ParseInput<'a, N>,
ss: &mut StaticState<L>,
) -> Result<(ParseInput<'a, N>, Transform<N>), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
{
match avt::<N, L>()(input, ss) {
Err(err) => Err(err),
Ok(((input1, state1), e)) => {
if input1.is_empty() {
Ok(((input1, state1), e))
} else {
Err(ParseError::NotWellFormed(format!(
"unexpected extra characters: \"{}\"",
input1
)))
}
}
}
}
fn avt<'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(
many0(alt2(
map(many1(none_of("{")), |v| {
Transform::Literal(Item::Value(Rc::new(Value::from(
v.iter().fold(String::new(), |mut s, w| {
s.push_str(w);
s
}), ))))
}),
braced_expr(),
)),
|mut v| {
if v.len() == 1 {
v.pop().unwrap()
} else {
Transform::SequenceItems(v)
}
},
))
}
fn braced_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>,
{
Box::new(move |(input, state), ss| {
match input.get(0..1) {
Some("{") => match input.find('}') {
None => Err(ParseError::Combinator(String::from("no closing brace"))),
Some(ind) => match expr()((input.get(1..ind).unwrap(), state.clone()), ss) {
Ok((_, result)) => {
Ok(((input.get((ind + 1)..).map_or("", |r| r), state), result))
}
Err(e) => Err(e),
},
},
_ => Err(ParseError::Combinator(String::from(
"closing brace not found",
))),
}
})
}