sixtyfps_compilerlib/
parser.rs

1// Copyright © SixtyFPS GmbH <info@sixtyfps.io>
2// SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
3
4/*! The sixtyfps language parser
5
6This module is responsible to parse a string onto a syntax tree.
7
8The core of it is the `DefaultParser` class that holds a list of token and
9generates a `rowan::GreenNode`
10
11This module has different sub modules with the actual parser functions
12
13*/
14
15use crate::diagnostics::{BuildDiagnostics, SourceFile, Spanned};
16pub use smol_str::SmolStr;
17use std::{convert::TryFrom, fmt::Display};
18
19mod document;
20mod element;
21mod expressions;
22mod statements;
23mod r#type;
24
25/// Each parser submodule would simply do `use super::prelude::*` to import typically used items
26mod prelude {
27    #[cfg(test)]
28    pub use super::{syntax_nodes, SyntaxNode, SyntaxNodeVerify};
29    pub use super::{DefaultParser, Parser, SyntaxKind};
30    #[cfg(test)]
31    pub use parser_test_macro::parser_test;
32}
33
34#[cfg(test)]
35pub trait SyntaxNodeVerify {
36    /// The SyntaxKind corresponding to this type
37    const KIND: SyntaxKind;
38    /// Asserts that the node is of the given SyntaxKind and that it has the expected children
39    /// Panic if this is not the case
40    fn verify(node: SyntaxNode) {
41        assert_eq!(node.kind(), Self::KIND)
42    }
43}
44
45/// Check that a node has the assumed children
46#[cfg(test)]
47macro_rules! verify_node {
48    // nothing to verify
49    ($node:ident, _) => {};
50    // Some combination of children
51    ($node:ident, [ $($t1:tt $($t2:ident)?),* ]) => {
52        // Check that every children is there
53        $(verify_node!(@check_has_children $node, $t1 $($t2)* );)*
54
55        // check that there are not too many nodes
56        for c in $node.children() {
57            assert!(
58                false $(|| c.kind() == verify_node!(@extract_kind $t1 $($t2)*))*,
59                "Node is none of [{}]\n{:?}", stringify!($($t1 $($t2)*),*) ,c);
60        }
61
62        // recurse
63        $(
64            for _c in $node.children().filter(|n| n.kind() == verify_node!(@extract_kind $t1 $($t2)*)) {
65                <verify_node!(@extract_type $t1 $($t2)*)>::verify(_c)
66            }
67        )*
68    };
69
70    // Any number of this kind.
71    (@check_has_children $node:ident, * $kind:ident) => {};
72    // 1 or 0
73    (@check_has_children $node:ident, ? $kind:ident) => {
74        let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
75        assert!(count <= 1, "Expecting one or zero sub-node of type {}, found {}\n{:?}", stringify!($kind), count, $node);
76    };
77    // Exactly one
78    (@check_has_children $node:ident, $kind:ident) => {
79        let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
80        assert_eq!(count, 1, "Expecting exactly one sub-node of type {}\n{:?}", stringify!($kind), $node);
81    };
82    // Exact number
83    (@check_has_children $node:ident, $count:literal $kind:ident) => {
84        let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
85        assert_eq!(count, $count, "Expecting {} sub-node of type {}, found {}\n{:?}", $count, stringify!($kind), count, $node);
86    };
87
88    (@extract_kind * $kind:ident) => {SyntaxKind::$kind};
89    (@extract_kind ? $kind:ident) => {SyntaxKind::$kind};
90    (@extract_kind $count:literal $kind:ident) => {SyntaxKind::$kind};
91    (@extract_kind $kind:ident) => {SyntaxKind::$kind};
92
93    (@extract_type * $kind:ident) => {$crate::parser::syntax_nodes::$kind};
94    (@extract_type ? $kind:ident) => {$crate::parser::syntax_nodes::$kind};
95    (@extract_type $count:literal $kind:ident) => {$crate::parser::syntax_nodes::$kind};
96    (@extract_type $kind:ident) => {$crate::parser::syntax_nodes::$kind};
97}
98
99macro_rules! node_accessors {
100    // nothing
101    (_) => {};
102    // Some combination of children
103    ([ $($t1:tt $($t2:ident)?),* ]) => {
104        $(node_accessors!{@ $t1 $($t2)*} )*
105    };
106
107    (@ * $kind:ident) => {
108        #[allow(non_snake_case)]
109        pub fn $kind(&self) -> impl Iterator<Item = $kind> {
110            self.0.children().filter(|n| n.kind() == SyntaxKind::$kind).map(Into::into)
111        }
112    };
113    (@ ? $kind:ident) => {
114        #[allow(non_snake_case)]
115        pub fn $kind(&self) -> Option<$kind> {
116            self.0.child_node(SyntaxKind::$kind).map(Into::into)
117        }
118    };
119    (@ 2 $kind:ident) => {
120        #[allow(non_snake_case)]
121        pub fn $kind(&self) -> ($kind, $kind) {
122            let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
123            let a = it.next().unwrap();
124            let b = it.next().unwrap();
125            debug_assert!(it.next().is_none());
126            (a.into(), b.into())
127        }
128    };
129    (@ 3 $kind:ident) => {
130        #[allow(non_snake_case)]
131        pub fn $kind(&self) -> ($kind, $kind, $kind) {
132            let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
133            let a = it.next().unwrap();
134            let b = it.next().unwrap();
135            let c = it.next().unwrap();
136            debug_assert!(it.next().is_none());
137            (a.into(), b.into(), c.into())
138        }
139    };
140    (@ $kind:ident) => {
141        #[allow(non_snake_case)]
142        pub fn $kind(&self) -> $kind {
143            self.0.child_node(SyntaxKind::$kind).unwrap().into()
144        }
145    };
146
147}
148
149/// This macro is invoked once, to declare all the token and syntax kind.
150/// The purpose of this macro is to declare the token with its regexp at the same place,
151/// and the nodes with their contents.
152///
153/// This is split into two group: first the tokens, then the nodes.
154///
155/// # Tokens
156///
157/// Given as `$token:ident -> $rule:expr`. The rule parameter can be either a string literal or
158/// a lexer function. The order of tokens is important because the rules will be run in that order
159/// and the first one matching will be chosen.
160///
161/// # Nodes
162///
163/// Given as `$(#[$attr:meta])* $nodekind:ident -> [$($children:tt),*] `.
164/// Where `children` is a list of sub-nodes (not including tokens).
165/// This will allow to self-document and create the structure from the [`syntax_nodes`] module.
166/// The children can be prefixed with the following symbol:
167///
168/// - nothing: The node occurs once and exactly once, the generated accessor returns the node itself
169/// - `+`: the node occurs one or several times, the generated accessor returns an `Iterator`
170/// - `*`: the node occurs zero or several times, the generated accessor returns an `Iterator`
171/// - `?`: the node occurs once or zero times, the generated accessor returns an `Option`
172/// - `2` or `3`: the node occurs exactly two or three times, the generated accessor returns a tuple
173///
174/// Note: the parser must generate the right amount of sub nodes, even if there is a parse error.
175///
176/// ## The [`syntax_nodes`] module
177///
178/// Creates one struct for every node with the given accessor.
179/// The struct can be converted from and to the node.
180macro_rules! declare_syntax {
181    ({
182        $($token:ident -> $rule:expr ,)*
183     }
184     {
185        $( $(#[$attr:meta])*  $nodekind:ident -> $children:tt ,)*
186    })
187    => {
188        #[repr(u16)]
189        #[derive(Debug, Copy, Clone, Eq, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
190        pub enum SyntaxKind {
191            Error,
192            Eof,
193
194            // Tokens:
195            $(
196                /// Token
197                $token,
198            )*
199
200            // Nodes:
201            $(
202                $(#[$attr])*
203                $nodekind,
204            )*
205        }
206
207        impl Display for SyntaxKind {
208            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209                match self {
210                    $(Self::$token => {
211                        if let Some(character) = <dyn std::any::Any>::downcast_ref::<&str>(& $rule) {
212                            return write!(f, "'{}'", character)
213                        }
214                    })*
215                    _ => ()
216                }
217                write!(f, "{:?}", self)
218            }
219        }
220
221
222        /// Returns a pair of the matched token type at the beginning of `text`, and its size
223        pub fn lex_next_token(text : &str, state: &mut crate::lexer::LexState) -> Option<(usize, SyntaxKind)> {
224            use crate::lexer::LexingRule;
225            $(
226                let len = ($rule).lex(text, state);
227                if len > 0 {
228                    return Some((len, SyntaxKind::$token));
229                }
230            )*
231            None
232        }
233
234        pub mod syntax_nodes {
235            use super::*;
236            use derive_more::*;
237            $(
238                #[derive(Debug, Clone, Deref, Into)]
239                pub struct $nodekind(SyntaxNode);
240                #[cfg(test)]
241                impl SyntaxNodeVerify for $nodekind {
242                    const KIND: SyntaxKind = SyntaxKind::$nodekind;
243                    fn verify(node: SyntaxNode) {
244                        assert_eq!(node.kind(), Self::KIND);
245                        verify_node!(node, $children);
246                    }
247                }
248                impl $nodekind {
249                    node_accessors!{$children}
250
251                    /// Create a new node from a SyntaxNode, if the SyntaxNode is of the correct kind
252                    pub fn new(node: SyntaxNode) -> Option<Self> {
253                        (node.kind() == SyntaxKind::$nodekind).then(|| Self(node))
254                    }
255                }
256
257                impl From<SyntaxNode> for $nodekind {
258                    fn from(node: SyntaxNode) -> Self {
259                        debug_assert_eq!(node.kind(), SyntaxKind::$nodekind);
260                        Self(node)
261                    }
262                }
263
264                impl Spanned for $nodekind {
265                    fn span(&self) -> crate::diagnostics::Span {
266                        self.0.span()
267                    }
268
269                    fn source_file(&self) -> Option<&SourceFile> {
270                        self.0.source_file()
271                    }
272                }
273            )*
274        }
275    }
276}
277declare_syntax! {
278    // Tokens.
279    // WARNING: when changing this, do not forget to update the tokenizer in the sixtyfps-rs-macro crate!
280    // The order of token is important because the rules will be run in that order
281    // and the first one matching will be chosen.
282    {
283        Whitespace -> &crate::lexer::lex_whitespace,
284        Comment -> &crate::lexer::lex_comment,
285        StringLiteral -> &crate::lexer::lex_string,
286        NumberLiteral -> &crate::lexer::lex_number,
287        ColorLiteral -> &crate::lexer::lex_color,
288        Identifier -> &crate::lexer::lex_identifier,
289        DoubleArrow -> "<=>",
290        PlusEqual -> "+=",
291        MinusEqual -> "-=",
292        StarEqual -> "*=",
293        DivEqual -> "/=",
294        LessEqual -> "<=",
295        GreaterEqual -> ">=",
296        EqualEqual -> "==",
297        NotEqual -> "!=",
298        ColonEqual -> ":=",
299        FatArrow -> "=>",
300        Arrow -> "->",
301        OrOr -> "||",
302        AndAnd -> "&&",
303        LBrace -> "{",
304        RBrace -> "}",
305        LParent -> "(",
306        RParent -> ")",
307        LAngle -> "<",
308        RAngle -> ">",
309        LBracket -> "[",
310        RBracket -> "]",
311        Plus -> "+",
312        Minus -> "-",
313        Star -> "*",
314        Div -> "/",
315        Equal -> "=",
316        Colon -> ":",
317        Comma -> ",",
318        Semicolon -> ";",
319        Bang -> "!",
320        Dot -> ".",
321        Question -> "?",
322        Dollar -> "$",
323        At -> "@",
324    }
325    // syntax kind
326    {
327        Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration ],
328        /// `DeclaredIdentifier := Element { ... }`
329        Component -> [ DeclaredIdentifier, Element ],
330        /// `id := Element { ... }`
331        SubElement -> [ Element ],
332        Element -> [ ?QualifiedName, *PropertyDeclaration, *Binding, *CallbackConnection,
333                     *CallbackDeclaration, *SubElement, *RepeatedElement, *PropertyAnimation,
334                     *TwoWayBinding, *States, *Transitions, ?ChildrenPlaceholder ],
335        RepeatedElement -> [ ?DeclaredIdentifier, ?RepeatedIndex, Expression , SubElement],
336        RepeatedIndex -> [],
337        ConditionalElement -> [ Expression , SubElement],
338        CallbackDeclaration -> [ DeclaredIdentifier, *Type, ?ReturnType, ?TwoWayBinding ],
339        /// `-> type`  (but without the ->)
340        ReturnType -> [Type],
341        CallbackConnection -> [ *DeclaredIdentifier,  CodeBlock ],
342        /// Declaration of a property.
343        PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
344        /// QualifiedName are the properties name
345        PropertyAnimation-> [ *QualifiedName, *Binding ],
346        /// wraps Identifiers, like `Rectangle` or `SomeModule.SomeType`
347        QualifiedName-> [],
348        /// Wraps single identifier (to disambiguate when there are other identifier in the production)
349        DeclaredIdentifier -> [],
350        ChildrenPlaceholder -> [],
351        Binding-> [ BindingExpression ],
352        /// `xxx <=> something`
353        TwoWayBinding -> [ Expression ],
354        /// the right-hand-side of a binding
355        // Fixme: the test should be a or
356        BindingExpression-> [ ?CodeBlock, ?Expression ],
357        CodeBlock-> [ *Expression, *ReturnStatement ],
358        ReturnStatement -> [ ?Expression ],
359        // FIXME: the test should test that as alternative rather than several of them (but it can also be a literal)
360        Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
361                       ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
362                       ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtLinearGradient,
363                       ?MemberAccess ],
364        /// Concatenate the Expressions to make a string (usually expended from a template string)
365        StringTemplate -> [*Expression],
366        /// `@image-url("foo.png")`
367        AtImageUrl -> [],
368        /// `@linear-gradient(...)`
369        AtLinearGradient -> [*Expression],
370        /// expression()
371        FunctionCallExpression -> [*Expression],
372        /// expression[index]
373        IndexExpression -> [2 Expression],
374        /// `expression += expression`
375        SelfAssignment -> [2 Expression],
376        /// `condition ? first : second`
377        ConditionalExpression -> [3 Expression],
378        /// `expr + expr`
379        BinaryExpression -> [2 Expression],
380        /// `- expr`
381        UnaryOpExpression -> [Expression],
382        /// `(foo).bar`, where `foo` is the base expression, and `bar` is a Identifier.
383        MemberAccess -> [Expression],
384        /// `[ ... ]`
385        Array -> [ *Expression ],
386        /// `{ foo: bar }`
387        ObjectLiteral -> [ *ObjectMember ],
388        /// `foo: bar` inside an ObjectLiteral
389        ObjectMember -> [ Expression ],
390        /// `states: [...]`
391        States -> [*State],
392        /// The DeclaredIdentifier is the state name. The Expression, if any, is the condition.
393        State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange],
394        /// binding within a state
395        StatePropertyChange -> [ QualifiedName, BindingExpression ],
396        /// `transitions: [...]`
397        Transitions -> [*Transition],
398        /// There is an identifier "in" or "out", the DeclaredIdentifier is the state name
399        Transition -> [DeclaredIdentifier, *PropertyAnimation],
400        /// Export a set of declared components by name
401        ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration ],
402        /// Declare the first identifier to be exported, either under its name or instead
403        /// under the name of the second identifier.
404        ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
405        ExportIdentifier -> [],
406        ExportName -> [],
407        /// import { foo, bar, baz } from "blah"; The import uri is stored as string literal.
408        ImportSpecifier -> [ ?ImportIdentifierList ],
409        ImportIdentifierList -> [ *ImportIdentifier ],
410        /// { foo as bar } or just { foo }
411        ImportIdentifier -> [ ExternalName, ?InternalName ],
412        ExternalName -> [],
413        InternalName -> [],
414        /// The representation of a type
415        Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
416        /// `{foo: string, bar: string} `
417        ObjectType ->[ *ObjectTypeMember ],
418        /// `foo: type` inside an ObjectType
419        ObjectTypeMember -> [ Type ],
420        /// `[ type ]`
421        ArrayType -> [ Type ],
422        /// `struct Foo := { ... }
423        StructDeclaration -> [DeclaredIdentifier, ObjectType],
424
425    }
426}
427
428impl From<SyntaxKind> for rowan::SyntaxKind {
429    fn from(v: SyntaxKind) -> Self {
430        rowan::SyntaxKind(v.into())
431    }
432}
433
434#[derive(Clone, Debug)]
435pub struct Token {
436    pub kind: SyntaxKind,
437    pub text: SmolStr,
438    pub offset: usize,
439    #[cfg(feature = "proc_macro_span")]
440    pub span: Option<proc_macro::Span>,
441}
442
443impl Default for Token {
444    fn default() -> Self {
445        Token {
446            kind: SyntaxKind::Eof,
447            text: Default::default(),
448            offset: 0,
449            #[cfg(feature = "proc_macro_span")]
450            span: None,
451        }
452    }
453}
454
455impl Token {
456    pub fn as_str(&self) -> &str {
457        self.text.as_str()
458    }
459
460    pub fn kind(&self) -> SyntaxKind {
461        self.kind
462    }
463}
464
465mod parser_trait {
466    //! module allowing to keep implementation details of the node private
467    use super::*;
468
469    pub trait Parser: Sized {
470        type Checkpoint: Clone;
471
472        /// Enter a new node.  The node is going to be finished when
473        /// The return value of this function is dropped
474        ///
475        /// (do not re-implement this function, re-implement
476        /// start_node_impl and finish_node_impl)
477        #[must_use = "The node will be finished when it is dropped"]
478        fn start_node(&mut self, kind: SyntaxKind) -> Node<Self> {
479            self.start_node_impl(kind, None, NodeToken(()));
480            Node(self)
481        }
482        #[must_use = "use start_node_at to use this checkpoint"]
483        fn checkpoint(&mut self) -> Self::Checkpoint;
484        #[must_use = "The node will be finished when it is dropped"]
485        fn start_node_at(&mut self, checkpoint: Self::Checkpoint, kind: SyntaxKind) -> Node<Self> {
486            self.start_node_impl(kind, Some(checkpoint), NodeToken(()));
487            Node(self)
488        }
489
490        /// Can only be called by Node::drop
491        fn finish_node_impl(&mut self, token: NodeToken);
492        /// Can only be called by Self::start_node
493        fn start_node_impl(
494            &mut self,
495            kind: SyntaxKind,
496            checkpoint: Option<Self::Checkpoint>,
497            token: NodeToken,
498        );
499
500        /// Same as nth(0)
501        fn peek(&mut self) -> Token {
502            self.nth(0)
503        }
504        /// Peek the `n`th token, not including whitespace and comments
505        fn nth(&mut self, n: usize) -> Token;
506        fn consume(&mut self);
507        fn error(&mut self, e: impl Into<String>);
508
509        /// Consume the token if it has the right kind, otherwise report a syntax error.
510        /// Returns true if the token was consumed.
511        fn expect(&mut self, kind: SyntaxKind) -> bool {
512            if !self.test(kind) {
513                self.error(format!("Syntax error: expected {}", kind));
514                return false;
515            }
516            true
517        }
518
519        /// If the token if of this type, consume it and return true, otherwise return false
520        fn test(&mut self, kind: SyntaxKind) -> bool {
521            if self.nth(0).kind() != kind {
522                return false;
523            }
524            self.consume();
525            true
526        }
527
528        /// consume everything until reaching a token of this kind
529        fn until(&mut self, kind: SyntaxKind) {
530            // FIXME! match {} () []
531            while {
532                let k = self.nth(0).kind();
533                k != kind && k != SyntaxKind::Eof
534            } {
535                self.consume();
536            }
537            self.expect(kind);
538        }
539    }
540
541    /// A token to proof that start_node_impl and finish_node_impl are only
542    /// called from the Node implementation
543    ///
544    /// Since the constructor is private, it cannot be produced by anything else.
545    pub struct NodeToken(());
546    /// The return value of `DefaultParser::start_node`. This borrows the parser
547    /// and finishes the node on Drop
548    #[derive(derive_more::DerefMut)]
549    pub struct Node<'a, P: Parser>(&'a mut P);
550    impl<'a, P: Parser> Drop for Node<'a, P> {
551        fn drop(&mut self) {
552            self.0.finish_node_impl(NodeToken(()));
553        }
554    }
555    impl<'a, P: Parser> core::ops::Deref for Node<'a, P> {
556        type Target = P;
557        fn deref(&self) -> &Self::Target {
558            self.0
559        }
560    }
561}
562#[doc(inline)]
563pub use parser_trait::*;
564
565pub struct DefaultParser<'a> {
566    builder: rowan::GreenNodeBuilder<'static>,
567    tokens: Vec<Token>,
568    cursor: usize,
569    diags: &'a mut BuildDiagnostics,
570    source_file: SourceFile,
571}
572
573impl<'a> DefaultParser<'a> {
574    fn from_tokens(tokens: Vec<Token>, diags: &'a mut BuildDiagnostics) -> Self {
575        Self {
576            builder: Default::default(),
577            tokens,
578            cursor: 0,
579            diags,
580            source_file: Default::default(),
581        }
582    }
583
584    /// Constructor that create a parser from the source code
585    pub fn new(source: &str, diags: &'a mut BuildDiagnostics) -> Self {
586        Self::from_tokens(crate::lexer::lex(source), diags)
587    }
588
589    fn current_token(&self) -> Token {
590        self.tokens.get(self.cursor).cloned().unwrap_or_default()
591    }
592
593    /// Consume all the whitespace
594    pub fn consume_ws(&mut self) {
595        while matches!(self.current_token().kind, SyntaxKind::Whitespace | SyntaxKind::Comment) {
596            self.consume()
597        }
598    }
599}
600
601impl Parser for DefaultParser<'_> {
602    fn start_node_impl(
603        &mut self,
604        kind: SyntaxKind,
605        checkpoint: Option<Self::Checkpoint>,
606        _: NodeToken,
607    ) {
608        match checkpoint {
609            None => self.builder.start_node(kind.into()),
610            Some(cp) => self.builder.start_node_at(cp, kind.into()),
611        }
612    }
613
614    fn finish_node_impl(&mut self, _: NodeToken) {
615        self.builder.finish_node();
616    }
617
618    /// Peek the `n`th token, not including whitespace and comments
619    fn nth(&mut self, mut n: usize) -> Token {
620        self.consume_ws();
621        let mut c = self.cursor;
622        while n > 0 {
623            n -= 1;
624            c += 1;
625            while c < self.tokens.len()
626                && matches!(self.tokens[c].kind, SyntaxKind::Whitespace | SyntaxKind::Comment)
627            {
628                c += 1;
629            }
630        }
631        self.tokens.get(c).cloned().unwrap_or_default()
632    }
633
634    /// Consume the current token
635    fn consume(&mut self) {
636        let t = self.current_token();
637        self.builder.token(t.kind.into(), t.text.as_str());
638        self.cursor += 1;
639    }
640
641    /// Reports an error at the current token location
642    fn error(&mut self, e: impl Into<String>) {
643        let current_token = self.current_token();
644        #[allow(unused_mut)]
645        let mut span = crate::diagnostics::Span::new(current_token.offset);
646        #[cfg(feature = "proc_macro_span")]
647        {
648            span.span = current_token.span;
649        }
650
651        self.diags.push_error_with_span(
652            e.into(),
653            crate::diagnostics::SourceLocation {
654                source_file: Some(self.source_file.clone()),
655                span,
656            },
657        );
658    }
659
660    type Checkpoint = rowan::Checkpoint;
661    fn checkpoint(&mut self) -> Self::Checkpoint {
662        self.builder.checkpoint()
663    }
664}
665
666#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
667pub enum Language {}
668impl rowan::Language for Language {
669    type Kind = SyntaxKind;
670    fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
671        SyntaxKind::try_from(raw.0).unwrap()
672    }
673    fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
674        kind.into()
675    }
676}
677
678#[derive(Debug, Clone, derive_more::Deref)]
679pub struct SyntaxNode {
680    #[deref]
681    pub node: rowan::SyntaxNode<Language>,
682    pub source_file: SourceFile,
683}
684
685#[derive(Debug, Clone, derive_more::Deref)]
686pub struct SyntaxToken {
687    #[deref]
688    pub token: rowan::SyntaxToken<Language>,
689    pub source_file: SourceFile,
690}
691
692impl SyntaxToken {
693    pub fn parent(&self) -> SyntaxNode {
694        SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
695    }
696}
697
698impl std::fmt::Display for SyntaxToken {
699    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
700        self.token.fmt(f)
701    }
702}
703
704impl SyntaxNode {
705    pub fn child_node(&self, kind: SyntaxKind) -> Option<SyntaxNode> {
706        self.node
707            .children()
708            .find(|n| n.kind() == kind)
709            .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
710    }
711    pub fn child_token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
712        self.node
713            .children_with_tokens()
714            .find(|n| n.kind() == kind)
715            .and_then(|x| x.into_token())
716            .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
717    }
718    pub fn child_text(&self, kind: SyntaxKind) -> Option<String> {
719        self.node
720            .children_with_tokens()
721            .find(|n| n.kind() == kind)
722            .and_then(|x| x.as_token().map(|x| x.text().to_string()))
723    }
724    pub fn kind(&self) -> SyntaxKind {
725        self.node.kind()
726    }
727    pub fn children(&self) -> impl Iterator<Item = SyntaxNode> {
728        let source_file = self.source_file.clone();
729        self.node.children().map(move |node| SyntaxNode { node, source_file: source_file.clone() })
730    }
731    pub fn children_with_tokens(&self) -> impl Iterator<Item = NodeOrToken> {
732        let source_file = self.source_file.clone();
733        self.node.children_with_tokens().map(move |token| match token {
734            rowan::NodeOrToken::Node(node) => {
735                SyntaxNode { node, source_file: source_file.clone() }.into()
736            }
737            rowan::NodeOrToken::Token(token) => {
738                SyntaxToken { token, source_file: source_file.clone() }.into()
739            }
740        })
741    }
742    pub fn text(&self) -> rowan::SyntaxText {
743        self.node.text()
744    }
745    pub fn parent(&self) -> Option<SyntaxNode> {
746        self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
747    }
748}
749
750#[derive(Debug, Clone, derive_more::From)]
751pub enum NodeOrToken {
752    Node(SyntaxNode),
753    Token(SyntaxToken),
754}
755
756impl NodeOrToken {
757    pub fn kind(&self) -> SyntaxKind {
758        match self {
759            NodeOrToken::Node(n) => n.kind(),
760            NodeOrToken::Token(t) => t.kind(),
761        }
762    }
763
764    pub fn as_node(&self) -> Option<&SyntaxNode> {
765        match self {
766            NodeOrToken::Node(n) => Some(n),
767            NodeOrToken::Token(_) => None,
768        }
769    }
770
771    pub fn as_token(&self) -> Option<&SyntaxToken> {
772        match self {
773            NodeOrToken::Node(_) => None,
774            NodeOrToken::Token(t) => Some(t),
775        }
776    }
777
778    pub fn into_token(self) -> Option<SyntaxToken> {
779        match self {
780            NodeOrToken::Token(t) => Some(t),
781            _ => None,
782        }
783    }
784
785    pub fn into_node(self) -> Option<SyntaxNode> {
786        match self {
787            NodeOrToken::Node(n) => Some(n),
788            _ => None,
789        }
790    }
791}
792
793impl Spanned for SyntaxNode {
794    fn span(&self) -> crate::diagnostics::Span {
795        crate::diagnostics::Span::new(self.node.text_range().start().into())
796    }
797
798    fn source_file(&self) -> Option<&SourceFile> {
799        Some(&self.source_file)
800    }
801}
802
803impl Spanned for Option<SyntaxNode> {
804    fn span(&self) -> crate::diagnostics::Span {
805        self.as_ref().map(|n| n.span()).unwrap_or_default()
806    }
807
808    fn source_file(&self) -> Option<&SourceFile> {
809        self.as_ref().and_then(|n| n.source_file())
810    }
811}
812
813impl Spanned for SyntaxToken {
814    fn span(&self) -> crate::diagnostics::Span {
815        crate::diagnostics::Span::new(self.token.text_range().start().into())
816    }
817
818    fn source_file(&self) -> Option<&SourceFile> {
819        Some(&self.source_file)
820    }
821}
822
823impl Spanned for NodeOrToken {
824    fn span(&self) -> crate::diagnostics::Span {
825        match self {
826            NodeOrToken::Node(n) => n.span(),
827            NodeOrToken::Token(t) => t.span(),
828        }
829    }
830
831    fn source_file(&self) -> Option<&SourceFile> {
832        match self {
833            NodeOrToken::Node(n) => n.source_file(),
834            NodeOrToken::Token(t) => t.source_file(),
835        }
836    }
837}
838
839impl Spanned for Option<NodeOrToken> {
840    fn span(&self) -> crate::diagnostics::Span {
841        self.as_ref().map(|t| t.span()).unwrap_or_default()
842    }
843    fn source_file(&self) -> Option<&SourceFile> {
844        self.as_ref().and_then(|t| t.source_file())
845    }
846}
847
848impl Spanned for Option<SyntaxToken> {
849    fn span(&self) -> crate::diagnostics::Span {
850        self.as_ref().map(|t| t.span()).unwrap_or_default()
851    }
852    fn source_file(&self) -> Option<&SourceFile> {
853        self.as_ref().and_then(|t| t.source_file())
854    }
855}
856
857/// return the normalized identifier string of the first SyntaxKind::Identifier in this node
858pub fn identifier_text(node: &SyntaxNode) -> Option<String> {
859    node.child_text(SyntaxKind::Identifier).map(|x| normalize_identifier(&x))
860}
861
862pub fn normalize_identifier(ident: &str) -> String {
863    ident.replace('_', "-")
864}
865
866// Actual parser
867pub fn parse(
868    source: String,
869    path: Option<&std::path::Path>,
870    build_diagnostics: &mut BuildDiagnostics,
871) -> SyntaxNode {
872    let mut p = DefaultParser::new(&source, build_diagnostics);
873    let source_file = if let Some(path) = path {
874        p.source_file =
875            std::rc::Rc::new(crate::diagnostics::SourceFileInner::new(path.to_path_buf(), source));
876        p.source_file.clone()
877    } else {
878        Default::default()
879    };
880    document::parse_document(&mut p);
881    SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
882}
883
884pub fn parse_file<P: AsRef<std::path::Path>>(
885    path: P,
886    build_diagnostics: &mut BuildDiagnostics,
887) -> Option<SyntaxNode> {
888    let source = crate::diagnostics::load_from_path(path.as_ref())
889        .map_err(|d| build_diagnostics.push_internal_error(d))
890        .ok()?;
891    Some(parse(source, Some(path.as_ref()), build_diagnostics))
892}
893
894pub fn parse_tokens(
895    tokens: Vec<Token>,
896    source_file: SourceFile,
897    diags: &mut BuildDiagnostics,
898) -> SyntaxNode {
899    let mut p = DefaultParser::from_tokens(tokens, diags);
900    document::parse_document(&mut p);
901    SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
902}