Skip to main content

i_slint_compiler/
parser.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4/*! The Slint 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};
16use smol_str::SmolStr;
17use std::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::DefaultParser;
29    pub use super::{Parser, SyntaxKind};
30    #[cfg(test)]
31    pub use super::{SyntaxNode, SyntaxNodeVerify, syntax_nodes};
32    #[cfg(test)]
33    pub use i_slint_parser_test_macro::parser_test;
34}
35
36#[cfg(test)]
37pub trait SyntaxNodeVerify {
38    /// The SyntaxKind corresponding to this type
39    const KIND: SyntaxKind;
40    /// Asserts that the node is of the given SyntaxKind and that it has the expected children
41    /// Panic if this is not the case
42    fn verify(node: SyntaxNode) {
43        assert_eq!(node.kind(), Self::KIND)
44    }
45}
46
47pub use rowan::{TextRange, TextSize};
48
49/// Check that a node has the assumed children
50#[cfg(test)]
51macro_rules! verify_node {
52    // Some combination of children
53    ($node:ident, [ $($t1:tt $($t2:ident)?),* ]) => {
54        // Check that every children is there
55        $(verify_node!(@check_has_children $node, $t1 $($t2)* );)*
56
57        // check that there are not too many nodes
58        for c in $node.children() {
59            assert!(
60                false $(|| c.kind() == verify_node!(@extract_kind $t1 $($t2)*))*,
61                "Node is none of [{}]\n{:?}", stringify!($($t1 $($t2)*),*) ,c);
62        }
63
64        // recurse
65        $(
66            for _c in $node.children().filter(|n| n.kind() == verify_node!(@extract_kind $t1 $($t2)*)) {
67                <verify_node!(@extract_type $t1 $($t2)*)>::verify(_c)
68            }
69        )*
70    };
71
72    // Any number of this kind.
73    (@check_has_children $node:ident, * $kind:ident) => {};
74    // 1 or 0
75    (@check_has_children $node:ident, ? $kind:ident) => {
76        let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
77        assert!(count <= 1, "Expecting one or zero sub-node of type {}, found {}\n{:?}", stringify!($kind), count, $node);
78    };
79    // Exactly one
80    (@check_has_children $node:ident, $kind:ident) => {
81        let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
82        assert_eq!(count, 1, "Expecting exactly one sub-node of type {}\n{:?}", stringify!($kind), $node);
83    };
84    // Exact number
85    (@check_has_children $node:ident, $count:literal $kind:ident) => {
86        let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
87        assert_eq!(count, $count, "Expecting {} sub-node of type {}, found {}\n{:?}", $count, stringify!($kind), count, $node);
88    };
89
90    (@extract_kind * $kind:ident) => {SyntaxKind::$kind};
91    (@extract_kind ? $kind:ident) => {SyntaxKind::$kind};
92    (@extract_kind $count:literal $kind:ident) => {SyntaxKind::$kind};
93    (@extract_kind $kind:ident) => {SyntaxKind::$kind};
94
95    (@extract_type * $kind:ident) => {$crate::parser::syntax_nodes::$kind};
96    (@extract_type ? $kind:ident) => {$crate::parser::syntax_nodes::$kind};
97    (@extract_type $count:literal $kind:ident) => {$crate::parser::syntax_nodes::$kind};
98    (@extract_type $kind:ident) => {$crate::parser::syntax_nodes::$kind};
99}
100
101macro_rules! node_accessors {
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> + use<> {
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        #[track_caller]
122        pub fn $kind(&self) -> ($kind, $kind) {
123            let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
124            let a = it.next().expect(stringify!(Missing first $kind));
125            let b = it.next().expect(stringify!(Missing second $kind));
126            debug_assert!(it.next().is_none(), stringify!(More $kind than expected));
127            (a.into(), b.into())
128        }
129    };
130    (@ 3 $kind:ident) => {
131        #[allow(non_snake_case)]
132        #[track_caller]
133        pub fn $kind(&self) -> ($kind, $kind, $kind) {
134            let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
135            let a = it.next().expect(stringify!(Missing first $kind));
136            let b = it.next().expect(stringify!(Missing second $kind));
137            let c = it.next().expect(stringify!(Missing third $kind));
138            debug_assert!(it.next().is_none(), stringify!(More $kind than expected));
139            (a.into(), b.into(), c.into())
140        }
141    };
142    (@ $kind:ident) => {
143        #[allow(non_snake_case)]
144        #[track_caller]
145        pub fn $kind(&self) -> $kind {
146            self.0.child_node(SyntaxKind::$kind).expect(stringify!(Missing $kind)).into()
147        }
148    };
149
150}
151
152/// This macro is invoked once, to declare all the token and syntax kind.
153/// The purpose of this macro is to declare the token with its regexp at the same place,
154/// and the nodes with their contents.
155///
156/// This is split into two group: first the tokens, then the nodes.
157///
158/// # Tokens
159///
160/// Given as `$token:ident -> $rule:expr`. The rule parameter can be either a string literal or
161/// a lexer function. The order of tokens is important because the rules will be run in that order
162/// and the first one matching will be chosen.
163///
164/// # Nodes
165///
166/// Given as `$(#[$attr:meta])* $nodekind:ident -> [$($children:tt),*] `.
167/// Where `children` is a list of sub-nodes (not including tokens).
168/// This will allow to self-document and create the structure from the [`syntax_nodes`] module.
169/// The children can be prefixed with the following symbol:
170///
171/// - nothing: The node occurs once and exactly once, the generated accessor returns the node itself
172/// - `+`: the node occurs one or several times, the generated accessor returns an `Iterator`
173/// - `*`: the node occurs zero or several times, the generated accessor returns an `Iterator`
174/// - `?`: the node occurs once or zero times, the generated accessor returns an `Option`
175/// - `2` or `3`: the node occurs exactly two or three times, the generated accessor returns a tuple
176///
177/// Note: the parser must generate the right amount of sub nodes, even if there is a parse error.
178///
179/// ## The [`syntax_nodes`] module
180///
181/// Creates one struct for every node with the given accessor.
182/// The struct can be converted from and to the node.
183macro_rules! declare_syntax {
184    ({
185        $($token:ident -> $rule:expr ,)*
186     }
187     {
188        $( $(#[$attr:meta])*  $nodekind:ident -> $children:tt ,)*
189    })
190    => {
191        #[repr(u16)]
192        #[derive(Debug, Copy, Clone, Eq, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive, Hash, Ord, PartialOrd)]
193        pub enum SyntaxKind {
194            Error,
195            Eof,
196
197            // Tokens:
198            $(
199                /// Token
200                $token,
201            )*
202
203            // Nodes:
204            $(
205                $(#[$attr])*
206                $nodekind,
207            )*
208        }
209
210        impl Display for SyntaxKind {
211            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212                match self {
213                    $(Self::$token => {
214                        if let Some(character) = <dyn std::any::Any>::downcast_ref::<&str>(& $rule) {
215                            return write!(f, "'{}'", character)
216                        }
217                    })*
218                    _ => ()
219                }
220                write!(f, "{:?}", self)
221            }
222        }
223
224
225        /// Returns a pair of the matched token type at the beginning of `text`, and its size
226        pub fn lex_next_token(text : &str, state: &mut crate::lexer::LexState) -> Option<(usize, SyntaxKind)> {
227            use crate::lexer::LexingRule;
228            $(
229                let len = ($rule).lex(text, state);
230                if len > 0 {
231                    return Some((len, SyntaxKind::$token));
232                }
233            )*
234            None
235        }
236
237        pub mod syntax_nodes {
238            use super::*;
239            $(
240                #[derive(Debug, Clone, derive_more::Deref, derive_more::Into)]
241                pub struct $nodekind(SyntaxNode);
242                #[cfg(test)]
243                impl SyntaxNodeVerify for $nodekind {
244                    const KIND: SyntaxKind = SyntaxKind::$nodekind;
245                    #[track_caller]
246                    fn verify(node: SyntaxNode) {
247                        assert_eq!(node.kind(), Self::KIND);
248                        verify_node!(node, $children);
249                    }
250                }
251                impl $nodekind {
252                    node_accessors!{$children}
253
254                    /// Create a new node from a SyntaxNode, if the SyntaxNode is of the correct kind
255                    pub fn new(node: SyntaxNode) -> Option<Self> {
256                        (node.kind() == SyntaxKind::$nodekind).then(|| Self(node))
257                    }
258                }
259
260                impl From<SyntaxNode> for $nodekind {
261                    #[track_caller]
262                    fn from(node: SyntaxNode) -> Self {
263                        assert_eq!(node.kind(), SyntaxKind::$nodekind);
264                        Self(node)
265                    }
266                }
267
268                impl Spanned for $nodekind {
269                    fn span(&self) -> crate::diagnostics::Span {
270                        self.0.span()
271                    }
272
273                    fn source_file(&self) -> Option<&SourceFile> {
274                        self.0.source_file()
275                    }
276                }
277            )*
278        }
279    }
280}
281declare_syntax! {
282    // Tokens.
283    // WARNING: when changing this, do not forget to update the tokenizer in the slint-rs-macro crate!
284    // The order of token is important because the rules will be run in that order
285    // and the first one matching will be chosen.
286    {
287        Whitespace -> &crate::lexer::lex_whitespace,
288        Comment -> &crate::lexer::lex_comment,
289        StringLiteral -> &crate::lexer::lex_string,
290        NumberLiteral -> &crate::lexer::lex_number,
291        ColorLiteral -> &crate::lexer::lex_color,
292        Identifier -> &crate::lexer::lex_identifier,
293        DoubleArrow -> "<=>",
294        PlusEqual -> "+=",
295        MinusEqual -> "-=",
296        StarEqual -> "*=",
297        DivEqual -> "/=",
298        LessEqual -> "<=",
299        GreaterEqual -> ">=",
300        EqualEqual -> "==",
301        NotEqual -> "!=",
302        ColonEqual -> ":=",
303        FatArrow -> "=>",
304        Arrow -> "->",
305        OrOr -> "||",
306        AndAnd -> "&&",
307        LBrace -> "{",
308        RBrace -> "}",
309        LParent -> "(",
310        RParent -> ")",
311        LAngle -> "<",
312        RAngle -> ">",
313        LBracket -> "[",
314        RBracket -> "]",
315        Plus -> "+",
316        Minus -> "-",
317        Star -> "*",
318        Div -> "/",
319        Equal -> "=",
320        Colon -> ":",
321        Comma -> ",",
322        Semicolon -> ";",
323        Bang -> "!",
324        Dot -> ".",
325        Question -> "?",
326        Dollar -> "$",
327        At -> "@",
328        Pipe -> "|",
329        Percent -> "%",
330    }
331    // Syntax Nodes. The list after the `->` is the possible child nodes,
332    // see the documentation of `declare_syntax!` macro for details.
333    {
334        Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration, *EnumDeclaration ],
335        /// `DeclaredIdentifier := Element { ... }`
336        Component -> [ DeclaredIdentifier, ?UsesSpecifier, ?ImplementsSpecifier, Element ],
337        /// `id := Element { ... }`
338        SubElement -> [ Element ],
339        Element -> [ ?QualifiedName, *PropertyDeclaration, *Binding, *CallbackConnection,
340                     *CallbackDeclaration, *ConditionalElement, *Function, *SubElement,
341                     *RepeatedElement, *PropertyAnimation, *PropertyChangedCallback,
342                     *TwoWayBinding, *States, *Transitions, ?ChildrenPlaceholder ],
343        RepeatedElement -> [ ?DeclaredIdentifier, ?RepeatedIndex, Expression , SubElement],
344        RepeatedIndex -> [],
345        ConditionalElement -> [ Expression , SubElement],
346        CallbackDeclaration -> [ DeclaredIdentifier, *CallbackDeclarationParameter, ?ReturnType, ?TwoWayBinding ],
347        // `foo: type` or just `type`
348        CallbackDeclarationParameter -> [ ?DeclaredIdentifier, Type],
349        Function -> [DeclaredIdentifier, *ArgumentDeclaration, ?ReturnType, ?CodeBlock ],
350        ArgumentDeclaration -> [DeclaredIdentifier, Type],
351        /// `-> type`  (but without the ->)
352        ReturnType -> [Type],
353        CallbackConnection -> [ *DeclaredIdentifier, ?CodeBlock, ?Expression ],
354        /// Declaration of a property.
355        PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
356        /// QualifiedName are the properties name
357        PropertyAnimation-> [ *QualifiedName, *Binding ],
358        /// `changed xxx => {...}`  where `xxx` is the DeclaredIdentifier
359        PropertyChangedCallback-> [ DeclaredIdentifier, ?CodeBlock, ?Expression ],
360        /// wraps Identifiers, like `Rectangle` or `SomeModule.SomeType`
361        QualifiedName-> [],
362        /// Wraps single identifier (to disambiguate when there are other identifier in the production)
363        DeclaredIdentifier -> [],
364        ChildrenPlaceholder -> [],
365        Binding-> [ BindingExpression ],
366        /// `xxx <=> something`
367        TwoWayBinding -> [ Expression ],
368        /// the right-hand-side of a binding
369        // Fixme: the test should be a or
370        BindingExpression-> [ ?CodeBlock, ?Expression ],
371        CodeBlock-> [ *Expression, *LetStatement, *ReturnStatement ],
372        LetStatement -> [ DeclaredIdentifier, ?Type, Expression ],
373        ReturnStatement -> [ ?Expression ],
374        // FIXME: the test should test that as alternative rather than several of them (but it can also be a literal)
375        Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
376                       ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
377                       ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtGradient, ?AtTr,
378                       ?MemberAccess, ?AtKeys ],
379        /// Concatenate the children Expressions and StringLiteral to make a string
380        StringTemplate -> [*Expression],
381        /// `@image-url("foo.png")`
382        AtImageUrl -> [],
383        /// `@linear-gradient(...)` or `@radial-gradient(...)`
384        AtGradient -> [*Expression],
385        /// `@tr("foo", ...)`  // the string is a StringLiteral
386        AtTr -> [?TrContext, ?TrPlural, *Expression],
387        AtMarkdown -> [*Expression],
388        /// `"foo" =>`  in a `AtTr` node
389        TrContext -> [],
390        /// `| "foo" % n`  in a `AtTr` node
391        TrPlural -> [Expression],
392        /// `@keys(...)`
393        AtKeys -> [],
394        /// expression()
395        FunctionCallExpression -> [*Expression],
396        /// `expression[index]`
397        IndexExpression -> [2 Expression],
398        /// `expression += expression`
399        SelfAssignment -> [2 Expression],
400        /// `condition ? first : second`
401        ConditionalExpression -> [3 Expression],
402        /// `expr + expr`
403        BinaryExpression -> [2 Expression],
404        /// `- expr`
405        UnaryOpExpression -> [Expression],
406        /// `(foo).bar`, where `foo` is the base expression, and `bar` is a Identifier.
407        MemberAccess -> [Expression],
408        /// `[ ... ]`
409        Array -> [ *Expression ],
410        /// `{ foo: bar }`
411        ObjectLiteral -> [ *ObjectMember ],
412        /// `foo: bar` inside an ObjectLiteral
413        ObjectMember -> [ Expression ],
414        /// `states: [...]`
415        States -> [*State],
416        /// The DeclaredIdentifier is the state name. The Expression, if any, is the condition.
417        State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange, *Transition],
418        /// binding within a state
419        StatePropertyChange -> [ QualifiedName, BindingExpression ],
420        /// `transitions: [...]`
421        Transitions -> [*Transition],
422        /// There is an identifier "in", "out", "in-out", the DeclaredIdentifier is the state name
423        Transition -> [?DeclaredIdentifier, *PropertyAnimation],
424        /// Export a set of declared components by name
425        ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration, ?ExportModule, *EnumDeclaration ],
426        /// Declare the first identifier to be exported, either under its name or instead
427        /// under the name of the second identifier.
428        ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
429        ExportIdentifier -> [],
430        ExportName -> [],
431        /// `export ... from "foo"`. The import uri is stored as string literal.
432        ExportModule -> [],
433        /// import { foo, bar, baz } from "blah"; The import uri is stored as string literal.
434        ImportSpecifier -> [ ?ImportIdentifierList ],
435        ImportIdentifierList -> [ *ImportIdentifier ],
436        /// { foo as bar } or just { foo }
437        ImportIdentifier -> [ ExternalName, ?InternalName ],
438        ExternalName -> [],
439        InternalName -> [],
440        /// The representation of a type
441        Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
442        /// `{foo: string, bar: string} `
443        ObjectType ->[ *ObjectTypeMember ],
444        /// `foo: type` inside an ObjectType
445        ObjectTypeMember -> [ Type ],
446        /// `[ type ]`
447        ArrayType -> [ Type ],
448        /// `struct Foo { ... }`
449        StructDeclaration -> [DeclaredIdentifier, ObjectType, *AtRustAttr],
450        /// `enum Foo { bli, bla, blu }`
451        EnumDeclaration -> [DeclaredIdentifier, *EnumValue, *AtRustAttr],
452        /// The value is a Identifier
453        EnumValue -> [],
454        /// `@rust-attr(...)`
455        AtRustAttr -> [],
456        /// `uses { Foo from Bar, Baz from Qux }`
457        UsesSpecifier -> [ *UsesIdentifier ],
458        /// `Interface.Foo from bar`
459        UsesIdentifier -> [QualifiedName, DeclaredIdentifier],
460        /// `implements Interface.Foo`
461        ImplementsSpecifier -> [ QualifiedName ],
462    }
463}
464
465impl From<SyntaxKind> for rowan::SyntaxKind {
466    fn from(v: SyntaxKind) -> Self {
467        rowan::SyntaxKind(v.into())
468    }
469}
470
471#[derive(Clone, Debug)]
472pub struct Token {
473    pub kind: SyntaxKind,
474    pub text: SmolStr,
475    pub offset: usize,
476    pub length: usize,
477    #[cfg(feature = "proc_macro_span")]
478    pub span: Option<proc_macro::Span>,
479}
480
481impl Default for Token {
482    fn default() -> Self {
483        Token {
484            kind: SyntaxKind::Eof,
485            text: Default::default(),
486            offset: 0,
487            length: 0,
488            #[cfg(feature = "proc_macro_span")]
489            span: None,
490        }
491    }
492}
493
494impl Token {
495    pub fn as_str(&self) -> &str {
496        self.text.as_str()
497    }
498
499    pub fn kind(&self) -> SyntaxKind {
500        self.kind
501    }
502}
503
504mod parser_trait {
505    //! module allowing to keep implementation details of the node private
506    use super::*;
507
508    pub trait Parser: Sized {
509        type Checkpoint: Clone;
510
511        /// Enter a new node.  The node is going to be finished when
512        /// The return value of this function is dropped
513        ///
514        /// (do not re-implement this function, re-implement
515        /// start_node_impl and finish_node_impl)
516        #[must_use = "The node will be finished when it is dropped"]
517        fn start_node(&mut self, kind: SyntaxKind) -> Node<'_, Self> {
518            self.start_node_impl(kind, None, NodeToken(()));
519            Node(self)
520        }
521        #[must_use = "use start_node_at to use this checkpoint"]
522        fn checkpoint(&mut self) -> Self::Checkpoint;
523        #[must_use = "The node will be finished when it is dropped"]
524        fn start_node_at(
525            &mut self,
526            checkpoint: impl Into<Option<Self::Checkpoint>>,
527            kind: SyntaxKind,
528        ) -> Node<'_, Self> {
529            self.start_node_impl(kind, checkpoint.into(), NodeToken(()));
530            Node(self)
531        }
532
533        /// Can only be called by Node::drop
534        fn finish_node_impl(&mut self, token: NodeToken);
535        /// Can only be called by Self::start_node
536        fn start_node_impl(
537            &mut self,
538            kind: SyntaxKind,
539            checkpoint: Option<Self::Checkpoint>,
540            token: NodeToken,
541        );
542
543        /// Same as nth(0)
544        fn peek(&mut self) -> Token {
545            self.nth(0)
546        }
547        /// Peek the `n`th token, not including whitespace and comments
548        fn nth(&mut self, n: usize) -> Token;
549        /// Consume the token and point to the next token
550        fn consume(&mut self);
551        fn error(&mut self, e: impl Into<String>);
552        fn warning(&mut self, e: impl Into<String>);
553
554        /// Consume the token if it has the right kind, otherwise report a syntax error.
555        /// Returns true if the token was consumed.
556        fn expect(&mut self, kind: SyntaxKind) -> bool {
557            if !self.test(kind) {
558                self.error(format!("Syntax error: expected {kind}"));
559                return false;
560            }
561            true
562        }
563
564        /// If the token if of this type, consume it and return true, otherwise return false
565        fn test(&mut self, kind: SyntaxKind) -> bool {
566            if self.nth(0).kind() != kind {
567                return false;
568            }
569            self.consume();
570            true
571        }
572
573        /// consume everything until reaching a token of this kind
574        fn until(&mut self, kind: SyntaxKind) {
575            let mut parens = 0;
576            let mut braces = 0;
577            let mut brackets = 0;
578            loop {
579                match self.nth(0).kind() {
580                    k if k == kind && parens == 0 && braces == 0 && brackets == 0 => break,
581                    SyntaxKind::Eof => break,
582                    SyntaxKind::LParent => parens += 1,
583                    SyntaxKind::LBrace => braces += 1,
584                    SyntaxKind::LBracket => brackets += 1,
585                    SyntaxKind::RParent if parens == 0 => break,
586                    SyntaxKind::RParent => parens -= 1,
587                    SyntaxKind::RBrace if braces == 0 => break,
588                    SyntaxKind::RBrace => braces -= 1,
589                    SyntaxKind::RBracket if brackets == 0 => break,
590                    SyntaxKind::RBracket => brackets -= 1,
591                    _ => {}
592                };
593                self.consume();
594            }
595            self.expect(kind);
596        }
597    }
598
599    /// A token to proof that start_node_impl and finish_node_impl are only
600    /// called from the Node implementation
601    ///
602    /// Since the constructor is private, it cannot be produced by anything else.
603    pub struct NodeToken(());
604    /// The return value of `DefaultParser::start_node`. This borrows the parser
605    /// and finishes the node on Drop
606    #[derive(derive_more::DerefMut)]
607    pub struct Node<'a, P: Parser>(&'a mut P);
608    impl<P: Parser> Drop for Node<'_, P> {
609        fn drop(&mut self) {
610            self.0.finish_node_impl(NodeToken(()));
611        }
612    }
613    impl<P: Parser> core::ops::Deref for Node<'_, P> {
614        type Target = P;
615        fn deref(&self) -> &Self::Target {
616            self.0
617        }
618    }
619}
620#[doc(inline)]
621pub use parser_trait::*;
622
623pub struct DefaultParser<'a> {
624    builder: rowan::GreenNodeBuilder<'static>,
625    /// tokens from the lexer
626    tokens: Vec<Token>,
627    /// points on the current token of the token list
628    cursor: usize,
629    diags: &'a mut BuildDiagnostics,
630    source_file: SourceFile,
631}
632
633impl<'a> DefaultParser<'a> {
634    fn from_tokens(tokens: Vec<Token>, diags: &'a mut BuildDiagnostics) -> Self {
635        Self {
636            builder: Default::default(),
637            tokens,
638            cursor: 0,
639            diags,
640            source_file: Default::default(),
641        }
642    }
643
644    /// Constructor that create a parser from the source code.
645    /// It creates the tokens by lexing the code
646    pub fn new(source: &str, diags: &'a mut BuildDiagnostics) -> Self {
647        Self::from_tokens(crate::lexer::lex(source), diags)
648    }
649
650    fn current_token(&self) -> Token {
651        self.tokens.get(self.cursor).cloned().unwrap_or_default()
652    }
653
654    /// Consume all the whitespace
655    pub fn consume_ws(&mut self) {
656        while matches!(self.current_token().kind, SyntaxKind::Whitespace | SyntaxKind::Comment) {
657            self.consume()
658        }
659    }
660}
661
662impl Parser for DefaultParser<'_> {
663    fn start_node_impl(
664        &mut self,
665        kind: SyntaxKind,
666        checkpoint: Option<Self::Checkpoint>,
667        _: NodeToken,
668    ) {
669        if kind != SyntaxKind::Document {
670            self.consume_ws();
671        }
672        match checkpoint {
673            None => self.builder.start_node(kind.into()),
674            Some(cp) => self.builder.start_node_at(cp, kind.into()),
675        }
676    }
677
678    fn finish_node_impl(&mut self, _: NodeToken) {
679        self.builder.finish_node();
680    }
681
682    /// Peek the `n`th token starting from the cursor position, not including whitespace and comments
683    fn nth(&mut self, mut n: usize) -> Token {
684        self.consume_ws();
685        let mut c = self.cursor;
686        while n > 0 {
687            n -= 1;
688            c += 1;
689            while c < self.tokens.len()
690                && matches!(self.tokens[c].kind, SyntaxKind::Whitespace | SyntaxKind::Comment)
691            {
692                c += 1;
693            }
694        }
695        self.tokens.get(c).cloned().unwrap_or_default()
696    }
697
698    /// Adds the current token to the node builder and increments the cursor to point on the next token
699    fn consume(&mut self) {
700        let t = self.current_token();
701        self.builder.token(t.kind.into(), t.text.as_str());
702        if t.kind != SyntaxKind::Eof {
703            self.cursor += 1;
704        }
705    }
706
707    /// Reports an error at the current token location
708    fn error(&mut self, e: impl Into<String>) {
709        let current_token = self.current_token();
710        #[allow(unused_mut)]
711        let mut span = crate::diagnostics::Span::new(current_token.offset, current_token.length);
712        #[cfg(feature = "proc_macro_span")]
713        {
714            span.span = current_token.span;
715        }
716
717        self.diags.push_error_with_span(
718            e.into(),
719            crate::diagnostics::SourceLocation {
720                source_file: Some(self.source_file.clone()),
721                span,
722            },
723        );
724    }
725
726    /// Reports an error at the current token location
727    fn warning(&mut self, e: impl Into<String>) {
728        let current_token = self.current_token();
729        #[allow(unused_mut)]
730        let mut span = crate::diagnostics::Span::new(current_token.offset, current_token.length);
731        #[cfg(feature = "proc_macro_span")]
732        {
733            span.span = current_token.span;
734        }
735
736        self.diags.push_warning_with_span(
737            e.into(),
738            crate::diagnostics::SourceLocation {
739                source_file: Some(self.source_file.clone()),
740                span,
741            },
742        );
743    }
744
745    type Checkpoint = rowan::Checkpoint;
746    fn checkpoint(&mut self) -> Self::Checkpoint {
747        self.builder.checkpoint()
748    }
749}
750
751#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
752pub enum Language {}
753impl rowan::Language for Language {
754    type Kind = SyntaxKind;
755    fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
756        SyntaxKind::try_from(raw.0).unwrap()
757    }
758    fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
759        kind.into()
760    }
761}
762
763#[derive(Debug, Clone, derive_more::Deref)]
764pub struct SyntaxNode {
765    #[deref]
766    pub node: rowan::SyntaxNode<Language>,
767    pub source_file: SourceFile,
768}
769
770#[derive(Debug, Clone, derive_more::Deref)]
771pub struct SyntaxToken {
772    #[deref]
773    pub token: rowan::SyntaxToken<Language>,
774    pub source_file: SourceFile,
775}
776
777impl SyntaxToken {
778    pub fn parent(&self) -> SyntaxNode {
779        SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
780    }
781    pub fn parent_ancestors(&self) -> impl Iterator<Item = SyntaxNode> + '_ {
782        self.token
783            .parent_ancestors()
784            .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
785    }
786    pub fn next_token(&self) -> Option<SyntaxToken> {
787        // Due to a bug (as of rowan 0.15.3), rowan::SyntaxToken::next_token doesn't work if a
788        // sibling don't have tokens.
789        // For example, if we have an expression like  `if (true) {}`  the
790        // ConditionalExpression has an empty Expression/CodeBlock  for the else part,
791        // and next_token doesn't go into that.
792        // So re-implement
793
794        let token = self
795            .token
796            .next_sibling_or_token()
797            .and_then(|e| match e {
798                rowan::NodeOrToken::Node(n) => n.first_token(),
799                rowan::NodeOrToken::Token(t) => Some(t),
800            })
801            .or_else(|| {
802                self.token.parent_ancestors().find_map(|it| it.next_sibling_or_token()).and_then(
803                    |e| match e {
804                        rowan::NodeOrToken::Node(n) => n.first_token(),
805                        rowan::NodeOrToken::Token(t) => Some(t),
806                    },
807                )
808            })?;
809        Some(SyntaxToken { token, source_file: self.source_file.clone() })
810    }
811    pub fn prev_token(&self) -> Option<SyntaxToken> {
812        let token = self.token.prev_token()?;
813        Some(SyntaxToken { token, source_file: self.source_file.clone() })
814    }
815    pub fn text(&self) -> &str {
816        self.token.text()
817    }
818}
819
820impl std::fmt::Display for SyntaxToken {
821    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
822        self.token.fmt(f)
823    }
824}
825
826impl SyntaxNode {
827    pub fn child_node(&self, kind: SyntaxKind) -> Option<SyntaxNode> {
828        self.node
829            .children()
830            .find(|n| n.kind() == kind)
831            .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
832    }
833    pub fn child_token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
834        self.node
835            .children_with_tokens()
836            .find(|n| n.kind() == kind)
837            .and_then(|x| x.into_token())
838            .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
839    }
840    pub fn child_text(&self, kind: SyntaxKind) -> Option<SmolStr> {
841        self.node
842            .children_with_tokens()
843            .find(|n| n.kind() == kind)
844            .and_then(|x| x.as_token().map(|x| x.text().into()))
845    }
846    pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> + use<> {
847        let source_file = self.source_file.clone();
848        self.node
849            .descendants()
850            .map(move |node| SyntaxNode { node, source_file: source_file.clone() })
851    }
852    pub fn kind(&self) -> SyntaxKind {
853        self.node.kind()
854    }
855    pub fn children(&self) -> impl Iterator<Item = SyntaxNode> + use<> {
856        let source_file = self.source_file.clone();
857        self.node.children().map(move |node| SyntaxNode { node, source_file: source_file.clone() })
858    }
859    pub fn children_with_tokens(&self) -> impl Iterator<Item = NodeOrToken> + use<> {
860        let source_file = self.source_file.clone();
861        self.node.children_with_tokens().map(move |token| match token {
862            rowan::NodeOrToken::Node(node) => {
863                SyntaxNode { node, source_file: source_file.clone() }.into()
864            }
865            rowan::NodeOrToken::Token(token) => {
866                SyntaxToken { token, source_file: source_file.clone() }.into()
867            }
868        })
869    }
870    pub fn text(&self) -> rowan::SyntaxText {
871        self.node.text()
872    }
873    pub fn parent(&self) -> Option<SyntaxNode> {
874        self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
875    }
876    pub fn first_token(&self) -> Option<SyntaxToken> {
877        self.node
878            .first_token()
879            .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
880    }
881    pub fn last_token(&self) -> Option<SyntaxToken> {
882        self.node
883            .last_token()
884            .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
885    }
886    pub fn token_at_offset(&self, offset: TextSize) -> rowan::TokenAtOffset<SyntaxToken> {
887        self.node
888            .token_at_offset(offset)
889            .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
890    }
891    pub fn first_child(&self) -> Option<SyntaxNode> {
892        self.node
893            .first_child()
894            .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
895    }
896    pub fn first_child_or_token(&self) -> Option<NodeOrToken> {
897        self.node.first_child_or_token().map(|n_o_t| match n_o_t {
898            rowan::NodeOrToken::Node(node) => {
899                NodeOrToken::Node(SyntaxNode { node, source_file: self.source_file.clone() })
900            }
901            rowan::NodeOrToken::Token(token) => {
902                NodeOrToken::Token(SyntaxToken { token, source_file: self.source_file.clone() })
903            }
904        })
905    }
906    pub fn next_sibling(&self) -> Option<SyntaxNode> {
907        self.node
908            .next_sibling()
909            .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
910    }
911}
912
913#[derive(Debug, Clone, derive_more::From)]
914pub enum NodeOrToken {
915    Node(SyntaxNode),
916    Token(SyntaxToken),
917}
918
919impl NodeOrToken {
920    pub fn kind(&self) -> SyntaxKind {
921        match self {
922            NodeOrToken::Node(n) => n.kind(),
923            NodeOrToken::Token(t) => t.kind(),
924        }
925    }
926
927    pub fn as_node(&self) -> Option<&SyntaxNode> {
928        match self {
929            NodeOrToken::Node(n) => Some(n),
930            NodeOrToken::Token(_) => None,
931        }
932    }
933
934    pub fn as_token(&self) -> Option<&SyntaxToken> {
935        match self {
936            NodeOrToken::Node(_) => None,
937            NodeOrToken::Token(t) => Some(t),
938        }
939    }
940
941    pub fn into_token(self) -> Option<SyntaxToken> {
942        match self {
943            NodeOrToken::Token(t) => Some(t),
944            _ => None,
945        }
946    }
947
948    pub fn into_node(self) -> Option<SyntaxNode> {
949        match self {
950            NodeOrToken::Node(n) => Some(n),
951            _ => None,
952        }
953    }
954
955    pub fn text_range(&self) -> TextRange {
956        match self {
957            NodeOrToken::Node(n) => n.text_range(),
958            NodeOrToken::Token(t) => t.text_range(),
959        }
960    }
961}
962
963impl Spanned for SyntaxNode {
964    fn span(&self) -> crate::diagnostics::Span {
965        let range = self.node.text_range();
966        crate::diagnostics::Span::new(range.start().into(), range.len().into())
967    }
968
969    fn source_file(&self) -> Option<&SourceFile> {
970        Some(&self.source_file)
971    }
972}
973
974impl Spanned for Option<SyntaxNode> {
975    fn span(&self) -> crate::diagnostics::Span {
976        self.as_ref().map(|n| n.span()).unwrap_or_default()
977    }
978
979    fn source_file(&self) -> Option<&SourceFile> {
980        self.as_ref().and_then(|n| n.source_file())
981    }
982}
983
984impl Spanned for SyntaxToken {
985    fn span(&self) -> crate::diagnostics::Span {
986        let range = self.token.text_range();
987        crate::diagnostics::Span::new(range.start().into(), range.len().into())
988    }
989
990    fn source_file(&self) -> Option<&SourceFile> {
991        Some(&self.source_file)
992    }
993}
994
995impl Spanned for NodeOrToken {
996    fn span(&self) -> crate::diagnostics::Span {
997        match self {
998            NodeOrToken::Node(n) => n.span(),
999            NodeOrToken::Token(t) => t.span(),
1000        }
1001    }
1002
1003    fn source_file(&self) -> Option<&SourceFile> {
1004        match self {
1005            NodeOrToken::Node(n) => n.source_file(),
1006            NodeOrToken::Token(t) => t.source_file(),
1007        }
1008    }
1009}
1010
1011impl Spanned for Option<NodeOrToken> {
1012    fn span(&self) -> crate::diagnostics::Span {
1013        self.as_ref().map(|t| t.span()).unwrap_or_default()
1014    }
1015    fn source_file(&self) -> Option<&SourceFile> {
1016        self.as_ref().and_then(|t| t.source_file())
1017    }
1018}
1019
1020impl Spanned for Option<SyntaxToken> {
1021    fn span(&self) -> crate::diagnostics::Span {
1022        self.as_ref().map(|t| t.span()).unwrap_or_default()
1023    }
1024    fn source_file(&self) -> Option<&SourceFile> {
1025        self.as_ref().and_then(|t| t.source_file())
1026    }
1027}
1028
1029/// return the normalized identifier string of the first SyntaxKind::Identifier in this node
1030pub fn identifier_text(node: &SyntaxNode) -> Option<SmolStr> {
1031    node.child_text(SyntaxKind::Identifier).map(|x| normalize_identifier(&x))
1032}
1033
1034pub fn normalize_identifier(ident: &str) -> SmolStr {
1035    let mut builder = smol_str::SmolStrBuilder::default();
1036    for (pos, c) in ident.chars().enumerate() {
1037        match (pos, c) {
1038            (0, '-') | (0, '_') => builder.push('_'),
1039            (_, '_') => builder.push('-'),
1040            (_, c) => builder.push(c),
1041        }
1042    }
1043    builder.finish()
1044}
1045
1046#[test]
1047fn test_normalize_identifier() {
1048    assert_eq!(normalize_identifier("true"), SmolStr::new("true"));
1049    assert_eq!(normalize_identifier("foo_bar"), SmolStr::new("foo-bar"));
1050    assert_eq!(normalize_identifier("-foo_bar"), SmolStr::new("_foo-bar"));
1051    assert_eq!(normalize_identifier("-foo-bar"), SmolStr::new("_foo-bar"));
1052    assert_eq!(normalize_identifier("foo_bar_"), SmolStr::new("foo-bar-"));
1053    assert_eq!(normalize_identifier("foo_bar-"), SmolStr::new("foo-bar-"));
1054    assert_eq!(normalize_identifier("_foo_bar_"), SmolStr::new("_foo-bar-"));
1055    assert_eq!(normalize_identifier("__1"), SmolStr::new("_-1"));
1056    assert_eq!(normalize_identifier("--1"), SmolStr::new("_-1"));
1057    assert_eq!(normalize_identifier("--1--"), SmolStr::new("_-1--"));
1058}
1059
1060// Actual parser
1061pub fn parse(
1062    source: String,
1063    path: Option<&std::path::Path>,
1064    build_diagnostics: &mut BuildDiagnostics,
1065) -> SyntaxNode {
1066    let mut p = DefaultParser::new(&source, build_diagnostics);
1067    p.source_file = std::rc::Rc::new(crate::diagnostics::SourceFileInner::new(
1068        path.map(crate::pathutils::clean_path).unwrap_or_default(),
1069        source,
1070    ));
1071    document::parse_document(&mut p);
1072    SyntaxNode {
1073        node: rowan::SyntaxNode::new_root(p.builder.finish()),
1074        source_file: p.source_file.clone(),
1075    }
1076}
1077
1078pub fn parse_file<P: AsRef<std::path::Path>>(
1079    path: P,
1080    build_diagnostics: &mut BuildDiagnostics,
1081) -> Option<SyntaxNode> {
1082    let path = crate::pathutils::clean_path(path.as_ref());
1083    let source = crate::diagnostics::load_from_path(&path)
1084        .map_err(|d| build_diagnostics.push_internal_error(d))
1085        .ok()?;
1086    Some(parse(source, Some(path.as_ref()), build_diagnostics))
1087}
1088
1089pub fn parse_tokens(
1090    tokens: Vec<Token>,
1091    source_file: SourceFile,
1092    diags: &mut BuildDiagnostics,
1093) -> SyntaxNode {
1094    let mut p = DefaultParser::from_tokens(tokens, diags);
1095    document::parse_document(&mut p);
1096    SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
1097}