envuse_parser/parser/
ast.rs

1use super::{span::Span, tokenizer::Token};
2use crate::syntax_error::SyntaxError;
3use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6#[derive(Debug, Serialize, Deserialize)]
7pub struct Document {
8    pub span: Span,
9    pub executable: Option<String>,
10    pub elements: Vec<Expression>,
11}
12
13#[derive(Debug, Serialize, Deserialize)]
14pub struct Variable {
15    pub span: Span,
16    pub comment: Box<Option<Expression>>,
17    pub name: String,
18    pub variable_type: Option<String>,
19    pub options_variable_type: Option<BTreeMap<String, Option<Expression>>>,
20    pub default_value: Box<Option<Expression>>,
21    pub nullable: bool,
22}
23
24#[derive(Debug, Serialize, Deserialize)]
25pub struct CommentBlock {
26    pub span: Span,
27    pub raw: Vec<String>,
28}
29
30#[derive(Debug, Serialize, Deserialize)]
31pub struct DefaultValue {
32    pub span: Span,
33    pub value: String,
34}
35
36#[derive(Debug, Serialize, Deserialize)]
37pub struct OptionValue {
38    pub span: Span,
39    pub value: String,
40}
41
42/// Expression
43#[derive(Debug, Serialize, Deserialize)]
44pub enum Expression {
45    Document(Document),
46    CommentBlock(CommentBlock),
47    Variable(Variable),
48    DefaultValue(DefaultValue),
49    OptionValue(OptionValue),
50}
51
52impl Expression {
53    fn to_span(&self) -> Span {
54        match self {
55            Expression::Document(Document { span, .. }) => span.clone(),
56            Expression::CommentBlock(CommentBlock { span, .. }) => span.clone(),
57            Expression::Variable(Variable { span, .. }) => span.clone(),
58            Expression::DefaultValue(DefaultValue { span, .. }) => span.clone(),
59            Expression::OptionValue(OptionValue { span, .. }) => span.clone(),
60        }
61    }
62
63    pub fn as_variable(&self) -> Option<&Variable> {
64        if let Self::Variable(v) = self {
65            Some(v)
66        } else {
67            None
68        }
69    }
70
71    pub fn as_document(&self) -> Option<&Document> {
72        if let Self::Document(v) = self {
73            Some(v)
74        } else {
75            None
76        }
77    }
78
79    pub fn as_default_value(&self) -> Option<&DefaultValue> {
80        if let Self::DefaultValue(v) = self {
81            Some(v)
82        } else {
83            None
84        }
85    }
86}
87
88#[derive(Debug, Clone)]
89struct Cursor<T>
90where
91    T: AsRef<Vec<Token>>,
92{
93    index: usize,
94    items: T,
95}
96
97impl<T> Cursor<T>
98where
99    T: AsRef<Vec<Token>>,
100{
101    fn new(items: T) -> Self {
102        Self { index: 0, items }
103    }
104
105    fn assert_current_kind<S: ToString, const U: usize>(
106        &self,
107        kinds: [S; U],
108    ) -> Result<&Token, SyntaxError> {
109        let kinds_str = kinds.map(|k| k.to_string());
110        if let Some(token) = self.select_current() {
111            if kinds_str.contains(&token.kind) {
112                Ok(token)
113            } else {
114                do yeet SyntaxError::new(
115                    format!("Unexpected token {}", token.kind),
116                    token.span.clone(),
117                )
118            }
119        } else {
120            do yeet SyntaxError::new(
121                "Unexpected token",
122                Span {
123                    start: self.index,
124                    end: self.index + 1,
125                },
126            )
127        }
128    }
129
130    fn forward_some_kind<S: ToString, const Z: usize>(&mut self, kinds: [S; Z]) {
131        let kinds_str = kinds.map(|k| k.to_string());
132        while let Some(token) = self.select_current() {
133            if kinds_str.contains(&token.kind) {
134                self.forward(1);
135                continue;
136            }
137            break;
138        }
139    }
140
141    fn select_current(&self) -> Option<&Token> {
142        self.items.as_ref().get(self.index)
143    }
144
145    fn select_next(&self) -> Option<&Token> {
146        self.items.as_ref().get(self.index + 1)
147    }
148
149    fn select_nexts(&self, steps: usize) -> Option<&Token> {
150        self.items.as_ref().get(self.index + steps)
151    }
152
153    fn select_prev(&self) -> Option<&Token> {
154        self.items.as_ref().get(self.index - 1)
155    }
156
157    fn next(&mut self) -> Option<&Token> {
158        self.forward(1);
159        self.select_prev()
160    }
161
162    fn forward(&mut self, steps: usize) {
163        self.index = self.index + steps;
164    }
165}
166
167pub struct AST {}
168
169impl AST {
170    pub fn parse(tokens: Vec<Token>) -> Result<Expression, SyntaxError> {
171        let mut executable: Option<String> = None;
172        let ref mut token_cursor = Cursor::new(tokens);
173        let mut span_start: usize = 0;
174        let mut span_end: usize = 0;
175
176        if let Some(token) = token_cursor.select_current() {
177            if token.kind == "comment" && token.raw.starts_with("#!") {
178                span_start = token.span.start;
179                span_end = token.span.end;
180                executable = Some(token.raw.to_string());
181                token_cursor.forward(1);
182            }
183        }
184
185        let elements = Self::parse_expressions_list(token_cursor)?;
186
187        if let Some(expression) = elements.last() {
188            span_end = expression.to_span().end;
189        }
190
191        Ok(Expression::Document(Document {
192            executable,
193            elements,
194            span: Span {
195                start: span_start,
196                end: span_end,
197            },
198        }))
199    }
200
201    fn parse_expressions_list(
202        tokens_cursor: &mut Cursor<Vec<Token>>,
203    ) -> Result<Vec<Expression>, SyntaxError> {
204        let mut vec: Vec<Expression> = vec![];
205
206        while let Some(token) = tokens_cursor.select_current() {
207            if token.kind == "newline" || token.kind == "space" {
208                tokens_cursor.forward(1);
209                continue;
210            }
211            if token.kind == "comment" {
212                vec.push(Self::parse_block_comment(tokens_cursor)?);
213                continue;
214            }
215            if token.kind == "keyword" {
216                vec.push(Self::parse_variable(tokens_cursor, None)?);
217                continue;
218            }
219            do yeet SyntaxError::new("Unexpected type", token.span.clone())
220        }
221
222        Ok(vec)
223    }
224
225    fn parse_block_comment(
226        tokens_cursor: &mut Cursor<Vec<Token>>,
227    ) -> Result<Expression, SyntaxError> {
228        let span_start = tokens_cursor.select_current().unwrap().span.start;
229        let mut span_end = tokens_cursor.select_current().unwrap().span.end;
230        let mut raw: Vec<String> = vec![];
231
232        while let Some(token) = tokens_cursor.select_current() {
233            if token.kind == "space" {
234                tokens_cursor.forward(1);
235                continue;
236            }
237
238            if token.kind != "comment" {
239                break;
240            }
241
242            raw.push(token.raw.to_string());
243            span_end = token.span.end;
244
245            if let Some(token) = tokens_cursor.select_next() {
246                if token.kind == "newline" {
247                    tokens_cursor.forward(1);
248                }
249            }
250
251            tokens_cursor.forward(1);
252        }
253
254        let comment = Expression::CommentBlock(CommentBlock {
255            span: Span {
256                start: span_start,
257                end: span_end,
258            },
259            raw,
260        });
261
262        if let Some(token) = tokens_cursor.select_current() {
263            if token.kind == "keyword" {
264                return Ok(Self::parse_variable(tokens_cursor, Some(comment))?);
265            }
266        }
267
268        Ok(comment)
269    }
270
271    fn parse_variable(
272        tokens_cursor: &mut Cursor<Vec<Token>>,
273        comment: Option<Expression>,
274    ) -> Result<Expression, SyntaxError> {
275        // Assert Start with keyword
276        tokens_cursor.assert_current_kind(["keyword"])?;
277
278        let name: String = tokens_cursor.select_current().unwrap().raw.to_string();
279        let span_start: usize = tokens_cursor.select_current().unwrap().span.start;
280        let mut span_end: usize = tokens_cursor.select_current().unwrap().span.end;
281        let mut variable_type: Option<String> = None;
282        let mut options_variable_type: Option<BTreeMap<String, Option<Expression>>> = None;
283        let mut default_value: Option<Expression> = None;
284        let mut nullable: bool = false;
285        tokens_cursor.forward(1);
286
287        tokens_cursor.forward_some_kind(["space"]);
288
289        if tokens_cursor.assert_current_kind(["colon"]).is_ok() {
290            tokens_cursor.forward(1);
291            tokens_cursor.forward_some_kind(["space"]);
292            tokens_cursor.assert_current_kind(["keyword"])?;
293            let variable_type_token = tokens_cursor.select_current().unwrap();
294            variable_type = Some(variable_type_token.raw.to_string());
295            span_end = variable_type_token.span.end;
296            tokens_cursor.forward(1);
297            tokens_cursor.forward_some_kind(["space"]);
298
299            if tokens_cursor.assert_current_kind(["less_than"]).is_ok() {
300                tokens_cursor.forward(1);
301                tokens_cursor.forward_some_kind(["space", "newline"]);
302
303                let mut options: BTreeMap<String, Option<Expression>> = Default::default();
304
305                while tokens_cursor.assert_current_kind(["keyword"]).is_ok() {
306                    let option_key = tokens_cursor.select_current().unwrap().raw.to_string();
307                    tokens_cursor.forward(1);
308                    tokens_cursor.forward_some_kind(["space", "newline"]);
309                    if tokens_cursor.assert_current_kind(["equal"]).is_ok() {
310                        tokens_cursor.assert_current_kind(["equal"])?;
311                        tokens_cursor.forward(1);
312                        tokens_cursor.forward_some_kind(["space"]);
313                        let value_expression = Self::parse_items_option_value(tokens_cursor)?;
314                        options.insert(option_key, Some(value_expression));
315                        tokens_cursor.forward_some_kind(["space", "newline"]);
316                    } else {
317                        options.insert(option_key, None);
318                    }
319                }
320
321                let greater_than = tokens_cursor.assert_current_kind(["greater_than"])?;
322                span_end = greater_than.span.end;
323                tokens_cursor.forward(1);
324
325                options_variable_type = Some(options);
326
327                tokens_cursor.forward_some_kind(["space"]);
328            }
329
330            if let Ok(token) = tokens_cursor.assert_current_kind(["question_mark"]) {
331                span_end = token.span.end;
332                tokens_cursor.forward(1);
333                nullable = true;
334            }
335        }
336
337        if tokens_cursor.assert_current_kind(["equal"]).is_ok() {
338            tokens_cursor.forward(1);
339            tokens_cursor.forward_some_kind(["space"]);
340            let default_value_expression = Self::parse_items_default_value(tokens_cursor)?;
341            span_end = default_value_expression.to_span().end;
342            default_value = Some(default_value_expression);
343        }
344
345        Ok(Expression::Variable(Variable {
346            span: Span {
347                start: span_start,
348                end: span_end,
349            },
350            comment: Box::new(comment),
351            name: name,
352            variable_type,
353            options_variable_type,
354            default_value: Box::new(default_value),
355            nullable,
356        }))
357    }
358
359    fn parse_items_default_value(
360        tokens_cursor: &mut Cursor<Vec<Token>>,
361    ) -> Result<Expression, SyntaxError> {
362        match tokens_cursor.select_current() {
363            Some(token) if token.kind == "string" => {
364                Ok(Self::parse_items_default_value_string(tokens_cursor)?)
365            }
366            Some(token) if token.kind == "number" => {
367                Ok(Self::parse_items_default_value_number(tokens_cursor)?)
368            }
369            Some(token) => do yeet SyntaxError::new("Unexpected token", token.span.clone()),
370            _ => {
371                do yeet SyntaxError::new(
372                    "Unexpected token",
373                    Span {
374                        start: tokens_cursor.index,
375                        end: tokens_cursor.index + 1,
376                    },
377                )
378            }
379        }
380    }
381
382    fn parse_items_default_value_string(
383        tokens_cursor: &mut Cursor<Vec<Token>>,
384    ) -> Result<Expression, SyntaxError> {
385        let token = tokens_cursor.select_current().unwrap();
386        let a = Expression::DefaultValue(DefaultValue {
387            span: token.span.clone(),
388            value: token.raw.to_string(),
389        });
390        tokens_cursor.forward(1);
391        return Ok(a);
392    }
393
394    fn parse_items_default_value_number(
395        tokens_cursor: &mut Cursor<Vec<Token>>,
396    ) -> Result<Expression, SyntaxError> {
397        let token = tokens_cursor.select_current().unwrap();
398        let a = Expression::DefaultValue(DefaultValue {
399            span: token.span.clone(),
400            value: token.raw.to_string(),
401        });
402        tokens_cursor.forward(1);
403        return Ok(a);
404    }
405
406    fn parse_items_option_value(
407        tokens_cursor: &mut Cursor<Vec<Token>>,
408    ) -> Result<Expression, SyntaxError> {
409        match tokens_cursor.select_current() {
410            Some(token) if token.kind == "string" => {
411                Ok(Self::parse_items_option_value_string(tokens_cursor)?)
412            }
413            Some(token) if token.kind == "number" => {
414                Ok(Self::parse_items_option_value_number(tokens_cursor)?)
415            }
416            Some(token) => do yeet SyntaxError::new("Unexpected token", token.span.clone()),
417            _ => {
418                do yeet SyntaxError::new(
419                    "Unexpected token",
420                    Span {
421                        start: tokens_cursor.index,
422                        end: tokens_cursor.index + 1,
423                    },
424                )
425            }
426        }
427    }
428
429    fn parse_items_option_value_string(
430        tokens_cursor: &mut Cursor<Vec<Token>>,
431    ) -> Result<Expression, SyntaxError> {
432        let token = tokens_cursor.select_current().unwrap();
433        let a = Expression::OptionValue(OptionValue {
434            span: token.span.clone(),
435            value: token.raw.to_string(),
436        });
437        tokens_cursor.forward(1);
438        return Ok(a);
439    }
440
441    fn parse_items_option_value_number(
442        tokens_cursor: &mut Cursor<Vec<Token>>,
443    ) -> Result<Expression, SyntaxError> {
444        let token = tokens_cursor.select_current().unwrap();
445        let a = Expression::OptionValue(OptionValue {
446            span: token.span.clone(),
447            value: token.raw.to_string(),
448        });
449        tokens_cursor.forward(1);
450        return Ok(a);
451    }
452}