expr_solver/
ast.rs

1//! Abstract Syntax Tree for mathematical expressions.
2
3use crate::number::Number;
4use crate::span::Span;
5use crate::token::Token;
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 From<Token<'_>> for UnOp {
17    fn from(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 From<Token<'_>> for BinOp {
54    fn from(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<'src> {
75    pub kind: ExprKind<'src>,
76    pub span: Span,
77}
78
79/// Expression kind representing different types of expressions.
80#[derive(Debug, Clone)]
81pub enum ExprKind<'src> {
82    /// Numeric literal
83    Literal(Number),
84    /// Identifier (constant or variable)
85    Ident { name: &'src str },
86    /// Unary operation
87    Unary { op: UnOp, expr: Box<Expr<'src>> },
88    /// Binary operation
89    Binary {
90        op: BinOp,
91        left: Box<Expr<'src>>,
92        right: Box<Expr<'src>>,
93    },
94    /// Function call
95    Call {
96        name: &'src str,
97        args: Vec<Expr<'src>>,
98    },
99    /// Conditional expression
100    If {
101        cond: Box<Expr<'src>>,
102        then_branch: Box<Expr<'src>>,
103        else_branch: Box<Expr<'src>>,
104    },
105    /// Let expression with local constant declarations
106    Let {
107        decls: Vec<(&'src str, Expr<'src>)>,
108        body: Box<Expr<'src>>,
109    },
110}
111
112impl<'src> Expr<'src> {
113    pub fn literal(value: Number, span: Span) -> Self {
114        Self {
115            kind: ExprKind::Literal(value),
116            span,
117        }
118    }
119
120    pub fn ident(name: &'src str, span: Span) -> Self {
121        Self {
122            kind: ExprKind::Ident { name },
123            span,
124        }
125    }
126
127    pub fn unary(op: UnOp, expr: Expr<'src>, span: Span) -> Self {
128        Self {
129            kind: ExprKind::Unary {
130                op,
131                expr: Box::new(expr),
132            },
133            span,
134        }
135    }
136
137    pub fn binary(op: BinOp, left: Expr<'src>, right: Expr<'src>, span: Span) -> Self {
138        Self {
139            kind: ExprKind::Binary {
140                op,
141                left: Box::new(left),
142                right: Box::new(right),
143            },
144            span,
145        }
146    }
147
148    pub fn call(name: &'src str, args: Vec<Expr<'src>>, span: Span) -> Self {
149        Self {
150            kind: ExprKind::Call { name, args },
151            span,
152        }
153    }
154
155    pub fn if_expr(
156        cond: Expr<'src>,
157        then_branch: Expr<'src>,
158        else_branch: Expr<'src>,
159        span: Span,
160    ) -> Self {
161        Self {
162            kind: ExprKind::If {
163                cond: Box::new(cond),
164                then_branch: Box::new(then_branch),
165                else_branch: Box::new(else_branch),
166            },
167            span,
168        }
169    }
170
171    pub fn let_expr(decls: Vec<(&'src str, Expr<'src>)>, body: Expr<'src>, span: Span) -> Self {
172        Self {
173            kind: ExprKind::Let {
174                decls,
175                body: Box::new(body),
176            },
177            span,
178        }
179    }
180}