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