1use 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
26mod 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 const KIND: SyntaxKind;
41 fn verify(node: SyntaxNode) {
44 assert_eq!(node.kind(), Self::KIND)
45 }
46}
47
48pub use rowan::{TextRange, TextSize};
49
50#[cfg(test)]
52macro_rules! verify_node {
53 ($node:ident, [ $($t1:tt $($t2:ident)?),* ]) => {
55 $(verify_node!(@check_has_children $node, $t1 $($t2)* );)*
57
58 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 $(
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 (@check_has_children $node:ident, * $kind:ident) => {};
75 (@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 (@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 (@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 ([ $($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
153macro_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 $(
200 $token,
202 )*
203
204 $(
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 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 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 {
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 {
335 Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration, *EnumDeclaration ],
336 Component -> [ DeclaredIdentifier, ?UsesSpecifier, ?ImplementsSpecifier, Element ],
338 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 CallbackDeclarationParameter -> [ ?DeclaredIdentifier, Type],
350 Function -> [DeclaredIdentifier, *ArgumentDeclaration, ?ReturnType, ?CodeBlock ],
351 ArgumentDeclaration -> [DeclaredIdentifier, Type],
352 ReturnType -> [Type],
354 CallbackConnection -> [ *DeclaredIdentifier, ?CodeBlock, ?Expression ],
355 PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
357 PropertyAnimation-> [ *QualifiedName, *Binding ],
359 PropertyChangedCallback-> [ DeclaredIdentifier, ?CodeBlock, ?Expression ],
361 QualifiedName-> [],
363 DeclaredIdentifier -> [],
365 ChildrenPlaceholder -> [],
366 Binding-> [ BindingExpression ],
367 TwoWayBinding -> [ Expression ],
369 BindingExpression-> [ ?CodeBlock, ?Expression ],
372 CodeBlock-> [ *Expression, *LetStatement, *ReturnStatement ],
373 LetStatement -> [ DeclaredIdentifier, ?Type, Expression ],
374 ReturnStatement -> [ ?Expression ],
375 Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
377 ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
378 ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtGradient, ?AtTr,
379 ?MemberAccess, ?AtKeys ],
380 StringTemplate -> [*Expression],
382 AtImageUrl -> [],
384 AtGradient -> [*Expression],
386 AtTr -> [?TrContext, ?TrPlural, *Expression],
388 AtMarkdown -> [*Expression],
389 TrContext -> [],
391 TrPlural -> [Expression],
393 AtKeys -> [],
395 FunctionCallExpression -> [*Expression],
397 IndexExpression -> [2 Expression],
399 SelfAssignment -> [2 Expression],
401 ConditionalExpression -> [3 Expression],
403 BinaryExpression -> [2 Expression],
405 UnaryOpExpression -> [Expression],
407 MemberAccess -> [Expression],
409 Array -> [ *Expression ],
411 ObjectLiteral -> [ *ObjectMember ],
413 ObjectMember -> [ Expression ],
415 States -> [*State],
417 State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange, *Transition],
419 StatePropertyChange -> [ QualifiedName, BindingExpression ],
421 Transitions -> [*Transition],
423 Transition -> [?DeclaredIdentifier, *PropertyAnimation],
425 ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration, ?ExportModule, *EnumDeclaration ],
427 ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
430 ExportIdentifier -> [],
431 ExportName -> [],
432 ExportModule -> [],
434 ImportSpecifier -> [ ?ImportIdentifierList ],
436 ImportIdentifierList -> [ *ImportIdentifier ],
437 ImportIdentifier -> [ ExternalName, ?InternalName ],
439 ExternalName -> [],
440 InternalName -> [],
441 Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
443 ObjectType ->[ *ObjectTypeMember ],
445 ObjectTypeMember -> [ Type ],
447 ArrayType -> [ Type ],
449 StructDeclaration -> [DeclaredIdentifier, ObjectType, *AtRustAttr],
451 EnumDeclaration -> [DeclaredIdentifier, *EnumValue, *AtRustAttr],
453 EnumValue -> [],
455 AtRustAttr -> [],
457 UsesSpecifier -> [ *UsesIdentifier ],
459 UsesIdentifier -> [QualifiedName, DeclaredIdentifier],
461 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 use super::*;
508
509 pub trait Parser: Sized {
510 type Checkpoint: Clone;
511
512 #[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 fn finish_node_impl(&mut self, token: NodeToken);
536 fn start_node_impl(
538 &mut self,
539 kind: SyntaxKind,
540 checkpoint: Option<Self::Checkpoint>,
541 token: NodeToken,
542 );
543
544 fn peek(&mut self) -> Token {
546 self.nth(0)
547 }
548 fn nth(&mut self, n: usize) -> Token;
550 fn consume(&mut self);
552 fn error(&mut self, e: impl Into<String>);
553 fn warning(&mut self, e: impl Into<String>);
554
555 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 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 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 pub struct NodeToken(());
605 #[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: Vec<Token>,
628 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 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 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 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 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 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 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 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
1030pub 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
1061pub 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}