tenda_parser/
ast.rs

1use tenda_common::span::SourceSpan;
2use tenda_scanner::{Token, TokenKind};
3
4#[derive(Debug, PartialEq, Clone)]
5pub struct Ast {
6    pub inner: Vec<Stmt>,
7    pub span: SourceSpan,
8}
9
10impl Ast {
11    pub fn new(span: SourceSpan) -> Self {
12        Ast {
13            inner: vec![],
14            span,
15        }
16    }
17
18    pub fn from(inner: Vec<Stmt>, span: SourceSpan) -> Self {
19        Ast { inner, span }
20    }
21}
22
23impl IntoIterator for Ast {
24    type Item = Stmt;
25    type IntoIter = std::vec::IntoIter<Stmt>;
26
27    fn into_iter(self) -> Self::IntoIter {
28        self.inner.into_iter()
29    }
30}
31
32#[derive(Debug, PartialEq, Clone)]
33pub enum Stmt {
34    Expr(Expr),
35    Decl(Decl),
36    Cond(Cond),
37    While(While),
38    ForEach(ForEach),
39    Block(Block),
40    Return(Return),
41    Break(Break),
42    Continue(Continue),
43}
44
45impl Stmt {
46    pub fn get_span(&self) -> &SourceSpan {
47        match self {
48            Stmt::Expr(expr) => expr.get_span(),
49            Stmt::Decl(decl) => match decl {
50                Decl::Local(local) => &local.span,
51                Decl::Function(function) => &function.span,
52            },
53            Stmt::Cond(cond) => &cond.span,
54            Stmt::While(while_stmt) => &while_stmt.span,
55            Stmt::ForEach(for_each) => &for_each.span,
56            Stmt::Block(block) => &block.span,
57            Stmt::Return(return_stmt) => &return_stmt.span,
58            Stmt::Break(break_stmt) => &break_stmt.span,
59            Stmt::Continue(continue_stmt) => &continue_stmt.span,
60        }
61    }
62}
63
64#[derive(Debug, PartialEq, Clone)]
65pub struct Return {
66    pub value: Option<Expr>,
67    pub span: SourceSpan,
68}
69
70impl Return {
71    pub fn new(value: Option<Expr>, span: SourceSpan) -> Self {
72        Return { value, span }
73    }
74}
75
76#[derive(Debug, PartialEq, Clone)]
77pub struct Break {
78    pub span: SourceSpan,
79}
80
81impl Break {
82    pub fn new(span: SourceSpan) -> Self {
83        Break { span }
84    }
85}
86
87#[derive(Debug, PartialEq, Clone)]
88pub struct Continue {
89    pub span: SourceSpan,
90}
91
92impl Continue {
93    pub fn new(span: SourceSpan) -> Self {
94        Continue { span }
95    }
96}
97
98#[derive(Debug, PartialEq, Clone)]
99pub struct Block {
100    pub inner: Ast,
101    pub span: SourceSpan,
102}
103
104impl Block {
105    pub fn new(inner: Ast, span: SourceSpan) -> Self {
106        Block { inner, span }
107    }
108}
109
110#[derive(Debug, PartialEq, Clone)]
111pub enum Decl {
112    Local(LocalDecl),
113    Function(FunctionDecl),
114}
115
116impl Decl {
117    pub fn get_name(&self) -> &str {
118        match self {
119            Decl::Local(local) => &local.name,
120            Decl::Function(function) => &function.name,
121        }
122    }
123
124    pub fn get_uid(&self) -> usize {
125        match self {
126            Decl::Local(local) => local.uid,
127            Decl::Function(function) => function.uid,
128        }
129    }
130}
131
132#[derive(Debug, PartialEq, Clone)]
133pub struct LocalDecl {
134    pub name: String,
135    pub value: Expr,
136    pub captured: bool,
137    pub uid: usize,
138    pub span: SourceSpan,
139}
140
141impl LocalDecl {
142    pub fn new(name: String, value: Expr, uid: usize, span: SourceSpan) -> Self {
143        LocalDecl {
144            name,
145            value,
146            captured: false,
147            uid,
148            span,
149        }
150    }
151}
152
153#[derive(Debug, PartialEq, Clone)]
154pub struct FunctionParam {
155    pub name: String,
156    pub uid: usize,
157    pub captured: bool,
158    pub span: SourceSpan,
159}
160
161impl FunctionParam {
162    pub fn new(name: String, uid: usize, span: SourceSpan) -> Self {
163        FunctionParam {
164            name,
165            uid,
166            captured: false,
167            span,
168        }
169    }
170}
171
172#[derive(Debug, PartialEq, Clone)]
173pub struct FunctionDecl {
174    pub name: String,
175    pub params: Vec<FunctionParam>,
176    pub body: Box<Stmt>,
177    pub free_vars: Vec<String>,
178    pub captured: bool,
179    pub uid: usize,
180    pub span: SourceSpan,
181}
182
183impl FunctionDecl {
184    pub fn new(
185        name: String,
186        params: Vec<FunctionParam>,
187        body: Stmt,
188        uid: usize,
189        span: SourceSpan,
190    ) -> Self {
191        FunctionDecl {
192            name,
193            params,
194            body: Box::new(body),
195            free_vars: vec![],
196            captured: false,
197            uid,
198            span,
199        }
200    }
201}
202
203#[derive(Debug, PartialEq, Clone)]
204pub struct Cond {
205    pub cond: Expr,
206    pub then: Box<Stmt>,
207    pub or_else: Option<Box<Stmt>>,
208    pub span: SourceSpan,
209}
210
211impl Cond {
212    pub fn new(cond: Expr, then: Stmt, or_else: Option<Stmt>, span: SourceSpan) -> Self {
213        Cond {
214            cond,
215            then: Box::new(then),
216            or_else: or_else.map(Box::new),
217            span,
218        }
219    }
220}
221
222#[derive(Debug, PartialEq, Clone)]
223pub struct While {
224    pub cond: Expr,
225    pub body: Box<Stmt>,
226    pub span: SourceSpan,
227}
228
229impl While {
230    pub fn new(cond: Expr, body: Stmt, span: SourceSpan) -> Self {
231        While {
232            cond,
233            body: Box::new(body),
234            span,
235        }
236    }
237}
238
239#[derive(Debug, PartialEq, Clone)]
240pub struct ForEachItem {
241    pub name: String,
242    pub uid: usize,
243    pub captured: bool,
244    pub span: SourceSpan,
245}
246
247impl ForEachItem {
248    pub fn new(name: String, uid: usize, span: SourceSpan) -> Self {
249        ForEachItem {
250            name,
251            uid,
252            captured: false,
253            span,
254        }
255    }
256}
257
258#[derive(Debug, PartialEq, Clone)]
259pub struct ForEach {
260    pub item: ForEachItem,
261    pub iterable: Expr,
262    pub body: Box<Stmt>,
263    pub span: SourceSpan,
264}
265
266impl ForEach {
267    pub fn new(item: ForEachItem, iterable: Expr, body: Stmt, span: SourceSpan) -> Self {
268        ForEach {
269            item,
270            iterable,
271            body: Box::new(body),
272            span,
273        }
274    }
275}
276
277#[derive(Debug, PartialEq, Clone)]
278pub enum Expr {
279    Binary(BinaryOp),
280    Unary(UnaryOp),
281    Ternary(TernaryOp),
282    Call(Call),
283    Assign(Assign),
284    Access(Access),
285    List(List),
286    Grouping(Grouping),
287    Literal(Literal),
288    Variable(Variable),
289    AssociativeArray(AssociativeArray),
290    AnonymousFunction(AnonymousFunction),
291}
292
293impl Expr {
294    pub fn get_span(&self) -> &SourceSpan {
295        match self {
296            Expr::Binary(binary_op) => &binary_op.span,
297            Expr::Unary(unary_op) => &unary_op.span,
298            Expr::Ternary(ternary_op) => &ternary_op.span,
299            Expr::Call(call) => &call.span,
300            Expr::Assign(assign) => &assign.span,
301            Expr::Access(access) => &access.span,
302            Expr::List(list) => &list.span,
303            Expr::Grouping(grouping) => &grouping.span,
304            Expr::Literal(literal) => &literal.span,
305            Expr::Variable(variable) => &variable.span,
306            Expr::AssociativeArray(associative_array) => &associative_array.span,
307            Expr::AnonymousFunction(anonymous_function) => &anonymous_function.span,
308        }
309    }
310}
311
312#[derive(Debug, PartialEq, Clone)]
313pub struct BinaryOp {
314    pub lhs: Box<Expr>,
315    pub op: BinaryOperator,
316    pub rhs: Box<Expr>,
317    pub span: SourceSpan,
318}
319
320impl BinaryOp {
321    pub fn new(lhs: Expr, op: BinaryOperator, rhs: Expr, span: SourceSpan) -> Self {
322        BinaryOp {
323            lhs: Box::new(lhs),
324            op,
325            rhs: Box::new(rhs),
326            span,
327        }
328    }
329}
330
331#[derive(Debug, PartialEq, Clone)]
332pub struct UnaryOp {
333    pub op: UnaryOperator,
334    pub rhs: Box<Expr>,
335    pub span: SourceSpan,
336}
337
338impl UnaryOp {
339    pub fn new(op: UnaryOperator, rhs: Expr, span: SourceSpan) -> Self {
340        UnaryOp {
341            op,
342            rhs: Box::new(rhs),
343            span,
344        }
345    }
346}
347
348#[derive(Debug, PartialEq, Clone)]
349pub struct TernaryOp {
350    pub cond: Box<Expr>,
351    pub then: Box<Expr>,
352    pub or_else: Box<Expr>,
353    pub span: SourceSpan,
354}
355
356impl TernaryOp {
357    pub fn new(cond: Expr, then: Expr, or_else: Expr, span: SourceSpan) -> Self {
358        TernaryOp {
359            cond: Box::new(cond),
360            then: Box::new(then),
361            or_else: Box::new(or_else),
362            span,
363        }
364    }
365}
366
367#[derive(Debug, PartialEq, Clone)]
368pub struct Call {
369    pub callee: Box<Expr>,
370    pub args: Vec<Expr>,
371    pub span: SourceSpan,
372}
373
374impl Call {
375    pub fn new(callee: Expr, args: Vec<Expr>, span: SourceSpan) -> Self {
376        Call {
377            callee: Box::new(callee),
378            args,
379            span,
380        }
381    }
382}
383
384#[derive(Debug, PartialEq, Clone)]
385pub struct Assign {
386    pub name: Box<Expr>,
387    pub value: Box<Expr>,
388    pub span: SourceSpan,
389}
390
391impl Assign {
392    pub fn new(name: Expr, value: Expr, span: SourceSpan) -> Self {
393        Assign {
394            name: Box::new(name),
395            value: Box::new(value),
396            span,
397        }
398    }
399}
400
401#[derive(Debug, PartialEq, Clone)]
402pub struct Access {
403    pub subscripted: Box<Expr>,
404    pub index: Box<Expr>,
405    pub span: SourceSpan,
406}
407
408impl Access {
409    pub fn new(subscripted: Expr, index: Expr, span: SourceSpan) -> Self {
410        Access {
411            subscripted: Box::new(subscripted),
412            index: Box::new(index),
413            span,
414        }
415    }
416}
417
418#[derive(Debug, PartialEq, Clone)]
419pub struct List {
420    pub elements: Vec<Expr>,
421    pub span: SourceSpan,
422}
423
424impl List {
425    pub fn new(elements: Vec<Expr>, span: SourceSpan) -> Self {
426        List { elements, span }
427    }
428}
429
430#[derive(Debug, PartialEq, Clone)]
431pub struct AssociativeArray {
432    pub elements: Vec<(Literal, Expr)>,
433    pub span: SourceSpan,
434}
435
436impl AssociativeArray {
437    pub fn new(elements: Vec<(Literal, Expr)>, span: SourceSpan) -> Self {
438        AssociativeArray { elements, span }
439    }
440}
441
442#[derive(Debug, PartialEq, Clone)]
443pub struct Grouping {
444    pub expr: Box<Expr>,
445    pub span: SourceSpan,
446}
447
448impl Grouping {
449    pub fn new(expr: Expr, span: SourceSpan) -> Self {
450        Grouping {
451            expr: Box::new(expr),
452            span,
453        }
454    }
455}
456
457#[derive(Debug, PartialEq, Clone)]
458pub struct Literal {
459    pub value: tenda_scanner::Literal,
460    pub span: SourceSpan,
461}
462
463impl Literal {
464    pub fn new(value: tenda_scanner::Literal, span: SourceSpan) -> Self {
465        Literal { value, span }
466    }
467}
468
469#[derive(Debug, PartialEq, Clone)]
470pub struct Variable {
471    pub name: String,
472    pub uid: usize,
473    pub captured: bool,
474    pub span: SourceSpan,
475}
476
477impl Variable {
478    pub fn new(name: String, id: usize, span: SourceSpan) -> Self {
479        Variable {
480            name,
481            uid: id,
482            captured: false,
483            span,
484        }
485    }
486}
487
488#[derive(Debug, PartialEq, Clone)]
489pub struct AnonymousFunction {
490    pub params: Vec<FunctionParam>,
491    pub body: Box<Stmt>,
492    pub uid: usize,
493    pub free_vars: Vec<String>,
494    pub span: SourceSpan,
495}
496
497impl AnonymousFunction {
498    pub fn new(params: Vec<FunctionParam>, body: Stmt, uid: usize, span: SourceSpan) -> Self {
499        AnonymousFunction {
500            params,
501            body: Box::new(body),
502            uid,
503            free_vars: vec![],
504            span,
505        }
506    }
507}
508
509#[derive(Debug, Copy, Clone, PartialEq)]
510pub enum BinaryOperator {
511    Add,
512    Subtract,
513    Multiply,
514    Divide,
515    Exponentiation,
516    Modulo,
517    Equality,
518    Inequality,
519    Greater,
520    GreaterOrEqual,
521    Less,
522    LessOrEqual,
523    LogicalAnd,
524    LogicalOr,
525    Range,
526    Has,
527    Lacks,
528}
529
530impl From<Token> for BinaryOperator {
531    fn from(value: Token) -> Self {
532        use BinaryOperator::*;
533
534        match value.kind {
535            TokenKind::Plus => Add,
536            TokenKind::Minus => Subtract,
537            TokenKind::Star => Multiply,
538            TokenKind::Slash => Divide,
539            TokenKind::Percent => Modulo,
540            TokenKind::Caret => Exponentiation,
541            TokenKind::Equals => Equality,
542            TokenKind::Greater => Greater,
543            TokenKind::GreaterOrEqual => GreaterOrEqual,
544            TokenKind::Less => Less,
545            TokenKind::LessOrEqual => LessOrEqual,
546            TokenKind::Or => LogicalOr,
547            TokenKind::And => LogicalAnd,
548            TokenKind::Until => Range,
549            _ => panic!("invalid token for binary operation"),
550        }
551    }
552}
553
554#[derive(Debug, Copy, Clone, PartialEq)]
555pub enum UnaryOperator {
556    Negative,
557    LogicalNot,
558}
559
560impl From<Token> for UnaryOperator {
561    fn from(value: Token) -> Self {
562        use UnaryOperator::*;
563
564        match value.kind {
565            TokenKind::Minus => Negative,
566            TokenKind::Not => LogicalNot,
567            _ => panic!("invalid token for unary operation"),
568        }
569    }
570}