Skip to main content

rbx_rsml/parser/
types.rs

1use ropey::Rope;
2
3use crate::range_from_span::RangeFromSpan;
4use crate::types::{Diagnostic, LanguageMode, Range};
5
6use crate::lexer::{SpannedToken, Token};
7use crate::parser::RsmlParser;
8use crate::parser::parse_error::ParseError;
9
10#[derive(Debug, Default, Clone, Copy)]
11pub struct Directives {
12    pub nobuiltins: bool,
13    pub language_mode: Option<LanguageMode>,
14}
15
16pub struct ParsedRsml<'a> {
17    pub ast: Vec<Construct<'a>>,
18    pub ast_errors: AstErrors,
19    pub directives: Directives,
20    pub rope: Rope,
21}
22
23impl<'a> ParsedRsml<'a> {
24    pub fn range_from_span(&self, span: (usize, usize)) -> Range {
25        Range::from_span(&self.rope, span)
26    }
27}
28
29pub(crate) type Trivia<'a> = Vec<SpannedToken<'a>>;
30
31#[derive(Debug)]
32pub struct Node<'a> {
33    pub token: SpannedToken<'a>,
34    pub leading_trivia: Option<Trivia<'a>>,
35}
36
37pub(crate) trait UpdateLastTokenEnd {
38    fn update_last_token_end(self, parser: &mut RsmlParser) -> Self;
39}
40
41impl<'a> UpdateLastTokenEnd for Option<Node<'a>> {
42    fn update_last_token_end(self, parser: &mut RsmlParser) -> Self {
43        if let Some(Node {
44            token: SpannedToken(_, _, end),
45            ..
46        }) = self
47        {
48            parser.last_token_end = end
49        };
50
51        self
52    }
53}
54
55pub(crate) trait ToStatus<'a> {
56    fn to_status(self) -> NodeStatus<'a>;
57}
58
59impl<'a> ToStatus<'a> for Option<Node<'a>> {
60    fn to_status(self) -> NodeStatus<'a> {
61        match self {
62            Some(node) => NodeStatus::Err(node),
63            None => NodeStatus::None,
64        }
65    }
66}
67
68impl<'a> ToStatus<'a> for Node<'a> {
69    fn to_status(self) -> NodeStatus<'a> {
70        NodeStatus::Err(self)
71    }
72}
73
74pub(crate) struct Parsed<'a, T = Construct<'a>>(pub Option<Node<'a>>, pub Option<T>);
75
76impl<'a> Parsed<'a> {
77    pub(crate) fn handle_construct(self, ast: &mut Vec<Construct<'a>>) -> Option<Node<'a>> {
78        if let Some(construct) = self.1 {
79            ast.push(construct)
80        };
81        self.0
82    }
83}
84
85pub trait SpanEnd {
86    fn end(&self) -> usize;
87}
88
89#[derive(Debug)]
90pub enum SelectorNode<'a> {
91    Token(Node<'a>),
92    MacroCall {
93        name: Node<'a>,
94        body: Option<Delimited<'a>>,
95    },
96}
97
98impl<'a> SelectorNode<'a> {
99    pub fn start(&self) -> usize {
100        match self {
101            Self::Token(node) => node.token.start(),
102            Self::MacroCall { name, .. } => name.token.start(),
103        }
104    }
105}
106
107impl<'a> SpanEnd for SelectorNode<'a> {
108    fn end(&self) -> usize {
109        match self {
110            Self::Token(node) => node.token.end(),
111            Self::MacroCall { name, body } => {
112                if let Some(body) = body {
113                    return body.end();
114                }
115                name.token.end()
116            }
117        }
118    }
119}
120
121#[derive(Debug)]
122pub enum MacroBodyContent<'a> {
123    Construct(Option<Vec<Construct<'a>>>),
124    Datatype(Option<Box<Construct<'a>>>),
125    Selector(Option<Vec<SelectorNode<'a>>>),
126}
127
128#[derive(Debug)]
129pub struct MacroBody<'a> {
130    pub open: Node<'a>,
131    pub content: MacroBodyContent<'a>,
132    pub close: Option<Node<'a>>,
133}
134
135impl<'a> SpanEnd for MacroBody<'a> {
136    fn end(&self) -> usize {
137        if let Some(close) = &self.close {
138            return close.token.end();
139        }
140        match &self.content {
141            MacroBodyContent::Construct(Some(items)) => {
142                if let Some(last) = items.last() {
143                    return last.end();
144                }
145            }
146
147            MacroBodyContent::Datatype(Some(item)) => return item.end(),
148
149            MacroBodyContent::Selector(Some(items)) => {
150                if let Some(last) = items.last() {
151                    return last.end();
152                }
153            }
154
155            _ => {}
156        }
157
158        self.open.token.end()
159    }
160}
161
162#[derive(Debug)]
163pub enum Construct<'a> {
164    Macro {
165        declaration: Node<'a>,
166        name: Option<Node<'a>>,
167        args: Option<Delimited<'a>>,
168        return_type: Option<(Node<'a>, Option<Node<'a>>)>,
169        body: Option<MacroBody<'a>>,
170    },
171
172    MacroCall {
173        name: Node<'a>,
174        body: Option<Delimited<'a>>,
175        terminator: Option<Node<'a>>,
176    },
177
178    Derive {
179        declaration: Node<'a>,
180        body: Option<Box<Construct<'a>>>,
181        terminator: Option<Node<'a>>,
182    },
183
184    Priority {
185        declaration: Node<'a>,
186        body: Option<Box<Construct<'a>>>,
187        terminator: Option<Node<'a>>,
188    },
189
190    Tween {
191        declaration: Node<'a>,
192        name: Option<Node<'a>>,
193        body: Option<Box<Construct<'a>>>,
194        terminator: Option<Node<'a>>,
195    },
196
197    Rule {
198        selectors: Option<Vec<SelectorNode<'a>>>,
199        body: Option<Delimited<'a>>,
200    },
201
202    Assignment {
203        left: Node<'a>,
204        middle: Option<Node<'a>>,
205        right: Option<Box<Construct<'a>>>,
206        terminator: Option<Node<'a>>,
207    },
208
209    MathOperation {
210        left: Box<Construct<'a>>,
211        operators: Vec<Node<'a>>,
212        right: Option<Box<Construct<'a>>>,
213    },
214
215    UnaryMinus {
216        operator: Node<'a>,
217        operand: Box<Construct<'a>>,
218    },
219
220    AnnotatedTable {
221        annotation: Node<'a>,
222        body: Option<Delimited<'a>>,
223    },
224
225    Table {
226        body: Delimited<'a>,
227    },
228
229    Enum {
230        keyword: Node<'a>,
231        name: Option<Node<'a>>,
232        variant: Option<Node<'a>>,
233    },
234
235    Node {
236        node: Node<'a>,
237    },
238
239    None {
240        node: Node<'a>,
241    },
242}
243
244impl<'a> Construct<'a> {
245    pub fn rule(selectors: Option<Vec<SelectorNode<'a>>>, body: Delimited<'a>) -> Self {
246        Self::Rule {
247            selectors,
248            body: Some(body),
249        }
250    }
251
252    pub fn name_plural(&self) -> &str {
253        match self {
254            Self::Macro { .. } => "Macros",
255            Self::MacroCall { .. } => "Macro calls",
256            Self::Derive { .. } => "Derives",
257            Self::Priority { .. } => "Priorities",
258            Self::Tween { .. } => "Tweens",
259            Self::Rule { .. } => "Rules",
260            Self::Assignment { left, .. } => match left.token.value() {
261                Token::Identifier(_) => "Property assignments",
262                Token::StaticTokenIdentifier(_) => "Static token assignments",
263                Token::TokenIdentifier(_) => "Token assignments",
264                _ => "Assignments",
265            },
266            Self::MathOperation { .. } | Self::UnaryMinus { .. } => "Math Operations",
267            Self::Table { .. } | Self::AnnotatedTable { .. } => "Tables",
268            Self::Enum { .. } => "Enums",
269            Self::Node { .. } | Self::None { .. } => "These",
270        }
271    }
272
273    pub fn start(&self) -> usize {
274        match self {
275            Self::Macro { declaration, .. } => declaration.token.start(),
276            Self::MacroCall { name, .. } => name.token.start(),
277
278            Self::Derive { declaration, .. }
279            | Self::Priority { declaration, .. }
280            | Self::Tween { declaration, .. } => declaration.token.start(),
281
282            Self::Rule { selectors, body } => {
283                if let Some(first) = selectors.as_ref().and_then(|s| s.first()) {
284                    return first.start();
285                }
286
287                if let Some(body) = body {
288                    return body.start();
289                }
290
291                0
292            }
293
294            Self::Assignment { left, .. } => left.token.start(),
295            Self::MathOperation { left, .. } => left.start(),
296            Self::UnaryMinus { operator, .. } => operator.token.start(),
297            Self::AnnotatedTable { annotation, .. } => annotation.token.start(),
298            Self::Table { body } => body.start(),
299            Self::Enum { keyword, .. } => keyword.token.start(),
300            Self::Node { node } | Self::None { node } => node.token.start(),
301        }
302    }
303
304    pub fn span(&self) -> (usize, usize) {
305        (self.start(), self.end())
306    }
307}
308
309impl<'a> SpanEnd for Construct<'a> {
310    fn end(&self) -> usize {
311        match self {
312            Self::Macro {
313                declaration,
314                name,
315                args,
316                return_type,
317                body,
318            } => {
319                if let Some(body) = body {
320                    return body.end();
321                }
322
323                if let Some((arrow, ident)) = return_type {
324                    if let Some(ident) = ident {
325                        return ident.token.end();
326                    }
327
328                    return arrow.token.end();
329                }
330
331                if let Some(args) = args {
332                    return args.end();
333                }
334
335                if let Some(name) = name {
336                    return name.token.end();
337                }
338
339                declaration.token.end()
340            }
341
342            Self::MacroCall {
343                name,
344                body,
345                terminator,
346            } => {
347                if let Some(terminator) = terminator {
348                    return terminator.token.end();
349                }
350
351                if let Some(body) = body {
352                    return body.end();
353                }
354
355                name.token.end()
356            }
357
358            Self::Derive {
359                declaration,
360                body,
361                terminator,
362            }
363            | Self::Priority {
364                declaration,
365                body,
366                terminator,
367            }
368            => {
369                if let Some(terminator) = terminator {
370                    return terminator.token.end();
371                }
372
373                if let Some(body) = body {
374                    return body.end();
375                }
376
377                declaration.token.end()
378            }
379
380            Self::Tween {
381                declaration,
382                name,
383                body,
384                terminator,
385            } => {
386                if let Some(terminator) = terminator {
387                    return terminator.token.end();
388                }
389
390                if let Some(body) = body {
391                    return body.end();
392                }
393
394                if let Some(name) = name {
395                    return name.token.end();
396                }
397
398                declaration.token.end()
399            }
400
401            Self::Rule { body, .. } => {
402                if let Some(body) = body {
403                    return body.end();
404                }
405
406                0
407            }
408
409            Self::Assignment {
410                left,
411                middle,
412                right,
413                terminator,
414            } => {
415                if let Some(terminator) = terminator {
416                    return terminator.token.end();
417                }
418
419                if let Some(right) = right {
420                    return right.end();
421                }
422
423                if let Some(middle) = middle {
424                    return middle.token.end();
425                }
426
427                left.token.end()
428            }
429
430            Self::MathOperation {
431                left,
432                operators,
433                right,
434                ..
435            } => {
436                if let Some(right) = right {
437                    return right.end();
438                }
439
440                if let Some(last_op) = operators.last() {
441                    return last_op.token.end();
442                }
443
444                left.end()
445            }
446
447            Self::UnaryMinus { operand, .. } => operand.end(),
448
449            Self::AnnotatedTable { annotation, body } => {
450                if let Some(body) = body {
451                    return body.end();
452                }
453
454                annotation.token.end()
455            }
456
457            Self::Table { body } => body.end(),
458
459            Self::Enum {
460                keyword,
461                name,
462                variant,
463            } => {
464                if let Some(variant) = variant {
465                    return variant.token.end();
466                }
467
468                if let Some(name) = name {
469                    return name.token.end();
470                }
471
472                keyword.token.end()
473            }
474
475            Self::Node { node } | Self::None { node } => node.token.end(),
476        }
477    }
478}
479
480pub(crate) enum ParseEndedReason {
481    Eof,
482    Manual,
483}
484
485#[derive(Debug)]
486pub struct Delimited<'a, T: SpanEnd = Construct<'a>> {
487    pub left: Node<'a>,
488    pub content: Option<Vec<T>>,
489    pub right: Option<Node<'a>>,
490}
491
492impl<'a, T: SpanEnd> Delimited<'a, T> {
493    pub(crate) fn new(left: Node<'a>, content: Option<Vec<T>>, right: Option<Node<'a>>) -> Self {
494        Self {
495            left,
496            content,
497            right,
498        }
499    }
500
501    #[inline(always)]
502    pub(crate) fn start(&self) -> usize {
503        self.left.token.start()
504    }
505
506    pub(crate) fn end(&self) -> usize {
507        if let Some(right) = &self.right {
508            return right.token.2;
509        }
510
511        if let Some(content) = &self.content {
512            if let Some(last) = content.last() {
513                return last.end();
514            }
515        }
516
517        self.left.token.end()
518    }
519}
520
521impl<'a, T: SpanEnd> SpanEnd for Delimited<'a, T> {
522    fn end(&self) -> usize {
523        Delimited::end(self)
524    }
525}
526
527#[derive(Debug)]
528pub struct AstErrors(pub Vec<Diagnostic>);
529
530impl AstErrors {
531    pub fn new() -> Self {
532        Self(Vec::new())
533    }
534}
535
536pub(crate) trait PushParseError {
537    fn push(&mut self, error: ParseError, range: Range);
538}
539
540impl PushParseError for AstErrors {
541    fn push(&mut self, error: ParseError, range: Range) {
542        self.0.push(Diagnostic {
543            range,
544            severity: error.severity(),
545            code: error.to_string(),
546            message: error.message(),
547            data: error.data(),
548        });
549    }
550}
551
552#[inline(always)]
553pub(crate) fn clamp_span_to_end(span_end: usize) -> (usize, usize) {
554    (span_end - 1, span_end)
555}
556
557#[derive(Debug)]
558pub enum NodeStatus<'a> {
559    Exists,
560
561    None,
562
563    /// A block delimiter token was reached before the expected token while advancing.
564    Err(Node<'a>),
565}
566
567impl<'a> NodeStatus<'a> {
568    pub(crate) fn consume_err_or_advance(self, parser: &mut RsmlParser<'a>) -> Option<Node<'a>> {
569        match self {
570            Self::Err(node) => Some(node),
571            Self::Exists => parser.advance(),
572            Self::None => None,
573        }
574    }
575}