expr_solver/
ast.rs

1//! Abstract Syntax Tree for mathematical expressions.
2
3use crate::span::Span;
4use crate::token::Token;
5use rust_decimal::Decimal;
6
7/// Unary operators: negation and factorial.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum UnOp {
10    /// Negation (`-`)
11    Neg,
12    /// Factorial (`!`)
13    Fact,
14}
15
16impl UnOp {
17    pub fn from_token(token: &Token) -> Self {
18        match token {
19            Token::Minus => UnOp::Neg,
20            Token::Bang => UnOp::Fact,
21            _ => unreachable!("Invalid token for unary operator"),
22        }
23    }
24}
25
26/// Binary operators: arithmetic and comparison.
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum BinOp {
29    /// Addition (`+`)
30    Add,
31    /// Subtraction (`-`)
32    Sub,
33    /// Multiplication (`*`)
34    Mul,
35    /// Division (`/`)
36    Div,
37    /// Exponentiation (`^`)
38    Pow,
39    /// Equality (`==`)
40    Equal,
41    /// Inequality (`!=`)
42    NotEqual,
43    /// Less than (`<`)
44    Less,
45    /// Less than or equal (`<=`)
46    LessEqual,
47    /// Greater than (`>`)
48    Greater,
49    /// Greater than or equal (`>=`)
50    GreaterEqual,
51}
52
53impl BinOp {
54    pub fn from_token(token: &Token) -> Self {
55        match token {
56            Token::Plus => BinOp::Add,
57            Token::Minus => BinOp::Sub,
58            Token::Star => BinOp::Mul,
59            Token::Slash => BinOp::Div,
60            Token::Caret => BinOp::Pow,
61            Token::Equal => BinOp::Equal,
62            Token::NotEqual => BinOp::NotEqual,
63            Token::Less => BinOp::Less,
64            Token::LessEqual => BinOp::LessEqual,
65            Token::Greater => BinOp::Greater,
66            Token::GreaterEqual => BinOp::GreaterEqual,
67            _ => unreachable!("Invalid token for binary operator"),
68        }
69    }
70}
71
72/// Expression node in the AST with source location.
73#[derive(Debug, Clone)]
74pub struct Expr {
75    pub kind: ExprKind,
76    pub span: Span,
77}
78
79/// Expression kind representing different types of expressions.
80#[derive(Debug, Clone)]
81pub enum ExprKind {
82    /// Numeric literal
83    Literal(Decimal),
84    /// Identifier (constant or variable)
85    Ident { name: String },
86    /// Unary operation
87    Unary { op: UnOp, expr: Box<Expr> },
88    /// Binary operation
89    Binary {
90        op: BinOp,
91        left: Box<Expr>,
92        right: Box<Expr>,
93    },
94    /// Function call
95    Call { name: String, args: Vec<Expr> },
96}
97
98impl Expr {
99    pub fn literal(value: Decimal, span: Span) -> Self {
100        Self {
101            kind: ExprKind::Literal(value),
102            span,
103        }
104    }
105
106    pub fn ident(name: String, span: Span) -> Self {
107        Self {
108            kind: ExprKind::Ident { name },
109            span,
110        }
111    }
112
113    pub fn unary(op: UnOp, expr: Expr, span: Span) -> Self {
114        Self {
115            kind: ExprKind::Unary {
116                op,
117                expr: Box::new(expr),
118            },
119            span,
120        }
121    }
122
123    pub fn binary(op: BinOp, left: Expr, right: Expr, span: Span) -> Self {
124        Self {
125            kind: ExprKind::Binary {
126                op,
127                left: Box::new(left),
128                right: Box::new(right),
129            },
130            span,
131        }
132    }
133
134    pub fn call(name: String, args: Vec<Expr>, span: Span) -> Self {
135        Self {
136            kind: ExprKind::Call { name, args },
137            span,
138        }
139    }
140}