use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Axis {
Ancestor,
AncestorOrSelf,
Attribute,
Child,
Descendant,
DescendantOrSelf,
Following,
FollowingSibling,
Namespace,
Parent,
Preceding,
PrecedingSibling,
Self_,
}
impl Axis {
pub const ALL: &'static [Axis] = &[
Axis::Ancestor,
Axis::AncestorOrSelf,
Axis::Attribute,
Axis::Child,
Axis::Descendant,
Axis::DescendantOrSelf,
Axis::Following,
Axis::FollowingSibling,
Axis::Namespace,
Axis::Parent,
Axis::Preceding,
Axis::PrecedingSibling,
Axis::Self_,
];
pub fn as_str(&self) -> &'static str {
match self {
Axis::Ancestor => "ancestor",
Axis::AncestorOrSelf => "ancestor-or-self",
Axis::Attribute => "attribute",
Axis::Child => "child",
Axis::Descendant => "descendant",
Axis::DescendantOrSelf => "descendant-or-self",
Axis::Following => "following",
Axis::FollowingSibling => "following-sibling",
Axis::Namespace => "namespace",
Axis::Parent => "parent",
Axis::Preceding => "preceding",
Axis::PrecedingSibling => "preceding-sibling",
Axis::Self_ => "self",
}
}
}
impl fmt::Display for Axis {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum NodeTest {
NameTest(NameTest),
Comment,
Text,
ProcessingInstruction(Option<String>),
Node,
Wildcard,
NsWildcard(String),
}
#[derive(Debug, Clone, PartialEq)]
pub enum NameTest {
LocalName(String),
QName { prefix: String, local: String },
Any,
}
impl fmt::Display for NodeTest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NodeTest::NameTest(n) => match n {
NameTest::LocalName(s) => write!(f, "{}", s),
NameTest::QName { prefix, local } => write!(f, "{}:{}", prefix, local),
NameTest::Any => write!(f, "*"),
},
NodeTest::Comment => write!(f, "comment()"),
NodeTest::Text => write!(f, "text()"),
NodeTest::ProcessingInstruction(None) => write!(f, "processing-instruction()"),
NodeTest::ProcessingInstruction(Some(t)) => {
write!(f, "processing-instruction('{}')", t)
}
NodeTest::Node => write!(f, "node()"),
NodeTest::Wildcard => write!(f, "*"),
NodeTest::NsWildcard(prefix) => write!(f, "{}:*", prefix),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Step {
pub axis: Axis,
pub node_test: NodeTest,
pub predicates: Vec<Expr>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BinaryOp {
Union,
And,
Or,
Eq,
Ne,
Lt,
Gt,
Le,
Ge,
Add,
Sub,
Mul,
Div,
Mod,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
AbsolutePath(Box<Expr>),
RelativePath(Box<Expr>, Box<Expr>),
Step(Step),
Filter(Box<Expr>, Vec<Expr>),
Variable(String),
StringLiteral(String),
NumberLiteral(f64),
BooleanLiteral(bool),
FunctionCall { name: String, args: Vec<Expr> },
BinaryOp {
op: BinaryOp,
left: Box<Expr>,
right: Box<Expr>,
},
UnaryMinus(Box<Expr>),
Union(Box<Expr>, Box<Expr>),
}
impl Expr {
pub fn is_location_path(&self) -> bool {
matches!(
self,
Expr::AbsolutePath(_) | Expr::RelativePath(_, _) | Expr::Step(_) | Expr::Filter(_, _)
)
}
pub fn is_constant(&self) -> bool {
matches!(
self,
Expr::StringLiteral(_) | Expr::NumberLiteral(_) | Expr::BooleanLiteral(_)
)
}
}
#[derive(Debug, Clone)]
pub struct CompiledExpr {
pub original: String,
pub expr: Expr,
}
impl CompiledExpr {
pub fn new(original: String, expr: Expr) -> Self {
Self { original, expr }
}
}