113 lines
2.5 KiB
Rust
113 lines
2.5 KiB
Rust
//! # Expression AST
|
|
//!
|
|
//! Defines the abstract syntax tree nodes produced by the parser and consumed
|
|
//! by the evaluator.
|
|
|
|
use std::fmt;
|
|
|
|
/// A binary operator connecting two sub-expressions.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum BinaryOp {
|
|
// Arithmetic
|
|
Add,
|
|
Sub,
|
|
Mul,
|
|
Div,
|
|
Mod,
|
|
// Comparison
|
|
Eq,
|
|
Ne,
|
|
Lt,
|
|
Gt,
|
|
Le,
|
|
Ge,
|
|
// Logical
|
|
And,
|
|
Or,
|
|
// Membership
|
|
In,
|
|
}
|
|
|
|
impl fmt::Display for BinaryOp {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
BinaryOp::Add => write!(f, "+"),
|
|
BinaryOp::Sub => write!(f, "-"),
|
|
BinaryOp::Mul => write!(f, "*"),
|
|
BinaryOp::Div => write!(f, "/"),
|
|
BinaryOp::Mod => write!(f, "%"),
|
|
BinaryOp::Eq => write!(f, "=="),
|
|
BinaryOp::Ne => write!(f, "!="),
|
|
BinaryOp::Lt => write!(f, "<"),
|
|
BinaryOp::Gt => write!(f, ">"),
|
|
BinaryOp::Le => write!(f, "<="),
|
|
BinaryOp::Ge => write!(f, ">="),
|
|
BinaryOp::And => write!(f, "and"),
|
|
BinaryOp::Or => write!(f, "or"),
|
|
BinaryOp::In => write!(f, "in"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A unary operator applied to a single sub-expression.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum UnaryOp {
|
|
/// Arithmetic negation: `-x`
|
|
Neg,
|
|
/// Logical negation: `not x`
|
|
Not,
|
|
}
|
|
|
|
impl fmt::Display for UnaryOp {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
UnaryOp::Neg => write!(f, "-"),
|
|
UnaryOp::Not => write!(f, "not"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An expression AST node.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum Expr {
|
|
/// A literal JSON value: number, string, bool, or null.
|
|
Literal(serde_json::Value),
|
|
|
|
/// An array literal: `[expr, expr, ...]`
|
|
Array(Vec<Expr>),
|
|
|
|
/// A variable reference by name (e.g., `x`, `parameters`, `item`).
|
|
Ident(String),
|
|
|
|
/// Binary operation: `left op right`
|
|
BinaryOp {
|
|
op: BinaryOp,
|
|
left: Box<Expr>,
|
|
right: Box<Expr>,
|
|
},
|
|
|
|
/// Unary operation: `op operand`
|
|
UnaryOp {
|
|
op: UnaryOp,
|
|
operand: Box<Expr>,
|
|
},
|
|
|
|
/// Property access: `expr.field`
|
|
DotAccess {
|
|
object: Box<Expr>,
|
|
field: String,
|
|
},
|
|
|
|
/// Index/bracket access: `expr[index_expr]`
|
|
IndexAccess {
|
|
object: Box<Expr>,
|
|
index: Box<Expr>,
|
|
},
|
|
|
|
/// Function call: `name(arg1, arg2, ...)`
|
|
FunctionCall {
|
|
name: String,
|
|
args: Vec<Expr>,
|
|
},
|
|
}
|