mod array;
mod conditional;
mod for_expr;
mod func_call;
mod object;
mod operation;
mod traversal;
pub use self::array::{Array, IntoIter, Iter, IterMut};
pub use self::conditional::Conditional;
pub use self::for_expr::{ForCond, ForExpr, ForIntro};
pub use self::func_call::{FuncArgs, FuncCall, FuncName};
pub use self::object::{
Object, ObjectIntoIter, ObjectIter, ObjectIterMut, ObjectKey, ObjectKeyMut, ObjectValue,
ObjectValueAssignment, ObjectValueTerminator,
};
pub use self::operation::{BinaryOp, BinaryOperator, UnaryOp, UnaryOperator};
pub use self::traversal::{Splat, Traversal, TraversalOperator};
use crate::encode::{EncodeDecorated, EncodeState, NO_DECOR};
use crate::template::{HeredocTemplate, StringTemplate, Template};
use crate::{parser, Decor, Decorate, Decorated, Formatted, Ident, Number};
use std::borrow::Cow;
use std::fmt;
use std::ops::Range;
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expression {
Null(Decorated<Null>),
Bool(Decorated<bool>),
Number(Formatted<Number>),
String(Decorated<String>),
Array(Array),
Object(Object),
StringTemplate(StringTemplate),
HeredocTemplate(Box<HeredocTemplate>),
Parenthesis(Box<Parenthesis>),
Variable(Decorated<Ident>),
Conditional(Box<Conditional>),
FuncCall(Box<FuncCall>),
Traversal(Box<Traversal>),
UnaryOp(Box<UnaryOp>),
BinaryOp(Box<BinaryOp>),
ForExpr(Box<ForExpr>),
}
impl Expression {
pub fn null() -> Expression {
Expression::Null(Decorated::new(Null))
}
pub fn is_null(&self) -> bool {
matches!(self, Expression::Null(_))
}
pub fn is_bool(&self) -> bool {
self.as_bool().is_some()
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Expression::Bool(value) => Some(*value.value()),
_ => None,
}
}
pub fn is_number(&self) -> bool {
self.as_number().is_some()
}
pub fn as_number(&self) -> Option<&Number> {
match self {
Expression::Number(value) => Some(value.value()),
_ => None,
}
}
pub fn is_str(&self) -> bool {
self.as_str().is_some()
}
pub fn as_str(&self) -> Option<&str> {
match self {
Expression::String(value) => Some(value.value()),
_ => None,
}
}
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
pub fn as_array(&self) -> Option<&Array> {
match self {
Expression::Array(value) => Some(value),
_ => None,
}
}
pub fn as_array_mut(&mut self) -> Option<&mut Array> {
match self {
Expression::Array(value) => Some(value),
_ => None,
}
}
pub fn is_object(&self) -> bool {
self.as_object().is_some()
}
pub fn as_object(&self) -> Option<&Object> {
match self {
Expression::Object(value) => Some(value),
_ => None,
}
}
pub fn as_object_mut(&mut self) -> Option<&mut Object> {
match self {
Expression::Object(value) => Some(value),
_ => None,
}
}
pub fn is_template(&self) -> bool {
self.as_template().is_some()
}
pub fn as_template(&self) -> Option<&Template> {
match self {
Expression::StringTemplate(value) => Some(value),
Expression::HeredocTemplate(value) => Some(&value.template),
_ => None,
}
}
pub fn is_string_template(&self) -> bool {
self.as_string_template().is_some()
}
pub fn as_string_template(&self) -> Option<&StringTemplate> {
match self {
Expression::StringTemplate(value) => Some(value),
_ => None,
}
}
pub fn is_heredoc_template(&self) -> bool {
self.as_heredoc_template().is_some()
}
pub fn as_heredoc_template(&self) -> Option<&HeredocTemplate> {
match self {
Expression::HeredocTemplate(value) => Some(value),
_ => None,
}
}
pub fn is_parenthesis(&self) -> bool {
self.as_parenthesis().is_some()
}
pub fn as_parenthesis(&self) -> Option<&Parenthesis> {
match self {
Expression::Parenthesis(value) => Some(value),
_ => None,
}
}
pub fn is_variable(&self) -> bool {
self.as_variable().is_some()
}
pub fn as_variable(&self) -> Option<&Ident> {
match self {
Expression::Variable(value) => Some(value.value()),
_ => None,
}
}
pub fn is_conditional(&self) -> bool {
self.as_conditional().is_some()
}
pub fn as_conditional(&self) -> Option<&Conditional> {
match self {
Expression::Conditional(value) => Some(value),
_ => None,
}
}
pub fn is_func_call(&self) -> bool {
self.as_func_call().is_some()
}
pub fn as_func_call(&self) -> Option<&FuncCall> {
match self {
Expression::FuncCall(value) => Some(value),
_ => None,
}
}
pub fn is_traversal(&self) -> bool {
self.as_traversal().is_some()
}
pub fn as_traversal(&self) -> Option<&Traversal> {
match self {
Expression::Traversal(value) => Some(value),
_ => None,
}
}
pub fn is_unary_op(&self) -> bool {
self.as_unary_op().is_some()
}
pub fn as_unary_op(&self) -> Option<&UnaryOp> {
match self {
Expression::UnaryOp(value) => Some(value),
_ => None,
}
}
pub fn is_binary_op(&self) -> bool {
self.as_binary_op().is_some()
}
pub fn as_binary_op(&self) -> Option<&BinaryOp> {
match self {
Expression::BinaryOp(value) => Some(value),
_ => None,
}
}
pub fn is_for_expr(&self) -> bool {
self.as_for_expr().is_some()
}
pub fn as_for_expr(&self) -> Option<&ForExpr> {
match self {
Expression::ForExpr(value) => Some(value),
_ => None,
}
}
pub(crate) fn despan(&mut self, input: &str) {
match self {
Expression::Null(n) => n.decor_mut().despan(input),
Expression::Bool(b) => b.decor_mut().despan(input),
Expression::Number(n) => n.decor_mut().despan(input),
Expression::String(s) => s.decor_mut().despan(input),
Expression::Array(array) => array.despan(input),
Expression::Object(object) => object.despan(input),
Expression::StringTemplate(template) => template.despan(input),
Expression::HeredocTemplate(heredoc) => heredoc.despan(input),
Expression::Parenthesis(expr) => expr.despan(input),
Expression::Variable(var) => var.decor_mut().despan(input),
Expression::ForExpr(expr) => expr.despan(input),
Expression::Conditional(cond) => cond.despan(input),
Expression::FuncCall(call) => call.despan(input),
Expression::UnaryOp(op) => op.despan(input),
Expression::BinaryOp(op) => op.despan(input),
Expression::Traversal(traversal) => traversal.despan(input),
}
}
}
impl FromStr for Expression {
type Err = parser::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
parser::parse_expr(s)
}
}
macro_rules! impl_from_integer {
($($ty:ty),*) => {
$(
impl From<$ty> for Expression {
fn from(n: $ty) -> Self {
Expression::from(Number::from(n))
}
}
)*
};
}
impl_from_integer!(i8, i16, i32, i64, isize);
impl_from_integer!(u8, u16, u32, u64, usize);
impl From<f32> for Expression {
fn from(f: f32) -> Self {
From::from(f64::from(f))
}
}
impl From<f64> for Expression {
fn from(f: f64) -> Self {
Number::from_f64(f).map_or_else(Expression::null, Into::into)
}
}
impl From<bool> for Expression {
fn from(value: bool) -> Self {
Expression::from(Decorated::new(value))
}
}
impl From<Decorated<bool>> for Expression {
fn from(value: Decorated<bool>) -> Self {
Expression::Bool(value)
}
}
impl From<Number> for Expression {
fn from(value: Number) -> Self {
Expression::from(Formatted::new(value))
}
}
impl From<Formatted<Number>> for Expression {
fn from(value: Formatted<Number>) -> Self {
Expression::Number(value)
}
}
impl From<&str> for Expression {
fn from(value: &str) -> Self {
Expression::from(String::from(value))
}
}
impl From<String> for Expression {
fn from(value: String) -> Self {
Expression::from(Decorated::new(value))
}
}
impl<'a> From<Cow<'a, str>> for Expression {
fn from(s: Cow<'a, str>) -> Self {
Expression::from(s.into_owned())
}
}
impl From<Decorated<String>> for Expression {
fn from(value: Decorated<String>) -> Self {
Expression::String(value)
}
}
impl From<Array> for Expression {
fn from(value: Array) -> Self {
Expression::Array(value)
}
}
impl From<Object> for Expression {
fn from(value: Object) -> Self {
Expression::Object(value)
}
}
impl From<StringTemplate> for Expression {
fn from(value: StringTemplate) -> Self {
Expression::StringTemplate(value)
}
}
impl From<HeredocTemplate> for Expression {
fn from(value: HeredocTemplate) -> Self {
Expression::HeredocTemplate(Box::new(value))
}
}
impl From<Parenthesis> for Expression {
fn from(value: Parenthesis) -> Self {
Expression::Parenthesis(Box::new(value))
}
}
impl From<Ident> for Expression {
fn from(value: Ident) -> Self {
Expression::from(Decorated::new(value))
}
}
impl From<Decorated<Ident>> for Expression {
fn from(value: Decorated<Ident>) -> Self {
Expression::Variable(value)
}
}
impl From<Conditional> for Expression {
fn from(value: Conditional) -> Self {
Expression::Conditional(Box::new(value))
}
}
impl From<FuncCall> for Expression {
fn from(value: FuncCall) -> Self {
Expression::FuncCall(Box::new(value))
}
}
impl From<Traversal> for Expression {
fn from(value: Traversal) -> Self {
Expression::Traversal(Box::new(value))
}
}
impl From<UnaryOp> for Expression {
fn from(value: UnaryOp) -> Self {
Expression::UnaryOp(Box::new(value))
}
}
impl From<BinaryOp> for Expression {
fn from(value: BinaryOp) -> Self {
Expression::BinaryOp(Box::new(value))
}
}
impl From<ForExpr> for Expression {
fn from(value: ForExpr) -> Self {
Expression::ForExpr(Box::new(value))
}
}
impl<T> From<Vec<T>> for Expression
where
T: Into<Expression>,
{
fn from(value: Vec<T>) -> Self {
Expression::from_iter(value)
}
}
impl<'a, T> From<&'a [T]> for Expression
where
T: Clone + Into<Expression>,
{
fn from(value: &'a [T]) -> Self {
value.iter().cloned().collect()
}
}
impl<T: Into<Expression>> FromIterator<T> for Expression {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Expression::Array(Array::from_iter(iter))
}
}
impl<K: Into<ObjectKey>, V: Into<ObjectValue>> FromIterator<(K, V)> for Expression {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
Expression::Object(Object::from_iter(iter))
}
}
impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut state = EncodeState::new(f);
self.encode_decorated(&mut state, NO_DECOR)
}
}
#[derive(Debug, Clone, Eq)]
pub struct Parenthesis {
inner: Expression,
decor: Decor,
span: Option<Range<usize>>,
}
impl Parenthesis {
pub fn new(inner: Expression) -> Parenthesis {
Parenthesis {
inner,
decor: Decor::default(),
span: None,
}
}
pub fn inner(&self) -> &Expression {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut Expression {
&mut self.inner
}
pub fn into_inner(self) -> Expression {
self.inner
}
pub(crate) fn despan(&mut self, input: &str) {
self.decor.despan(input);
self.inner.despan(input);
}
}
impl PartialEq for Parenthesis {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Null;
impl fmt::Display for Null {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "null")
}
}
decorate_impl!(Parenthesis);
span_impl!(Parenthesis);
forward_decorate_impl!(Expression => {
Null, Bool, Number, String, Array, Object, StringTemplate, HeredocTemplate, Parenthesis,
Variable, ForExpr, Conditional, FuncCall, UnaryOp, BinaryOp, Traversal
});
forward_span_impl!(Expression => {
Null, Bool, Number, String, Array, Object, StringTemplate, HeredocTemplate, Parenthesis,
Variable, ForExpr, Conditional, FuncCall, UnaryOp, BinaryOp, Traversal
});