somni_parser/
ast.rs

1use crate::{
2    lexer::{Location, Token},
3    parser::{DefaultTypeSet, TypeSet},
4};
5
6#[derive(Debug)]
7pub struct Program {
8    pub items: Vec<Item>,
9}
10
11#[derive(Debug)]
12pub enum Item {
13    Function(Function),
14    ExternFunction(ExternalFunction),
15    GlobalVariable(GlobalVariable),
16}
17
18#[derive(Debug)]
19pub struct GlobalVariable {
20    pub decl_token: Token,
21    pub identifier: Token,
22    pub colon: Token,
23    pub type_token: TypeHint,
24    pub equals_token: Token,
25    pub initializer: Expression,
26    pub semicolon: Token,
27}
28impl GlobalVariable {
29    pub fn location(&self) -> Location {
30        let start = self.decl_token.location.start;
31        let end = self.semicolon.location.end;
32        Location { start, end }
33    }
34}
35
36#[derive(Debug)]
37pub struct ReturnDecl {
38    pub return_token: Token,
39    pub return_type: TypeHint,
40}
41
42#[derive(Debug)]
43pub struct ExternalFunction {
44    pub extern_fn_token: Token,
45    pub fn_token: Token,
46    pub name: Token,
47    pub opening_paren: Token,
48    pub arguments: Vec<FunctionArgument>,
49    pub closing_paren: Token,
50    pub return_decl: Option<ReturnDecl>,
51    pub semicolon: Token,
52}
53
54#[derive(Debug)]
55pub struct Function {
56    pub fn_token: Token,
57    pub name: Token,
58    pub opening_paren: Token,
59    pub arguments: Vec<FunctionArgument>,
60    pub closing_paren: Token,
61    pub return_decl: Option<ReturnDecl>,
62    pub body: Body,
63}
64
65#[derive(Debug, Clone)]
66pub struct Body {
67    pub opening_brace: Token,
68    pub statements: Vec<Statement>,
69    pub closing_brace: Token,
70}
71
72#[derive(Debug)]
73pub struct FunctionArgument {
74    pub name: Token,
75    pub colon: Token,
76    pub reference_token: Option<Token>,
77    pub arg_type: TypeHint,
78}
79
80#[derive(Clone, Copy, Debug)]
81pub struct TypeHint {
82    pub type_name: Token,
83}
84
85#[derive(Debug, Clone)]
86pub struct VariableDefinition {
87    pub decl_token: Token,
88    pub identifier: Token,
89    pub type_token: Option<TypeHint>,
90    pub equals_token: Token,
91    pub initializer: Expression,
92    pub semicolon: Token,
93}
94
95impl VariableDefinition {
96    pub fn location(&self) -> Location {
97        let start = self.decl_token.location.start;
98        let end = self.semicolon.location.end;
99        Location { start, end }
100    }
101}
102
103#[derive(Debug, Clone)]
104pub struct ReturnWithValue {
105    pub return_token: Token,
106    pub expression: Expression,
107    pub semicolon: Token,
108}
109
110impl ReturnWithValue {
111    pub fn location(&self) -> Location {
112        let start = self.return_token.location.start;
113        let end = self.semicolon.location.end;
114        Location { start, end }
115    }
116}
117
118#[derive(Debug, Clone)]
119pub struct EmptyReturn {
120    pub return_token: Token,
121    pub semicolon: Token,
122}
123
124impl EmptyReturn {
125    pub fn location(&self) -> Location {
126        let start = self.return_token.location.start;
127        let end = self.semicolon.location.end;
128        Location { start, end }
129    }
130}
131
132#[derive(Debug, Clone)]
133pub struct If {
134    pub if_token: Token,
135    pub condition: Expression,
136    pub body: Body,
137    pub else_branch: Option<Else>,
138}
139
140#[derive(Debug, Clone)]
141pub struct Loop {
142    pub loop_token: Token,
143    pub body: Body,
144}
145
146#[derive(Debug, Clone)]
147pub struct Break {
148    pub break_token: Token,
149    pub semicolon: Token,
150}
151
152#[derive(Debug, Clone)]
153pub struct Continue {
154    pub continue_token: Token,
155    pub semicolon: Token,
156}
157
158#[derive(Debug, Clone)]
159pub enum Statement {
160    VariableDefinition(VariableDefinition),
161    Return(ReturnWithValue),
162    EmptyReturn(EmptyReturn),
163    If(If),
164    Loop(Loop),
165    Break(Break),
166    Continue(Continue),
167    Expression {
168        expression: Expression,
169        semicolon: Token,
170    },
171}
172
173#[derive(Debug, Clone)]
174pub struct Else {
175    pub else_token: Token,
176    pub else_body: Body,
177}
178
179#[derive(Debug, Clone)]
180pub enum Expression<T = DefaultTypeSet>
181where
182    T: TypeSet,
183{
184    Variable {
185        variable: Token,
186    },
187    Literal {
188        value: Literal<T>,
189    },
190    UnaryOperator {
191        name: Token,
192        operand: Box<Self>,
193    },
194    BinaryOperator {
195        name: Token,
196        operands: Box<[Self; 2]>,
197    },
198    FunctionCall {
199        name: Token,
200        arguments: Box<[Self]>,
201    },
202}
203impl<T> Expression<T>
204where
205    T: TypeSet,
206{
207    pub fn location(&self) -> Location {
208        match self {
209            Expression::Variable { variable } => variable.location,
210            Expression::Literal { value } => value.location,
211            Expression::FunctionCall { name, arguments } => {
212                let mut location = name.location;
213                for arg in arguments {
214                    location.start = location.start.min(arg.location().start);
215                    location.end = location.end.max(arg.location().end);
216                }
217                location
218            }
219            Expression::UnaryOperator { name, operand: rhs } => {
220                let mut location = name.location;
221
222                location.start = location.start.min(rhs.location().start);
223                location.end = location.end.max(rhs.location().end);
224
225                location
226            }
227            Expression::BinaryOperator {
228                name,
229                operands: arguments,
230            } => {
231                let mut location = name.location;
232                for arg in arguments.iter() {
233                    location.start = location.start.min(arg.location().start);
234                    location.end = location.end.max(arg.location().end);
235                }
236                location
237            }
238        }
239    }
240
241    pub fn as_variable(&self) -> Option<Token> {
242        if let Expression::Variable { variable } = self {
243            Some(*variable)
244        } else {
245            None
246        }
247    }
248}
249
250#[derive(Debug, Clone)]
251pub struct Literal<T = DefaultTypeSet>
252where
253    T: TypeSet,
254{
255    pub value: LiteralValue<T>,
256    pub location: Location,
257}
258
259#[derive(Debug, Clone)]
260pub enum LiteralValue<T = DefaultTypeSet>
261where
262    T: TypeSet,
263{
264    Integer(T::Integer),
265    Float(T::Float),
266    String(String),
267    Boolean(bool),
268}