Skip to main content

somni_parser/
ast.rs

1use crate::{Location, lexer::Token, parser::TypeSet};
2
3#[derive(Debug)]
4pub struct Program<T>
5where
6    T: TypeSet,
7{
8    pub items: Vec<Item<T>>,
9}
10
11#[derive(Debug)]
12pub enum Item<T>
13where
14    T: TypeSet,
15{
16    Function(Function<T>),
17    ExternFunction(ExternalFunction),
18    GlobalVariable(GlobalVariable<T>),
19    Struct(StructDef),
20}
21
22/// A `struct Name { field: Type, ... }` definition.
23#[derive(Debug, Clone)]
24pub struct StructDef {
25    pub struct_token: Token,
26    pub name: Token,
27    pub opening_brace: Token,
28    pub fields: Vec<StructField>,
29    pub closing_brace: Token,
30}
31
32impl StructDef {
33    pub fn location(&self) -> Location {
34        Location {
35            start: self.struct_token.location.start,
36            end: self.closing_brace.location.end,
37        }
38    }
39}
40
41/// A single `field: Type` entry in a [`StructDef`].
42#[derive(Debug, Clone)]
43pub struct StructField {
44    pub name: Token,
45    pub colon: Token,
46    pub field_type: TypeHint,
47}
48
49#[derive(Debug)]
50pub struct GlobalVariable<T>
51where
52    T: TypeSet,
53{
54    pub decl_token: Token,
55    pub identifier: Token,
56    pub colon: Token,
57    pub type_token: TypeHint,
58    pub equals_token: Token,
59    pub initializer: Expression<T>,
60    pub semicolon: Token,
61}
62impl<T> GlobalVariable<T>
63where
64    T: TypeSet,
65{
66    pub fn location(&self) -> Location {
67        let start = self.decl_token.location.start;
68        let end = self.semicolon.location.end;
69        Location { start, end }
70    }
71}
72
73#[derive(Debug)]
74pub struct ReturnDecl {
75    pub return_token: Token,
76    pub return_type: TypeHint,
77}
78
79#[derive(Debug)]
80pub struct ExternalFunction {
81    pub extern_fn_token: Token,
82    pub fn_token: Token,
83    pub name: Token,
84    pub opening_paren: Token,
85    pub arguments: Vec<FunctionArgument>,
86    pub closing_paren: Token,
87    pub return_decl: Option<ReturnDecl>,
88    pub semicolon: Token,
89}
90
91#[derive(Debug)]
92pub struct Function<T>
93where
94    T: TypeSet,
95{
96    pub fn_token: Token,
97    pub name: Token,
98    pub opening_paren: Token,
99    pub arguments: Vec<FunctionArgument>,
100    pub closing_paren: Token,
101    pub return_decl: Option<ReturnDecl>,
102    pub body: Body<T>,
103}
104
105#[derive(Debug)]
106pub struct Body<T>
107where
108    T: TypeSet,
109{
110    pub opening_brace: Token,
111    pub statements: Vec<Statement<T>>,
112    pub closing_brace: Token,
113}
114impl<T: TypeSet> Body<T> {
115    pub fn location(&self) -> Location {
116        Location {
117            start: self.opening_brace.location.start,
118            end: self.closing_brace.location.end,
119        }
120    }
121}
122
123impl<T> Clone for Body<T>
124where
125    T: TypeSet,
126{
127    fn clone(&self) -> Self {
128        Self {
129            opening_brace: self.opening_brace,
130            statements: self.statements.clone(),
131            closing_brace: self.closing_brace,
132        }
133    }
134}
135
136#[derive(Debug)]
137pub struct FunctionArgument {
138    pub name: Token,
139    pub colon: Token,
140    pub reference_token: Option<Token>,
141    pub arg_type: TypeHint,
142}
143
144#[derive(Clone, Copy, Debug)]
145pub struct TypeHint {
146    pub type_name: Token,
147}
148
149#[derive(Debug)]
150pub struct VariableDefinition<T>
151where
152    T: TypeSet,
153{
154    pub decl_token: Token,
155    pub identifier: Token,
156    pub type_token: Option<TypeHint>,
157    pub equals_token: Token,
158    pub initializer: RightHandExpression<T>,
159    pub semicolon: Token,
160}
161
162impl<T> Clone for VariableDefinition<T>
163where
164    T: TypeSet,
165{
166    fn clone(&self) -> Self {
167        Self {
168            decl_token: self.decl_token,
169            identifier: self.identifier,
170            type_token: self.type_token,
171            equals_token: self.equals_token,
172            initializer: self.initializer.clone(),
173            semicolon: self.semicolon,
174        }
175    }
176}
177
178impl<T> VariableDefinition<T>
179where
180    T: TypeSet,
181{
182    pub fn location(&self) -> Location {
183        let start = self.decl_token.location.start;
184        let end = self.semicolon.location.end;
185        Location { start, end }
186    }
187}
188
189#[derive(Debug)]
190pub struct ReturnWithValue<T>
191where
192    T: TypeSet,
193{
194    pub return_token: Token,
195    pub expression: RightHandExpression<T>,
196    pub semicolon: Token,
197}
198
199impl<T> Clone for ReturnWithValue<T>
200where
201    T: TypeSet,
202{
203    fn clone(&self) -> Self {
204        Self {
205            return_token: self.return_token,
206            expression: self.expression.clone(),
207            semicolon: self.semicolon,
208        }
209    }
210}
211
212impl<T> ReturnWithValue<T>
213where
214    T: TypeSet,
215{
216    pub fn location(&self) -> Location {
217        let start = self.return_token.location.start;
218        let end = self.semicolon.location.end;
219        Location { start, end }
220    }
221}
222
223#[derive(Debug, Clone)]
224pub struct EmptyReturn {
225    pub return_token: Token,
226    pub semicolon: Token,
227}
228
229impl EmptyReturn {
230    pub fn location(&self) -> Location {
231        let start = self.return_token.location.start;
232        let end = self.semicolon.location.end;
233        Location { start, end }
234    }
235}
236
237#[derive(Debug)]
238pub struct If<T>
239where
240    T: TypeSet,
241{
242    pub if_token: Token,
243    pub condition: RightHandExpression<T>,
244    pub body: Body<T>,
245    pub else_branch: Option<Else<T>>,
246}
247impl<T> If<T>
248where
249    T: TypeSet,
250{
251    pub fn location(&self) -> Location {
252        Location {
253            start: self.if_token.location.start,
254            end: self
255                .else_branch
256                .as_ref()
257                .map(|else_branch| else_branch.location().end)
258                .unwrap_or_else(|| self.body.location().end),
259        }
260    }
261}
262
263impl<T> Clone for If<T>
264where
265    T: TypeSet,
266{
267    fn clone(&self) -> Self {
268        Self {
269            if_token: self.if_token,
270            condition: self.condition.clone(),
271            body: self.body.clone(),
272            else_branch: self.else_branch.clone(),
273        }
274    }
275}
276
277#[derive(Debug)]
278pub struct Loop<T>
279where
280    T: TypeSet,
281{
282    pub loop_token: Token,
283    pub body: Body<T>,
284}
285impl<T> Loop<T>
286where
287    T: TypeSet,
288{
289    pub fn location(&self) -> Location {
290        Location {
291            start: self.loop_token.location.start,
292            end: self.body.location().end,
293        }
294    }
295}
296
297impl<T> Clone for Loop<T>
298where
299    T: TypeSet,
300{
301    fn clone(&self) -> Self {
302        Self {
303            loop_token: self.loop_token,
304            body: self.body.clone(),
305        }
306    }
307}
308
309#[derive(Debug)]
310pub struct For<T>
311where
312    T: TypeSet,
313{
314    pub for_token: Token,
315    pub variable: Token,
316    pub var_type: Option<TypeHint>,
317    pub in_token: Token,
318    pub iterable: RightHandExpression<T>,
319    pub body: Body<T>,
320}
321impl<T> For<T>
322where
323    T: TypeSet,
324{
325    pub fn location(&self) -> Location {
326        Location {
327            start: self.for_token.location.start,
328            end: self.body.location().end,
329        }
330    }
331}
332
333impl<T> Clone for For<T>
334where
335    T: TypeSet,
336{
337    fn clone(&self) -> Self {
338        Self {
339            for_token: self.for_token,
340            variable: self.variable,
341            var_type: self.var_type,
342            in_token: self.in_token,
343            iterable: self.iterable.clone(),
344            body: self.body.clone(),
345        }
346    }
347}
348
349#[derive(Debug, Clone)]
350pub struct Break {
351    pub break_token: Token,
352    pub semicolon: Token,
353}
354
355impl Break {
356    pub fn location(&self) -> Location {
357        let start = self.break_token.location.start;
358        let end = self.semicolon.location.end;
359        Location { start, end }
360    }
361}
362
363#[derive(Debug, Clone)]
364pub struct Continue {
365    pub continue_token: Token,
366    pub semicolon: Token,
367}
368
369impl Continue {
370    pub fn location(&self) -> Location {
371        let start = self.continue_token.location.start;
372        let end = self.semicolon.location.end;
373        Location { start, end }
374    }
375}
376
377#[derive(Debug)]
378pub enum Statement<T>
379where
380    T: TypeSet,
381{
382    VariableDefinition(VariableDefinition<T>),
383    Return(ReturnWithValue<T>),
384    EmptyReturn(EmptyReturn),
385    If(If<T>),
386    Loop(Loop<T>),
387    For(For<T>),
388    Break(Break),
389    Continue(Continue),
390    Scope(Body<T>),
391    Expression {
392        expression: Expression<T>,
393        semicolon: Token,
394    },
395    ImplicitReturn(RightHandExpression<T>),
396}
397impl<T: TypeSet> Statement<T> {
398    pub fn location(&self) -> Location {
399        match self {
400            Statement::VariableDefinition(variable_definition) => variable_definition.location(),
401            Statement::Return(return_with_value) => return_with_value.location(),
402            Statement::EmptyReturn(empty_return) => empty_return.location(),
403            Statement::If(if_stmt) => if_stmt.location(),
404            Statement::Loop(loop_stmt) => loop_stmt.location(),
405            Statement::For(for_stmt) => for_stmt.location(),
406            Statement::Break(break_stmt) => break_stmt.location(),
407            Statement::Continue(continue_stmt) => continue_stmt.location(),
408            Statement::Scope(body) => body.location(),
409            Statement::Expression {
410                expression,
411                semicolon,
412            } => Location {
413                start: expression.location().start,
414                end: semicolon.location.end,
415            },
416            Statement::ImplicitReturn(right_hand_expression) => right_hand_expression.location(),
417        }
418    }
419}
420
421impl<T> Clone for Statement<T>
422where
423    T: TypeSet,
424{
425    fn clone(&self) -> Self {
426        match self {
427            Self::VariableDefinition(arg0) => Self::VariableDefinition(arg0.clone()),
428            Self::Return(arg0) => Self::Return(arg0.clone()),
429            Self::EmptyReturn(arg0) => Self::EmptyReturn(arg0.clone()),
430            Self::If(arg0) => Self::If(arg0.clone()),
431            Self::Loop(arg0) => Self::Loop(arg0.clone()),
432            Self::For(arg0) => Self::For(arg0.clone()),
433            Self::Break(arg0) => Self::Break(arg0.clone()),
434            Self::Continue(arg0) => Self::Continue(arg0.clone()),
435            Self::Scope(body) => Self::Scope(body.clone()),
436            Self::Expression {
437                expression,
438                semicolon,
439            } => Self::Expression {
440                expression: expression.clone(),
441                semicolon: *semicolon,
442            },
443            Statement::ImplicitReturn(expression) => Self::ImplicitReturn(expression.clone()),
444        }
445    }
446}
447
448#[derive(Debug)]
449pub struct Else<T>
450where
451    T: TypeSet,
452{
453    pub else_token: Token,
454    pub else_body: Body<T>,
455}
456impl<T> Else<T>
457where
458    T: TypeSet,
459{
460    pub fn location(&self) -> Location {
461        Location {
462            start: self.else_token.location.start,
463            end: self.else_body.location().end,
464        }
465    }
466}
467
468impl<T> Clone for Else<T>
469where
470    T: TypeSet,
471{
472    fn clone(&self) -> Self {
473        Self {
474            else_token: self.else_token,
475            else_body: self.else_body.clone(),
476        }
477    }
478}
479
480#[derive(Debug)]
481pub enum Expression<T>
482where
483    T: TypeSet,
484{
485    Assignment {
486        left_expr: LeftHandExpression,
487        operator: Token,
488        right_expr: RightHandExpression<T>,
489    },
490    Expression {
491        expression: RightHandExpression<T>,
492    },
493}
494impl<T> Clone for Expression<T>
495where
496    T: TypeSet,
497{
498    fn clone(&self) -> Self {
499        match self {
500            Expression::Assignment {
501                left_expr,
502                operator,
503                right_expr,
504            } => Self::Assignment {
505                left_expr: left_expr.clone(),
506                operator: *operator,
507                right_expr: right_expr.clone(),
508            },
509            Expression::Expression { expression } => Self::Expression {
510                expression: expression.clone(),
511            },
512        }
513    }
514}
515impl<T> Expression<T>
516where
517    T: TypeSet,
518{
519    pub fn location(&self) -> Location {
520        match self {
521            Expression::Expression { expression } => expression.location(),
522            Expression::Assignment {
523                left_expr,
524                operator: _,
525                right_expr,
526            } => {
527                let mut location = left_expr.location();
528
529                location.start = location.start.min(right_expr.location().start);
530                location.end = location.end.max(right_expr.location().end);
531
532                location
533            }
534        }
535    }
536}
537
538#[derive(Debug, Clone)]
539pub enum LeftHandExpression {
540    Name {
541        variable: Token,
542    },
543    Deref {
544        operator: Token,
545        name: Token,
546    },
547    /// A field of a place: `base.field`. `base` may itself be a `Name` or another
548    /// `Field` (field paths), enabling nested writes like `foo.x.y = 1`.
549    Field {
550        base: Box<LeftHandExpression>,
551        dot: Token,
552        field: Token,
553    },
554}
555
556impl LeftHandExpression {
557    pub fn location(&self) -> Location {
558        match self {
559            LeftHandExpression::Name { variable } => variable.location,
560            LeftHandExpression::Deref { operator, name } => {
561                let mut location = operator.location;
562
563                location.start = location.start.min(name.location.start);
564                location.end = location.end.max(name.location.end);
565
566                location
567            }
568            LeftHandExpression::Field { base, field, .. } => {
569                let mut location = base.location();
570
571                location.start = location.start.min(field.location.start);
572                location.end = location.end.max(field.location.end);
573
574                location
575            }
576        }
577    }
578}
579
580#[derive(Debug)]
581pub enum RightHandExpression<T>
582where
583    T: TypeSet,
584{
585    Variable {
586        variable: Token,
587    },
588    Literal {
589        value: Literal<T>,
590    },
591    UnaryOperator {
592        name: Token,
593        operand: Box<Self>,
594    },
595    BinaryOperator {
596        name: Token,
597        operands: Box<[Self; 2]>,
598    },
599    FunctionCall {
600        name: Token,
601        arguments: Box<[Self]>,
602    },
603    /// Field access: `base.field` (postfix, chains left-associatively).
604    FieldAccess {
605        base: Box<Self>,
606        dot: Token,
607        field: Token,
608    },
609    /// A struct literal: `Name { field: expr, ... }`.
610    StructLiteral {
611        name: Token,
612        opening_brace: Token,
613        fields: Vec<StructLiteralField<T>>,
614        closing_brace: Token,
615    },
616}
617
618/// A single `field: expr` initializer in a struct literal.
619#[derive(Debug)]
620pub struct StructLiteralField<T>
621where
622    T: TypeSet,
623{
624    pub name: Token,
625    pub colon: Token,
626    pub value: RightHandExpression<T>,
627}
628
629impl<T> Clone for StructLiteralField<T>
630where
631    T: TypeSet,
632{
633    fn clone(&self) -> Self {
634        Self {
635            name: self.name,
636            colon: self.colon,
637            value: self.value.clone(),
638        }
639    }
640}
641
642impl<T> Clone for RightHandExpression<T>
643where
644    T: TypeSet,
645{
646    fn clone(&self) -> Self {
647        match self {
648            Self::Variable { variable } => Self::Variable {
649                variable: *variable,
650            },
651            Self::Literal { value } => Self::Literal {
652                value: value.clone(),
653            },
654            Self::UnaryOperator { name, operand } => Self::UnaryOperator {
655                name: *name,
656                operand: operand.clone(),
657            },
658            Self::BinaryOperator { name, operands } => Self::BinaryOperator {
659                name: *name,
660                operands: operands.clone(),
661            },
662            Self::FunctionCall { name, arguments } => Self::FunctionCall {
663                name: *name,
664                arguments: arguments.clone(),
665            },
666            Self::FieldAccess { base, dot, field } => Self::FieldAccess {
667                base: base.clone(),
668                dot: *dot,
669                field: *field,
670            },
671            Self::StructLiteral {
672                name,
673                opening_brace,
674                fields,
675                closing_brace,
676            } => Self::StructLiteral {
677                name: *name,
678                opening_brace: *opening_brace,
679                fields: fields.clone(),
680                closing_brace: *closing_brace,
681            },
682        }
683    }
684}
685impl<T> RightHandExpression<T>
686where
687    T: TypeSet,
688{
689    pub fn location(&self) -> Location {
690        match self {
691            RightHandExpression::Variable { variable } => variable.location,
692            RightHandExpression::Literal { value } => value.location,
693            RightHandExpression::FunctionCall { name, arguments } => {
694                let mut location = name.location;
695                for arg in arguments {
696                    location.start = location.start.min(arg.location().start);
697                    location.end = location.end.max(arg.location().end);
698                }
699                location
700            }
701            RightHandExpression::UnaryOperator { name, operand: rhs } => {
702                let mut location = name.location;
703
704                location.start = location.start.min(rhs.location().start);
705                location.end = location.end.max(rhs.location().end);
706
707                location
708            }
709            RightHandExpression::BinaryOperator {
710                name,
711                operands: arguments,
712            } => {
713                let mut location = name.location;
714                for arg in arguments.iter() {
715                    location.start = location.start.min(arg.location().start);
716                    location.end = location.end.max(arg.location().end);
717                }
718                location
719            }
720            RightHandExpression::FieldAccess { base, field, .. } => {
721                let mut location = base.location();
722                location.start = location.start.min(field.location.start);
723                location.end = location.end.max(field.location.end);
724                location
725            }
726            RightHandExpression::StructLiteral {
727                name,
728                closing_brace,
729                ..
730            } => Location {
731                start: name.location.start,
732                end: closing_brace.location.end,
733            },
734        }
735    }
736}
737
738#[derive(Debug)]
739pub struct Literal<T>
740where
741    T: TypeSet,
742{
743    pub value: LiteralValue<T>,
744    pub location: Location,
745}
746
747impl<T> Clone for Literal<T>
748where
749    T: TypeSet,
750{
751    fn clone(&self) -> Self {
752        Self {
753            value: self.value.clone(),
754            location: self.location,
755        }
756    }
757}
758
759#[derive(Debug)]
760pub enum LiteralValue<T>
761where
762    T: TypeSet,
763{
764    Integer(T::Integer),
765    Float(T::Float),
766    String(String),
767    Boolean(bool),
768}
769
770impl<T> Clone for LiteralValue<T>
771where
772    T: TypeSet,
773{
774    fn clone(&self) -> Self {
775        match self {
776            Self::Integer(arg0) => Self::Integer(*arg0),
777            Self::Float(arg0) => Self::Float(*arg0),
778            Self::String(arg0) => Self::String(arg0.clone()),
779            Self::Boolean(arg0) => Self::Boolean(*arg0),
780        }
781    }
782}