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    StructLiteral(Vec<(String, Expr)>, Span),
16    ObjectLiteral(String, Vec<(String, Expr)>, Span),
17    Index(Box<Expr>, Vec<Expr>, Span),
18    IndexCell(Box<Expr>, Vec<Expr>, Span),
19    Range(Box<Expr>, Option<Box<Expr>>, Box<Expr>, Span),
20    Colon(Span),
21    FuncCall(String, Vec<Expr>, Span),
22    SuperConstructorCall {
23        current_class: String,
24        super_class: String,
25        args: Vec<Expr>,
26        span: Span,
27    },
28    SuperMethodCall {
29        current_class: String,
30        super_class: String,
31        method: String,
32        args: Vec<Expr>,
33        span: Span,
34    },
35    CommandCall(String, Vec<Expr>, Span),
36    Member(Box<Expr>, String, Span),
37    // Dynamic field: s.(expr)
38    MemberDynamic(Box<Expr>, Box<Expr>, Span),
39    DottedInvoke(Box<Expr>, String, Vec<Expr>, Span),
40    MethodCall(Box<Expr>, String, Vec<Expr>, Span),
41    AnonFunc {
42        params: Vec<String>,
43        body: Box<Expr>,
44        span: Span,
45    },
46    FuncHandle(String, Span),
47    MetaClass(String, Span),
48}
49
50impl Expr {
51    pub fn span(&self) -> Span {
52        match self {
53            Expr::Number(_, span)
54            | Expr::String(_, span)
55            | Expr::Ident(_, span)
56            | Expr::EndKeyword(span)
57            | Expr::Unary(_, _, span)
58            | Expr::Binary(_, _, _, span)
59            | Expr::Tensor(_, span)
60            | Expr::Cell(_, span)
61            | Expr::StructLiteral(_, span)
62            | Expr::ObjectLiteral(_, _, span)
63            | Expr::Index(_, _, span)
64            | Expr::IndexCell(_, _, span)
65            | Expr::Range(_, _, _, span)
66            | Expr::Colon(span)
67            | Expr::FuncCall(_, _, span)
68            | Expr::SuperConstructorCall { span, .. }
69            | Expr::SuperMethodCall { span, .. }
70            | Expr::CommandCall(_, _, span)
71            | Expr::Member(_, _, span)
72            | Expr::MemberDynamic(_, _, span)
73            | Expr::DottedInvoke(_, _, _, span)
74            | Expr::MethodCall(_, _, _, span)
75            | Expr::FuncHandle(_, span)
76            | Expr::MetaClass(_, span) => *span,
77            Expr::AnonFunc { span, .. } => *span,
78        }
79    }
80
81    pub fn with_span(self, span: Span) -> Expr {
82        match self {
83            Expr::Number(value, _) => Expr::Number(value, span),
84            Expr::String(value, _) => Expr::String(value, span),
85            Expr::Ident(value, _) => Expr::Ident(value, span),
86            Expr::EndKeyword(_) => Expr::EndKeyword(span),
87            Expr::Unary(op, expr, _) => Expr::Unary(op, expr, span),
88            Expr::Binary(lhs, op, rhs, _) => Expr::Binary(lhs, op, rhs, span),
89            Expr::Tensor(rows, _) => Expr::Tensor(rows, span),
90            Expr::Cell(rows, _) => Expr::Cell(rows, span),
91            Expr::StructLiteral(fields, _) => Expr::StructLiteral(fields, span),
92            Expr::ObjectLiteral(class_name, fields, _) => {
93                Expr::ObjectLiteral(class_name, fields, span)
94            }
95            Expr::Index(base, indices, _) => Expr::Index(base, indices, span),
96            Expr::IndexCell(base, indices, _) => Expr::IndexCell(base, indices, span),
97            Expr::Range(start, step, end, _) => Expr::Range(start, step, end, span),
98            Expr::Colon(_) => Expr::Colon(span),
99            Expr::FuncCall(name, args, _) => Expr::FuncCall(name, args, span),
100            Expr::SuperConstructorCall {
101                current_class,
102                super_class,
103                args,
104                ..
105            } => Expr::SuperConstructorCall {
106                current_class,
107                super_class,
108                args,
109                span,
110            },
111            Expr::SuperMethodCall {
112                current_class,
113                super_class,
114                method,
115                args,
116                ..
117            } => Expr::SuperMethodCall {
118                current_class,
119                super_class,
120                method,
121                args,
122                span,
123            },
124            Expr::CommandCall(name, args, _) => Expr::CommandCall(name, args, span),
125            Expr::Member(base, name, _) => Expr::Member(base, name, span),
126            Expr::MemberDynamic(base, name, _) => Expr::MemberDynamic(base, name, span),
127            Expr::DottedInvoke(base, name, args, _) => Expr::DottedInvoke(base, name, args, span),
128            Expr::MethodCall(base, name, args, _) => Expr::MethodCall(base, name, args, span),
129            Expr::AnonFunc { params, body, .. } => Expr::AnonFunc { params, body, span },
130            Expr::FuncHandle(name, _) => Expr::FuncHandle(name, span),
131            Expr::MetaClass(name, _) => Expr::MetaClass(name, span),
132        }
133    }
134}
135
136#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
137pub enum BinOp {
138    Add,
139    Sub,
140    Mul,
141    RightDiv,
142    Pow,
143    LeftDiv,
144    Colon,
145    // Element-wise operations
146    ElemMul,     // .*
147    ElemDiv,     // ./
148    ElemPow,     // .^
149    ElemLeftDiv, // .\
150    // Logical operations
151    AndAnd, // && (short-circuit)
152    OrOr,   // || (short-circuit)
153    BitAnd, // &
154    BitOr,  // |
155    // Comparison operations
156    Equal,        // ==
157    NotEqual,     // ~=
158    Less,         // <
159    LessEqual,    // <=
160    Greater,      // >
161    GreaterEqual, // >=
162}
163
164#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
165pub enum UnOp {
166    Plus,
167    Minus,
168    Transpose,
169    NonConjugateTranspose,
170    Not, // ~
171}
172
173#[derive(Debug, PartialEq)]
174pub enum Stmt {
175    ExprStmt(Expr, bool, Span), // Expression and whether it's semicolon-terminated (suppressed)
176    Assign(String, Expr, bool, Span), // Variable, Expression, and whether it's semicolon-terminated (suppressed)
177    MultiAssign(Vec<MultiAssignTarget>, Expr, bool, Span),
178    AssignLValue(LValue, Expr, bool, Span),
179    If {
180        cond: Expr,
181        then_body: Vec<Stmt>,
182        elseif_blocks: Vec<(Expr, Vec<Stmt>)>,
183        else_body: Option<Vec<Stmt>>,
184        span: Span,
185    },
186    While {
187        cond: Expr,
188        body: Vec<Stmt>,
189        span: Span,
190    },
191    For {
192        var: String,
193        expr: Expr,
194        body: Vec<Stmt>,
195        span: Span,
196    },
197    Switch {
198        expr: Expr,
199        cases: Vec<(Expr, Vec<Stmt>)>,
200        otherwise: Option<Vec<Stmt>>,
201        span: Span,
202    },
203    TryCatch {
204        try_body: Vec<Stmt>,
205        catch_var: Option<String>,
206        catch_body: Vec<Stmt>,
207        span: Span,
208    },
209    Global(Vec<String>, Span),
210    Persistent(Vec<String>, Span),
211    Break(Span),
212    Continue(Span),
213    Return(Span),
214    Function {
215        name: String,
216        params: Vec<String>,
217        outputs: Vec<String>,
218        argument_validations: Vec<FunctionArgValidationDecl>,
219        argument_block_kinds: Vec<FunctionArgumentsBlockKind>,
220        body: Vec<Stmt>,
221        isolated: bool,
222        is_async: bool,
223        span: Span,
224    },
225    Import {
226        path: Vec<String>,
227        wildcard: bool,
228        span: Span,
229    },
230    ClassDef {
231        attributes: Vec<Attr>,
232        name: String,
233        super_class: Option<String>,
234        members: Vec<ClassMember>,
235        span: Span,
236    },
237}
238
239#[derive(Debug, PartialEq, Clone)]
240pub enum MultiAssignTarget {
241    Discard,
242    LValue(LValue),
243}
244
245impl Stmt {
246    pub fn span(&self) -> Span {
247        match self {
248            Stmt::ExprStmt(_, _, span)
249            | Stmt::Assign(_, _, _, span)
250            | Stmt::MultiAssign(_, _, _, span)
251            | Stmt::AssignLValue(_, _, _, span)
252            | Stmt::Global(_, span)
253            | Stmt::Persistent(_, span)
254            | Stmt::Break(span)
255            | Stmt::Continue(span)
256            | Stmt::Return(span) => *span,
257            Stmt::If { span, .. }
258            | Stmt::While { span, .. }
259            | Stmt::For { span, .. }
260            | Stmt::Switch { span, .. }
261            | Stmt::TryCatch { span, .. }
262            | Stmt::Function { span, .. }
263            | Stmt::Import { span, .. }
264            | Stmt::ClassDef { span, .. } => *span,
265        }
266    }
267}
268
269#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
270pub enum LValue {
271    Var(String),
272    Member(Box<Expr>, String),
273    MemberDynamic(Box<Expr>, Box<Expr>),
274    Index(Box<Expr>, Vec<Expr>),
275    IndexCell(Box<Expr>, Vec<Expr>),
276}
277
278#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
279pub struct Attr {
280    pub name: String,
281    pub value: Option<String>,
282}
283
284#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
285pub struct ClassPropertyDecl {
286    pub name: String,
287    pub default: Option<Expr>,
288}
289
290#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
291pub enum FunctionArgDim {
292    Any,
293    Exact(usize),
294}
295
296#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
297pub struct FunctionArgSizeSpec {
298    pub rows: FunctionArgDim,
299    pub cols: FunctionArgDim,
300}
301
302#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
303pub struct FunctionArgValidationDecl {
304    pub name: String,
305    pub size: Option<FunctionArgSizeSpec>,
306    pub class_name: Option<String>,
307    pub validators: Vec<FunctionArgValidatorDecl>,
308    pub default_value: Option<Expr>,
309    pub has_unsupported_trailing: bool,
310}
311
312#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
313pub enum FunctionArgumentsBlockKind {
314    Input,
315    Repeating,
316    Output,
317    Unsupported(Vec<Attr>),
318}
319
320#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
321pub struct FunctionArgValidatorDecl {
322    pub name: String,
323    pub args: Vec<Expr>,
324}
325
326#[derive(Debug, PartialEq)]
327pub enum ClassMember {
328    Properties {
329        attributes: Vec<Attr>,
330        names: Vec<ClassPropertyDecl>,
331    },
332    Methods {
333        attributes: Vec<Attr>,
334        body: Vec<Stmt>,
335    },
336    Events {
337        attributes: Vec<Attr>,
338        names: Vec<String>,
339    },
340    Enumeration {
341        attributes: Vec<Attr>,
342        names: Vec<String>,
343    },
344    Arguments {
345        attributes: Vec<Attr>,
346        names: Vec<String>,
347    },
348}
349
350#[derive(Debug, PartialEq)]
351pub struct Program {
352    pub body: Vec<Stmt>,
353}