use std::iter::Peekable;
use crate::{DEBUG, Tokenizer, Evaluation, Node, ExprToken, Operator, Error, Result, Value, NodeTest, NodeType, PrincipalNodeType, AxisName};
use crate::expressions::{ExpressionArg, ContextNode, RootNode, Path, Step, Literal, Equal, NotEqual, And, Or, Function};
use crate::nodetest;
use crate::functions;
type ExpressionResult = Result<Option<ExpressionArg>>;
#[derive(Clone)]
pub struct Document {
pub root: Node
}
impl Document {
pub fn new(root: Node) -> Self {
Self {
root
}
}
pub fn evaluate<S: Into<String>>(&self, search: S) -> Result<Value> {
self.evaluate_from(search, self.root.clone())
}
pub fn evaluate_from<S: Into<String>>(&self, search: S, node: Node) -> Result<Value> {
Factory::new(search, self, node)
.produce()
}
pub fn evaluate_steps(&self, steps: Vec<ExprToken>) -> Result<Value> {
Factory::new_from_steps(steps, self, self.root.clone())
.produce()
}
}
macro_rules! return_value {
($stepper:expr, ExprToken::$token:ident) => {{
let step = $stepper.next().ok_or(Error::InputEmpty)?;
match step {
ExprToken::$token(v) => v,
s => return Err(Error::UnexpectedToken(s))
}
}};
}
pub struct Factory<'a> {
eval: Evaluation<'a>,
tokenizer: Tokenizer,
token_steps: Vec<ExprToken>,
error: Option<Error>
}
impl<'a> Factory<'a> {
pub fn new<S: Into<String>>(query: S, document: &'a Document, node: Node) -> Self {
Factory {
eval: Evaluation::new(node, document),
tokenizer: Tokenizer::new(query),
token_steps: Vec::new(),
error: None
}
}
pub fn new_from_steps(steps: Vec<ExprToken>, document: &'a Document, node: Node) -> Self {
Factory {
eval: Evaluation::new(node, document),
tokenizer: Tokenizer::new(""),
token_steps: steps,
error: None
}
}
fn tokenize(&mut self) {
while !self.tokenizer.is_finished() {
match self.tokenizer.next().unwrap() {
Ok(step) => self.expand_abbreviation(step),
Err(e) => {
eprintln!("{:?}", e);
self.error = Some(e);
return;
}
}
}
}
fn expand_abbreviation(&mut self, token: ExprToken) {
match token {
ExprToken::AtSign => {
self.token_steps.push(AxisName::Attribute.into());
}
ExprToken::Operator(Operator::DoubleForwardSlash) => {
self.token_steps.extend([
Operator::ForwardSlash.into(),
AxisName::DescendantOrSelf.into(),
NodeType::Node.into(),
Operator::ForwardSlash.into()
].iter().cloned());
}
ExprToken::Period => {
self.token_steps.extend([
AxisName::SelfAxis.into(),
NodeType::Node.into()
].iter().cloned());
}
ExprToken::ParentNode => {
self.token_steps.extend([
AxisName::Parent.into(),
NodeType::Node.into()
].iter().cloned());
}
_ => self.token_steps.push(token)
}
}
pub fn produce(&mut self) -> Result<Value> {
self.tokenize();
if self.error.is_none() {
if DEBUG {
println!("Steps");
self.token_steps
.iter()
.for_each(|t| println!(" - {:?}", t));
}
let mut stepper = Stepper::new(self.token_steps.clone().into_iter().peekable());
if stepper.has_more_tokens() {
let expr = self.parse_expression(&mut stepper)?;
match expr {
Some(e) => {
if DEBUG { println!("Parsed: {:#?}", e); }
return e.eval(&self.eval);
}
None => {
return Err(Error::InvalidXpath);
}
}
}
if !stepper.has_more_tokens() {
println!("Finished.");
}
}
Err(Error::UnableToEvaluate)
}
fn parse_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
self.parse_or_expression(step)
}
fn parse_or_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let left_expr = self.parse_and_expression(step)?;
if step.consume_if_next_token_is(Operator::Or)? {
let right_expr = self.parse_relational_expression(step)?;
return Ok(Some(Box::new(Or::new(left_expr.unwrap(), right_expr.ok_or(Error::MissingRightHandExpression)?))));
}
Ok(left_expr)
}
fn parse_and_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let left_expr = self.parse_equality_expression(step)?;
if step.consume_if_next_token_is(Operator::And)? {
let right_expr = self.parse_relational_expression(step)?;
return Ok(Some(Box::new(And::new(left_expr.unwrap(), right_expr.ok_or(Error::MissingRightHandExpression)?))));
}
Ok(left_expr)
}
fn parse_equality_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let left_expr = self.parse_relational_expression(step)?;
if step.consume_if_next_token_is(Operator::Equal)? {
let right_expr = self.parse_relational_expression(step)?;
return Ok(Some(Box::new(Equal::new(left_expr.unwrap(), right_expr.ok_or(Error::MissingRightHandExpression)?))));
}
if step.consume_if_next_token_is(Operator::DoesNotEqual)? {
let right_expr = self.parse_relational_expression(step)?;
return Ok(Some(Box::new(NotEqual::new(left_expr.unwrap(), right_expr.ok_or(Error::MissingRightHandExpression)?))));
}
Ok(left_expr)
}
fn parse_relational_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let left_expr = self.parse_additive_expression(step)?;
Ok(left_expr)
}
fn parse_additive_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let left_expr = self.parse_multiplicative_expression(step)?;
Ok(left_expr)
}
fn parse_multiplicative_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let left_expr = self.parse_unary_expression(step)?;
Ok(left_expr)
}
fn parse_unary_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
if step.is_next_token(Operator::Minus) {
let _ = step.consume(Operator::Minus)?;
}
self.parse_union_expression(step)
}
fn parse_union_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
self.parse_path_expression(step)
}
fn parse_path_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let expr = self.parse_location_path_expression(step)?;
if expr.is_some() {
return Ok(expr);
}
match self.parse_filter_expression(step)? {
Some(expr) => {
if step.is_next_token(Operator::ForwardSlash) {
step.consume(Operator::ForwardSlash)?;
let expr = self.parse_location_path_raw(step, expr)?;
Ok(Some(expr.expect("parse_path_expression")))
} else {
Ok(Some(expr))
}
}
None => Ok(None),
}
}
fn parse_location_path_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
let path = self.parse_relative_location_path(step)?;
if path.is_some() {
Ok(path)
} else {
self.parse_absolute_location_path(step)
}
}
fn parse_relative_location_path<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
self.parse_location_path_raw(step, Box::new(ContextNode))
}
fn parse_absolute_location_path<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
if step.is_next_token(Operator::ForwardSlash) {
step.consume(Operator::ForwardSlash)?;
match self.parse_location_path_raw(step, Box::new(RootNode))? {
Some(expr) => Ok(Some(expr)),
None => Ok(Some(Box::new(RootNode))),
}
} else {
Ok(None)
}
}
fn parse_abbreviated_relative_location_path<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
Ok(None)
}
fn parse_location_path_raw<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>, start_point: ExpressionArg) -> ExpressionResult {
match self.parse_step(step)? {
Some(expr_step) => {
let mut steps = vec![expr_step];
while step.is_next_token(Operator::ForwardSlash) {
step.consume(Operator::ForwardSlash)?;
let next = self.parse_step(step)?;
steps.push(next.ok_or(Error::TrailingSlash)?);
}
Ok(Some(Box::new(Path::new(start_point, steps))))
}
None => Ok(None),
}
}
fn parse_step<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> Result<Option<Step>> {
let axis = self.parse_axis_specifier(step)?;
let node_test = match self.parse_node_test(step)? {
Some(test) => Some(test),
None => self.default_node_test(step, axis)?,
};
let node_test = match node_test {
Some(test) => test,
None => return Ok(None),
};
let predicates = self.parse_predicate_expressions(step)?;
Ok(Some(Step::new(axis, node_test, predicates)))
}
fn parse_axis_specifier<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> Result<AxisName> {
if step.is_next_token_func(|t| t.is_axis()) {
Ok(return_value!(step, ExprToken::Axis))
} else {
Ok(AxisName::Child)
}
}
fn parse_filter_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
if let Some(expr) = self.parse_primary_expression(step)? {
Ok(Some(expr))
} else {
Ok(None)
}
}
fn parse_primary_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
if step.is_next_token_func(|i| i.is_literal()) {
let value = return_value!(step, ExprToken::Literal);
return Ok(Some(Box::new(Literal::from(Value::String(value)))));
}
if step.is_next_token_func(|i| i.is_number()) {
let value = return_value!(step, ExprToken::Number);
return Ok(Some(Box::new(Literal::from(Value::Number(value)))));
}
if let Some(func) = self.parse_function_call(step)? {
return Ok(Some(Box::new(Function::new(func))));
}
Ok(None)
}
fn parse_function_call<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> Result<Option<Box<dyn functions::Function>>> {
if step.is_next_token_func(|i| i.is_function_name()) {
let fn_name = return_value!(step, ExprToken::FunctionName);
step.consume(ExprToken::LeftParen)?;
match fn_name.as_str() {
"last" => {
step.consume(ExprToken::RightParen)?;
Ok(Some(Box::new(functions::Last)))
}
"position" => {
step.consume(ExprToken::RightParen)?;
Ok(Some(Box::new(functions::Position)))
}
"true" => {
step.consume(ExprToken::RightParen)?;
Ok(Some(Box::new(functions::True)))
}
"false" => {
step.consume(ExprToken::RightParen)?;
Ok(Some(Box::new(functions::False)))
}
"contains" => {
let expr = self.parse_expression(step)?;
step.consume(ExprToken::Comma)?;
let value = return_value!(step, ExprToken::Literal);
step.consume(ExprToken::RightParen)?;
if let Some(expr) = expr {
Ok(Some(Box::new(functions::Contains::new(expr, Value::String(value)))))
} else {
Ok(None)
}
}
"not" => {
let expr = self.parse_expression(step)?;
step.consume(ExprToken::RightParen)?;
if let Some(expr) = expr {
Ok(Some(Box::new(functions::Not::new(expr))))
} else {
Ok(None)
}
}
_ => Ok(None)
}
} else {
Ok(None)
}
}
fn parse_node_test<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> Result<Option<Box<dyn NodeTest>>> {
if step.is_next_token_func(|t| t.is_node_type()) {
let name = return_value!(step, ExprToken::NodeType);
match name {
NodeType::Node => Ok(Some(Box::new(nodetest::Node))),
NodeType::Text => Ok(Some(Box::new(nodetest::Text))),
NodeType::Comment => Ok(Some(Box::new(nodetest::Comment))),
NodeType::ProcessingInstruction(target) => Ok(Some(Box::new(
nodetest::ProcessingInstruction::new(target),
))),
}
} else {
Ok(None)
}
}
fn default_node_test<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>, axis: AxisName) -> Result<Option<Box<dyn NodeTest>>> {
if step.is_next_token_func(|t| t.is_name_test()) {
let name = return_value!(step, ExprToken::NameTest);
let test: Box<dyn NodeTest> = match axis.principal_node_type() {
PrincipalNodeType::Attribute => Box::new(nodetest::Attribute::new(name)),
PrincipalNodeType::Element => Box::new(nodetest::Element::new(name)),
PrincipalNodeType::Namespace => Box::new(nodetest::Namespace::new(name)),
};
Ok(Some(test))
} else {
Ok(None)
}
}
fn parse_predicate_expressions<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> Result<Vec<ExpressionArg>> {
let mut expr = Vec::new();
while let Some(pred) = self.parse_predicate_expression(step)? {
expr.push(pred);
}
Ok(expr)
}
fn parse_predicate_expression<S: Iterator<Item = ExprToken>>(&self, step: &mut Stepper<S>) -> ExpressionResult {
if step.is_next_token(ExprToken::LeftBracket) {
step.consume(ExprToken::LeftBracket)?;
let val = self.parse_expression(step)?;
step.consume(ExprToken::RightBracket)?;
Ok(val)
} else {
Ok(None)
}
}
}
pub struct Stepper<S: Iterator<Item = ExprToken>>(Peekable<S>);
impl<S: Iterator<Item = ExprToken>> Stepper<S> {
pub fn new(steps: Peekable<S>) -> Self {
Stepper(steps)
}
pub fn has_more_tokens(&mut self) -> bool {
self.peek().is_some()
}
pub fn is_next_token<T: Into<ExprToken>>(&mut self, token: T) -> bool {
match self.peek() {
Some(t) => t == &token.into(),
None => false
}
}
pub fn is_next_token_func<F: FnOnce(&S::Item) -> bool>(&mut self, token: F) -> bool {
match self.peek() {
Some(t) => token(t),
None => false
}
}
pub fn consume_if_next_token_is<T: Into<ExprToken> + Copy>(&mut self, token: T) -> Result<bool> {
if self.is_next_token(token) {
self.consume(token)?;
Ok(true)
} else {
Ok(false)
}
}
pub fn consume<T: Into<ExprToken>>(&mut self, token: T) -> Result<()> {
let step = self.next().ok_or(Error::InputEmpty)?;
if step == token.into() {
Ok(())
} else {
Err(Error::UnexpectedToken(step))
}
}
pub fn consume_func<F: FnOnce(&S::Item) -> bool>(&mut self, token: F) -> Result<()> {
let step = self.next().ok_or(Error::InputEmpty)?;
if token(&step) {
Ok(())
} else {
Err(Error::UnexpectedToken(step))
}
}
pub fn peek(&mut self) -> Option<&S::Item> {
self.0.peek()
}
}
impl<S: Iterator<Item = ExprToken>> Iterator for Stepper<S> {
type Item = S::Item;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}