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