Skip to main content

runmat_parser/
ast.rs

1use serde::{Deserialize, Serialize};
2
3use crate::Span;
4
5#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
6pub enum Expr {
7    Number(String, Span),
8    String(String, Span),
9    Ident(String, Span),
10    EndKeyword(Span), // 'end' used in indexing contexts
11    Unary(UnOp, Box<Expr>, Span),
12    Binary(Box<Expr>, BinOp, Box<Expr>, Span),
13    Tensor(Vec<Vec<Expr>>, Span),
14    Cell(Vec<Vec<Expr>>, Span),
15    Index(Box<Expr>, Vec<Expr>, Span),
16    IndexCell(Box<Expr>, Vec<Expr>, Span),
17    Range(Box<Expr>, Option<Box<Expr>>, Box<Expr>, Span),
18    Colon(Span),
19    FuncCall(String, Vec<Expr>, Span),
20    Member(Box<Expr>, String, Span),
21    // Dynamic field: s.(expr)
22    MemberDynamic(Box<Expr>, Box<Expr>, Span),
23    DottedInvoke(Box<Expr>, String, Vec<Expr>, Span),
24    MethodCall(Box<Expr>, String, Vec<Expr>, Span),
25    AnonFunc {
26        params: Vec<String>,
27        body: Box<Expr>,
28        span: Span,
29    },
30    FuncHandle(String, Span),
31    MetaClass(String, Span),
32}
33
34impl Expr {
35    pub fn span(&self) -> Span {
36        match self {
37            Expr::Number(_, span)
38            | Expr::String(_, span)
39            | Expr::Ident(_, span)
40            | Expr::EndKeyword(span)
41            | Expr::Unary(_, _, span)
42            | Expr::Binary(_, _, _, span)
43            | Expr::Tensor(_, span)
44            | Expr::Cell(_, span)
45            | Expr::Index(_, _, span)
46            | Expr::IndexCell(_, _, span)
47            | Expr::Range(_, _, _, span)
48            | Expr::Colon(span)
49            | Expr::FuncCall(_, _, span)
50            | Expr::Member(_, _, span)
51            | Expr::MemberDynamic(_, _, span)
52            | Expr::DottedInvoke(_, _, _, span)
53            | Expr::MethodCall(_, _, _, span)
54            | Expr::FuncHandle(_, span)
55            | Expr::MetaClass(_, span) => *span,
56            Expr::AnonFunc { span, .. } => *span,
57        }
58    }
59
60    pub fn with_span(self, span: Span) -> Expr {
61        match self {
62            Expr::Number(value, _) => Expr::Number(value, span),
63            Expr::String(value, _) => Expr::String(value, span),
64            Expr::Ident(value, _) => Expr::Ident(value, span),
65            Expr::EndKeyword(_) => Expr::EndKeyword(span),
66            Expr::Unary(op, expr, _) => Expr::Unary(op, expr, span),
67            Expr::Binary(lhs, op, rhs, _) => Expr::Binary(lhs, op, rhs, span),
68            Expr::Tensor(rows, _) => Expr::Tensor(rows, span),
69            Expr::Cell(rows, _) => Expr::Cell(rows, span),
70            Expr::Index(base, indices, _) => Expr::Index(base, indices, span),
71            Expr::IndexCell(base, indices, _) => Expr::IndexCell(base, indices, span),
72            Expr::Range(start, step, end, _) => Expr::Range(start, step, end, span),
73            Expr::Colon(_) => Expr::Colon(span),
74            Expr::FuncCall(name, args, _) => Expr::FuncCall(name, args, span),
75            Expr::Member(base, name, _) => Expr::Member(base, name, span),
76            Expr::MemberDynamic(base, name, _) => Expr::MemberDynamic(base, name, span),
77            Expr::DottedInvoke(base, name, args, _) => Expr::DottedInvoke(base, name, args, span),
78            Expr::MethodCall(base, name, args, _) => Expr::MethodCall(base, name, args, span),
79            Expr::AnonFunc { params, body, .. } => Expr::AnonFunc { params, body, span },
80            Expr::FuncHandle(name, _) => Expr::FuncHandle(name, span),
81            Expr::MetaClass(name, _) => Expr::MetaClass(name, span),
82        }
83    }
84}
85
86#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
87pub enum BinOp {
88    Add,
89    Sub,
90    Mul,
91    RightDiv,
92    Pow,
93    LeftDiv,
94    Colon,
95    // Element-wise operations
96    ElemMul,     // .*
97    ElemDiv,     // ./
98    ElemPow,     // .^
99    ElemLeftDiv, // .\
100    // Logical operations
101    AndAnd, // && (short-circuit)
102    OrOr,   // || (short-circuit)
103    BitAnd, // &
104    BitOr,  // |
105    // Comparison operations
106    Equal,        // ==
107    NotEqual,     // ~=
108    Less,         // <
109    LessEqual,    // <=
110    Greater,      // >
111    GreaterEqual, // >=
112}
113
114#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
115pub enum UnOp {
116    Plus,
117    Minus,
118    Transpose,
119    NonConjugateTranspose,
120    Not, // ~
121}
122
123#[derive(Debug, PartialEq)]
124pub enum Stmt {
125    ExprStmt(Expr, bool, Span), // Expression and whether it's semicolon-terminated (suppressed)
126    Assign(String, Expr, bool, Span), // Variable, Expression, and whether it's semicolon-terminated (suppressed)
127    MultiAssign(Vec<String>, Expr, bool, Span),
128    AssignLValue(LValue, Expr, bool, Span),
129    If {
130        cond: Expr,
131        then_body: Vec<Stmt>,
132        elseif_blocks: Vec<(Expr, Vec<Stmt>)>,
133        else_body: Option<Vec<Stmt>>,
134        span: Span,
135    },
136    While {
137        cond: Expr,
138        body: Vec<Stmt>,
139        span: Span,
140    },
141    For {
142        var: String,
143        expr: Expr,
144        body: Vec<Stmt>,
145        span: Span,
146    },
147    Switch {
148        expr: Expr,
149        cases: Vec<(Expr, Vec<Stmt>)>,
150        otherwise: Option<Vec<Stmt>>,
151        span: Span,
152    },
153    TryCatch {
154        try_body: Vec<Stmt>,
155        catch_var: Option<String>,
156        catch_body: Vec<Stmt>,
157        span: Span,
158    },
159    Global(Vec<String>, Span),
160    Persistent(Vec<String>, Span),
161    Break(Span),
162    Continue(Span),
163    Return(Span),
164    Function {
165        name: String,
166        params: Vec<String>,
167        outputs: Vec<String>,
168        body: Vec<Stmt>,
169        span: Span,
170    },
171    Import {
172        path: Vec<String>,
173        wildcard: bool,
174        span: Span,
175    },
176    ClassDef {
177        name: String,
178        super_class: Option<String>,
179        members: Vec<ClassMember>,
180        span: Span,
181    },
182}
183
184impl Stmt {
185    pub fn span(&self) -> Span {
186        match self {
187            Stmt::ExprStmt(_, _, span)
188            | Stmt::Assign(_, _, _, span)
189            | Stmt::MultiAssign(_, _, _, span)
190            | Stmt::AssignLValue(_, _, _, span)
191            | Stmt::Global(_, span)
192            | Stmt::Persistent(_, span)
193            | Stmt::Break(span)
194            | Stmt::Continue(span)
195            | Stmt::Return(span) => *span,
196            Stmt::If { span, .. }
197            | Stmt::While { span, .. }
198            | Stmt::For { span, .. }
199            | Stmt::Switch { span, .. }
200            | Stmt::TryCatch { span, .. }
201            | Stmt::Function { span, .. }
202            | Stmt::Import { span, .. }
203            | Stmt::ClassDef { span, .. } => *span,
204        }
205    }
206}
207
208#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
209pub enum LValue {
210    Var(String),
211    Member(Box<Expr>, String),
212    MemberDynamic(Box<Expr>, Box<Expr>),
213    Index(Box<Expr>, Vec<Expr>),
214    IndexCell(Box<Expr>, Vec<Expr>),
215}
216
217#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
218pub struct Attr {
219    pub name: String,
220    pub value: Option<String>,
221}
222
223#[derive(Debug, PartialEq)]
224pub enum ClassMember {
225    Properties {
226        attributes: Vec<Attr>,
227        names: Vec<String>,
228    },
229    Methods {
230        attributes: Vec<Attr>,
231        body: Vec<Stmt>,
232    },
233    Events {
234        attributes: Vec<Attr>,
235        names: Vec<String>,
236    },
237    Enumeration {
238        attributes: Vec<Attr>,
239        names: Vec<String>,
240    },
241    Arguments {
242        attributes: Vec<Attr>,
243        names: Vec<String>,
244    },
245}
246
247#[derive(Debug, PartialEq)]
248pub struct Program {
249    pub body: Vec<Stmt>,
250}