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 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
76 assert!(count >= 1, "Expecting one or more sub-node of type {}, found {}\n{:?}", stringify!($kind), count, $node);
77 };
78 (@check_has_children $node:ident, * $kind:ident) => {};
80 (@check_has_children $node:ident, ? $kind:ident) => {
82 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
83 assert!(count <= 1, "Expecting one or zero sub-node of type {}, found {}\n{:?}", stringify!($kind), count, $node);
84 };
85 (@check_has_children $node:ident, $kind:ident) => {
87 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
88 assert_eq!(count, 1, "Expecting exactly one sub-node of type {}\n{:?}", stringify!($kind), $node);
89 };
90 (@check_has_children $node:ident, $count:literal $kind:ident) => {
92 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
93 assert_eq!(count, $count, "Expecting {} sub-node of type {}, found {}\n{:?}", $count, stringify!($kind), count, $node);
94 };
95
96 (@extract_kind + $kind:ident) => {SyntaxKind::$kind};
97 (@extract_kind * $kind:ident) => {SyntaxKind::$kind};
98 (@extract_kind ? $kind:ident) => {SyntaxKind::$kind};
99 (@extract_kind $count:literal $kind:ident) => {SyntaxKind::$kind};
100 (@extract_kind $kind:ident) => {SyntaxKind::$kind};
101
102 (@extract_type + $kind:ident) => {$crate::parser::syntax_nodes::$kind};
103 (@extract_type * $kind:ident) => {$crate::parser::syntax_nodes::$kind};
104 (@extract_type ? $kind:ident) => {$crate::parser::syntax_nodes::$kind};
105 (@extract_type $count:literal $kind:ident) => {$crate::parser::syntax_nodes::$kind};
106 (@extract_type $kind:ident) => {$crate::parser::syntax_nodes::$kind};
107}
108
109macro_rules! node_accessors {
110 ([ $($t1:tt $($t2:ident)?),* ]) => {
112 $(node_accessors!{@ $t1 $($t2)*} )*
113 };
114 (@ + $kind:ident) => {
115 #[allow(non_snake_case)]
116 pub fn $kind(&self) -> impl Iterator<Item = $kind> + use<> {
117 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind).map(Into::into).peekable();
118 debug_assert!(it.peek().is_some(), stringify!(Expected at least one $kind));
119 it
120 }
121 };
122 (@ * $kind:ident) => {
123 #[allow(non_snake_case)]
124 pub fn $kind(&self) -> impl Iterator<Item = $kind> + use<> {
125 self.0.children().filter(|n| n.kind() == SyntaxKind::$kind).map(Into::into)
126 }
127 };
128 (@ ? $kind:ident) => {
129 #[allow(non_snake_case)]
130 pub fn $kind(&self) -> Option<$kind> {
131 self.0.child_node(SyntaxKind::$kind).map(Into::into)
132 }
133 };
134 (@ 2 $kind:ident) => {
135 #[allow(non_snake_case)]
136 #[track_caller]
137 pub fn $kind(&self) -> ($kind, $kind) {
138 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
139 let a = it.next().expect(stringify!(Missing first $kind));
140 let b = it.next().expect(stringify!(Missing second $kind));
141 debug_assert!(it.next().is_none(), stringify!(More $kind than expected));
142 (a.into(), b.into())
143 }
144 };
145 (@ 3 $kind:ident) => {
146 #[allow(non_snake_case)]
147 #[track_caller]
148 pub fn $kind(&self) -> ($kind, $kind, $kind) {
149 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
150 let a = it.next().expect(stringify!(Missing first $kind));
151 let b = it.next().expect(stringify!(Missing second $kind));
152 let c = it.next().expect(stringify!(Missing third $kind));
153 debug_assert!(it.next().is_none(), stringify!(More $kind than expected));
154 (a.into(), b.into(), c.into())
155 }
156 };
157 (@ $kind:ident) => {
158 #[allow(non_snake_case)]
159 #[track_caller]
160 pub fn $kind(&self) -> $kind {
161 self.0.child_node(SyntaxKind::$kind).expect(stringify!(Missing $kind)).into()
162 }
163 };
164
165}
166
167macro_rules! declare_syntax {
199 ({
200 $($token:ident -> $rule:expr ,)*
201 }
202 {
203 $( $(#[$attr:meta])* $nodekind:ident -> $children:tt ,)*
204 })
205 => {
206 #[repr(u16)]
207 #[derive(Debug, Copy, Clone, Eq, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive, Hash, Ord, PartialOrd)]
208 pub enum SyntaxKind {
209 Error,
210 Eof,
211
212 $(
214 $token,
216 )*
217
218 $(
220 $(#[$attr])*
221 $nodekind,
222 )*
223 }
224
225 impl Display for SyntaxKind {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 match self {
228 $(Self::$token => {
229 if let Some(character) = <dyn std::any::Any>::downcast_ref::<&str>(& $rule) {
230 return write!(f, "'{}'", character)
231 }
232 })*
233 _ => ()
234 }
235 write!(f, "{:?}", self)
236 }
237 }
238
239
240 pub fn lex_next_token(text : &str, state: &mut crate::lexer::LexState) -> Option<(usize, SyntaxKind)> {
242 use crate::lexer::LexingRule;
243 $(
244 let len = ($rule).lex(text, state);
245 if len > 0 {
246 return Some((len, SyntaxKind::$token));
247 }
248 )*
249 None
250 }
251
252 pub mod syntax_nodes {
253 use super::*;
254 $(
255 #[derive(Debug, Clone, derive_more::Deref, derive_more::Into)]
256 pub struct $nodekind(SyntaxNode);
257 #[cfg(test)]
258 impl SyntaxNodeVerify for $nodekind {
259 const KIND: SyntaxKind = SyntaxKind::$nodekind;
260 #[track_caller]
261 fn verify(node: SyntaxNode) {
262 assert_eq!(node.kind(), Self::KIND);
263 verify_node!(node, $children);
264 }
265 }
266 impl $nodekind {
267 node_accessors!{$children}
268
269 pub fn new(node: SyntaxNode) -> Option<Self> {
271 (node.kind() == SyntaxKind::$nodekind).then(|| Self(node))
272 }
273 }
274
275 impl From<SyntaxNode> for $nodekind {
276 #[track_caller]
277 fn from(node: SyntaxNode) -> Self {
278 assert_eq!(node.kind(), SyntaxKind::$nodekind);
279 Self(node)
280 }
281 }
282
283 impl Spanned for $nodekind {
284 fn span(&self) -> crate::diagnostics::Span {
285 self.0.span()
286 }
287
288 fn source_file(&self) -> Option<&SourceFile> {
289 self.0.source_file()
290 }
291 }
292 )*
293 }
294 }
295}
296declare_syntax! {
297 {
302 Whitespace -> &crate::lexer::lex_whitespace,
303 Comment -> &crate::lexer::lex_comment,
304 StringLiteral -> &crate::lexer::lex_string,
305 NumberLiteral -> &crate::lexer::lex_number,
306 ColorLiteral -> &crate::lexer::lex_color,
307 Identifier -> &crate::lexer::lex_identifier,
308 DoubleArrow -> "<=>",
309 DoubleLess -> "<<",
310 PlusEqual -> "+=",
311 MinusEqual -> "-=",
312 StarEqual -> "*=",
313 DivEqual -> "/=",
314 LessEqual -> "<=",
315 GreaterEqual -> ">=",
316 EqualEqual -> "==",
317 NotEqual -> "!=",
318 ColonEqual -> ":=",
319 FatArrow -> "=>",
320 Arrow -> "->",
321 OrOr -> "||",
322 AndAnd -> "&&",
323 LBrace -> "{",
324 RBrace -> "}",
325 LParent -> "(",
326 RParent -> ")",
327 LAngle -> "<",
328 RAngle -> ">",
329 LBracket -> "[",
330 RBracket -> "]",
331 Plus -> "+",
332 Minus -> "-",
333 Star -> "*",
334 Div -> "/",
335 Equal -> "=",
336 Colon -> ":",
337 Comma -> ",",
338 Semicolon -> ";",
339 Bang -> "!",
340 Dot -> ".",
341 Question -> "?",
342 Dollar -> "$",
343 At -> "@",
344 Pipe -> "|",
345 Percent -> "%",
346 }
347 {
350 Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration, *EnumDeclaration ],
351 Component -> [ DeclaredIdentifier, Element ],
353 SubElement -> [ Element ],
355 Element -> [ ?QualifiedName, *PropertyDeclaration, *Binding, *CallbackConnection,
356 *CallbackDeclaration, *ConditionalElement, *MatchElement, *Function, *SubElement,
357 *RepeatedElement, *PropertyAnimation, *PropertyChangedCallback,
358 *TwoWayBinding, *States, *Transitions, *ImplementStatement, ?ChildrenPlaceholder,
359 *SlotDeclaration, *SlotAssignment, *SlotForwarding ],
360 RepeatedElement -> [ ?DeclaredIdentifier, ?RepeatedIndex, Expression , SubElement],
361 RepeatedIndex -> [],
362 ConditionalElement -> [ Expression , SubElement],
363 MatchElement -> [ Expression , *MatchCase, ?WildcardMatchCase ],
365 MatchCase -> [ Expression, ?SubElement ],
367 WildcardMatchCase -> [ ?SubElement ],
369 CallbackDeclaration -> [ ?PropertyDeprecation, ?ShadowableAttribute, DeclaredIdentifier, *CallbackDeclarationParameter, ?ReturnType, ?TwoWayBinding ],
370 CallbackDeclarationParameter -> [ ?DeclaredIdentifier, Type],
372 Function -> [ ?PropertyDeprecation, ?ShadowableAttribute, DeclaredIdentifier, *ArgumentDeclaration, ?ReturnType, ?CodeBlock ],
373 ArgumentDeclaration -> [DeclaredIdentifier, Type],
374 ReturnType -> [Type],
376 CallbackConnection -> [ *DeclaredIdentifier, ?CodeBlock, ?Expression ],
377 PropertyDeclaration-> [ ?PropertyDeprecation, ?ShadowableAttribute, ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
379 PropertyDeprecation -> [],
382 ShadowableAttribute -> [],
385 PropertyAnimation-> [ *QualifiedName, *Binding ],
387 PropertyChangedCallback-> [ DeclaredIdentifier, ?CodeBlock, ?Expression ],
389 QualifiedName-> [],
391 DeclaredIdentifier -> [],
393 ChildrenPlaceholder -> [],
394 SlotAssignment -> [ DeclaredIdentifier, SubElement ],
395 SlotForwarding -> [ DeclaredIdentifier, ?Expression ],
396 Binding-> [ BindingExpression ],
397 TwoWayBinding -> [ Expression ],
399 ImplementStatement -> [ QualifiedName, DeclaredIdentifier ],
401 BindingExpression-> [ ?CodeBlock, ?Expression ],
404 CodeBlock-> [ *Expression, *LetStatement, *ReturnStatement ],
405 LetStatement -> [ DeclaredIdentifier, ?Type, Expression ],
406 ReturnStatement -> [ ?Expression ],
407 Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
409 ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
410 ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtGradient, ?AtTr,
411 ?MemberAccess, ?AtKeys, ?Closure ],
412 StringTemplate -> [*Expression],
414 AtImageUrl -> [],
416 AtGradient -> [*Expression],
418 AtTr -> [?TrContext, ?TrPlural, *Expression],
420 AtMarkdown -> [*Expression],
421 SlotDeclaration -> [ DeclaredIdentifier ],
423 TrContext -> [],
425 TrPlural -> [Expression],
427 AtKeys -> [],
429 FunctionCallExpression -> [*Expression],
431 IndexExpression -> [2 Expression],
433 SelfAssignment -> [2 Expression],
435 ConditionalExpression -> [3 Expression],
437 BinaryExpression -> [2 Expression],
439 UnaryOpExpression -> [Expression],
441 MemberAccess -> [Expression],
443 Array -> [ *Expression ],
445 ObjectLiteral -> [ *ObjectMember ],
447 ObjectMember -> [ Expression ],
449 States -> [*State],
451 State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange, *Transition],
453 StatePropertyChange -> [ QualifiedName, BindingExpression ],
455 Transitions -> [*Transition],
457 Transition -> [?DeclaredIdentifier, *PropertyAnimation],
459 ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration, ?ExportModule, *EnumDeclaration ],
461 ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
464 ExportIdentifier -> [],
465 ExportName -> [],
466 ExportModule -> [],
468 ImportSpecifier -> [ ?ImportIdentifierList ],
470 ImportIdentifierList -> [ *ImportIdentifier ],
471 ImportIdentifier -> [ ExternalName, ?InternalName ],
473 ExternalName -> [],
474 InternalName -> [],
475 Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
477 ObjectType ->[ *ObjectTypeMember ],
479 ObjectTypeMember -> [ Type, ?Expression ],
481 ArrayType -> [ Type ],
483 StructDeclaration -> [DeclaredIdentifier, ObjectType, *AtRustAttr],
485 EnumDeclaration -> [DeclaredIdentifier, *EnumValue, *AtRustAttr],
487 EnumValue -> [],
489 AtRustAttr -> [],
491 Closure -> [DeclaredIdentifier, Expression],
493 }
494}
495
496impl From<SyntaxKind> for rowan::SyntaxKind {
497 fn from(v: SyntaxKind) -> Self {
498 rowan::SyntaxKind(v.into())
499 }
500}
501
502#[derive(Clone, Debug)]
503pub struct Token {
504 pub kind: SyntaxKind,
505 pub text: SmolStr,
506 pub offset: usize,
508 #[cfg(feature = "proc_macro_span")]
509 pub span: Option<proc_macro::Span>,
510}
511
512impl Default for Token {
513 fn default() -> Self {
514 Token {
515 kind: SyntaxKind::Eof,
516 text: Default::default(),
517 offset: 0,
518 #[cfg(feature = "proc_macro_span")]
519 span: None,
520 }
521 }
522}
523
524impl Token {
525 pub fn as_str(&self) -> &str {
526 self.text.as_str()
527 }
528
529 pub fn kind(&self) -> SyntaxKind {
530 self.kind
531 }
532}
533
534mod parser_trait {
535 use super::*;
537
538 pub trait Parser: Sized {
539 type Checkpoint: Clone;
540
541 #[must_use = "The node will be finished when it is dropped"]
547 fn start_node(&mut self, kind: SyntaxKind) -> Node<'_, Self> {
548 self.start_node_impl(kind, None, NodeToken(()));
549 Node(self)
550 }
551 #[must_use = "use start_node_at to use this checkpoint"]
552 fn checkpoint(&mut self) -> Self::Checkpoint;
553 #[must_use = "The node will be finished when it is dropped"]
554 fn start_node_at(
555 &mut self,
556 checkpoint: impl Into<Option<Self::Checkpoint>>,
557 kind: SyntaxKind,
558 ) -> Node<'_, Self> {
559 self.start_node_impl(kind, checkpoint.into(), NodeToken(()));
560 Node(self)
561 }
562
563 fn finish_node_impl(&mut self, token: NodeToken);
565 fn start_node_impl(
567 &mut self,
568 kind: SyntaxKind,
569 checkpoint: Option<Self::Checkpoint>,
570 token: NodeToken,
571 );
572
573 fn peek(&mut self) -> Token {
575 self.nth(0)
576 }
577 fn nth(&mut self, n: usize) -> Token;
579 fn consume(&mut self);
581 fn error(&mut self, e: impl Into<String>);
582 fn warning(&mut self, e: impl Into<String>);
583
584 fn expect(&mut self, kind: SyntaxKind) -> bool {
587 if !self.test(kind) {
588 self.error(format!("Syntax error: expected {kind}"));
589 return false;
590 }
591 true
592 }
593
594 fn test(&mut self, kind: SyntaxKind) -> bool {
596 if self.nth(0).kind() != kind {
597 return false;
598 }
599 self.consume();
600 true
601 }
602
603 fn until(&mut self, kind: SyntaxKind) {
605 let mut parens = 0;
606 let mut braces = 0;
607 let mut brackets = 0;
608 loop {
609 match self.nth(0).kind() {
610 k if k == kind && parens == 0 && braces == 0 && brackets == 0 => break,
611 SyntaxKind::Eof => break,
612 SyntaxKind::LParent => parens += 1,
613 SyntaxKind::LBrace => braces += 1,
614 SyntaxKind::LBracket => brackets += 1,
615 SyntaxKind::RParent if parens == 0 => break,
616 SyntaxKind::RParent => parens -= 1,
617 SyntaxKind::RBrace if braces == 0 => break,
618 SyntaxKind::RBrace => braces -= 1,
619 SyntaxKind::RBracket if brackets == 0 => break,
620 SyntaxKind::RBracket => brackets -= 1,
621 _ => {}
622 };
623 self.consume();
624 }
625 self.expect(kind);
626 }
627 }
628
629 pub struct NodeToken(());
634 #[derive(derive_more::DerefMut)]
637 pub struct Node<'a, P: Parser>(&'a mut P);
638 impl<P: Parser> Drop for Node<'_, P> {
639 fn drop(&mut self) {
640 self.0.finish_node_impl(NodeToken(()));
641 }
642 }
643 impl<P: Parser> core::ops::Deref for Node<'_, P> {
644 type Target = P;
645 fn deref(&self) -> &Self::Target {
646 self.0
647 }
648 }
649}
650#[doc(inline)]
651pub use parser_trait::*;
652
653pub struct DefaultParser<'a> {
654 builder: rowan::GreenNodeBuilder<'static>,
655 tokens: Vec<Token>,
657 cursor: usize,
659 diags: &'a mut BuildDiagnostics,
660 source_file: SourceFile,
661}
662
663impl<'a> DefaultParser<'a> {
664 fn from_tokens(tokens: Vec<Token>, diags: &'a mut BuildDiagnostics) -> Self {
665 Self {
666 builder: Default::default(),
667 tokens,
668 cursor: 0,
669 diags,
670 source_file: Default::default(),
671 }
672 }
673
674 pub fn new(source: &str, diags: &'a mut BuildDiagnostics) -> Self {
677 Self::from_tokens(crate::lexer::lex(source), diags)
678 }
679
680 fn current_token(&self) -> Token {
681 self.tokens.get(self.cursor).cloned().unwrap_or_default()
682 }
683
684 fn current_token_location(&self) -> crate::diagnostics::SourceLocation {
686 let token = self.current_token();
687 crate::diagnostics::SourceLocation {
688 source_file: Some(self.source_file.clone()),
689 span: crate::diagnostics::Span::new(token.offset, token.text.len()),
690 }
691 }
692
693 pub fn consume_ws(&mut self) {
695 while matches!(self.current_token().kind, SyntaxKind::Whitespace | SyntaxKind::Comment) {
696 self.consume()
697 }
698 }
699}
700
701impl Parser for DefaultParser<'_> {
702 fn start_node_impl(
703 &mut self,
704 kind: SyntaxKind,
705 checkpoint: Option<Self::Checkpoint>,
706 _: NodeToken,
707 ) {
708 if kind != SyntaxKind::Document {
709 self.consume_ws();
710 }
711 match checkpoint {
712 None => self.builder.start_node(kind.into()),
713 Some(cp) => self.builder.start_node_at(cp, kind.into()),
714 }
715 }
716
717 fn finish_node_impl(&mut self, _: NodeToken) {
718 self.builder.finish_node();
719 }
720
721 fn nth(&mut self, mut n: usize) -> Token {
723 self.consume_ws();
724 let mut c = self.cursor;
725 while n > 0 {
726 n -= 1;
727 c += 1;
728 while c < self.tokens.len()
729 && matches!(self.tokens[c].kind, SyntaxKind::Whitespace | SyntaxKind::Comment)
730 {
731 c += 1;
732 }
733 }
734 self.tokens.get(c).cloned().unwrap_or_default()
735 }
736
737 fn consume(&mut self) {
739 let t = self.current_token();
740 self.builder.token(t.kind.into(), t.text.as_str());
741 if t.kind != SyntaxKind::Eof {
742 self.cursor += 1;
743 }
744 }
745
746 fn error(&mut self, e: impl Into<String>) {
748 let location = self.current_token_location();
749 self.diags.push_error_with_span(e.into(), location);
750 }
751
752 fn warning(&mut self, e: impl Into<String>) {
754 let location = self.current_token_location();
755 self.diags.push_warning_with_span(e.into(), location);
756 }
757
758 type Checkpoint = rowan::Checkpoint;
759 fn checkpoint(&mut self) -> Self::Checkpoint {
760 self.builder.checkpoint()
761 }
762}
763
764#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
765pub enum Language {}
766impl rowan::Language for Language {
767 type Kind = SyntaxKind;
768 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
769 SyntaxKind::try_from(raw.0).unwrap()
770 }
771 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
772 kind.into()
773 }
774}
775
776#[derive(Debug, Clone, derive_more::Deref)]
777pub struct SyntaxNode {
778 #[deref]
779 pub node: rowan::SyntaxNode<Language>,
780 pub source_file: SourceFile,
781}
782
783#[derive(Debug, Clone, derive_more::Deref)]
784pub struct SyntaxToken {
785 #[deref]
786 pub token: rowan::SyntaxToken<Language>,
787 pub source_file: SourceFile,
788}
789
790impl SyntaxToken {
791 pub fn parent(&self) -> SyntaxNode {
792 SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
793 }
794 pub fn parent_ancestors(&self) -> impl Iterator<Item = SyntaxNode> + '_ {
795 self.token
796 .parent_ancestors()
797 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
798 }
799 pub fn next_token(&self) -> Option<SyntaxToken> {
800 let token = self
808 .token
809 .next_sibling_or_token()
810 .and_then(|e| match e {
811 rowan::NodeOrToken::Node(n) => n.first_token(),
812 rowan::NodeOrToken::Token(t) => Some(t),
813 })
814 .or_else(|| {
815 self.token.parent_ancestors().find_map(|it| it.next_sibling_or_token()).and_then(
816 |e| match e {
817 rowan::NodeOrToken::Node(n) => n.first_token(),
818 rowan::NodeOrToken::Token(t) => Some(t),
819 },
820 )
821 })?;
822 Some(SyntaxToken { token, source_file: self.source_file.clone() })
823 }
824 pub fn prev_token(&self) -> Option<SyntaxToken> {
825 let token = self.token.prev_token()?;
826 Some(SyntaxToken { token, source_file: self.source_file.clone() })
827 }
828 pub fn text(&self) -> &str {
829 self.token.text()
830 }
831}
832
833impl std::fmt::Display for SyntaxToken {
834 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
835 self.token.fmt(f)
836 }
837}
838
839impl SyntaxNode {
840 pub fn child_node(&self, kind: SyntaxKind) -> Option<SyntaxNode> {
841 self.node
842 .children()
843 .find(|n| n.kind() == kind)
844 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
845 }
846 pub fn child_token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
847 self.node
848 .children_with_tokens()
849 .find(|n| n.kind() == kind)
850 .and_then(|x| x.into_token())
851 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
852 }
853 pub fn child_text(&self, kind: SyntaxKind) -> Option<SmolStr> {
854 self.node
855 .children_with_tokens()
856 .find(|n| n.kind() == kind)
857 .and_then(|x| x.as_token().map(|x| x.text().into()))
858 }
859 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> + use<> {
860 let source_file = self.source_file.clone();
861 self.node
862 .descendants()
863 .map(move |node| SyntaxNode { node, source_file: source_file.clone() })
864 }
865 pub fn kind(&self) -> SyntaxKind {
866 self.node.kind()
867 }
868 pub fn children(&self) -> impl Iterator<Item = SyntaxNode> + use<> {
869 let source_file = self.source_file.clone();
870 self.node.children().map(move |node| SyntaxNode { node, source_file: source_file.clone() })
871 }
872 pub fn children_with_tokens(&self) -> impl Iterator<Item = NodeOrToken> + use<> {
873 let source_file = self.source_file.clone();
874 self.node.children_with_tokens().map(move |token| match token {
875 rowan::NodeOrToken::Node(node) => {
876 SyntaxNode { node, source_file: source_file.clone() }.into()
877 }
878 rowan::NodeOrToken::Token(token) => {
879 SyntaxToken { token, source_file: source_file.clone() }.into()
880 }
881 })
882 }
883 pub fn text(&self) -> rowan::SyntaxText {
884 self.node.text()
885 }
886 pub fn parent(&self) -> Option<SyntaxNode> {
887 self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
888 }
889 pub fn first_token(&self) -> Option<SyntaxToken> {
890 self.node
891 .first_token()
892 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
893 }
894 pub fn last_token(&self) -> Option<SyntaxToken> {
895 self.node
896 .last_token()
897 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
898 }
899 pub fn token_at_offset(&self, offset: TextSize) -> rowan::TokenAtOffset<SyntaxToken> {
900 self.node
901 .token_at_offset(offset)
902 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
903 }
904 pub fn first_child(&self) -> Option<SyntaxNode> {
905 self.node
906 .first_child()
907 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
908 }
909 pub fn first_child_or_token(&self) -> Option<NodeOrToken> {
910 self.node.first_child_or_token().map(|n_o_t| match n_o_t {
911 rowan::NodeOrToken::Node(node) => {
912 NodeOrToken::Node(SyntaxNode { node, source_file: self.source_file.clone() })
913 }
914 rowan::NodeOrToken::Token(token) => {
915 NodeOrToken::Token(SyntaxToken { token, source_file: self.source_file.clone() })
916 }
917 })
918 }
919 pub fn next_sibling(&self) -> Option<SyntaxNode> {
920 self.node
921 .next_sibling()
922 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
923 }
924}
925
926#[derive(Debug, Clone, derive_more::From)]
927pub enum NodeOrToken {
928 Node(SyntaxNode),
929 Token(SyntaxToken),
930}
931
932impl NodeOrToken {
933 pub fn kind(&self) -> SyntaxKind {
934 match self {
935 NodeOrToken::Node(n) => n.kind(),
936 NodeOrToken::Token(t) => t.kind(),
937 }
938 }
939
940 pub fn as_node(&self) -> Option<&SyntaxNode> {
941 match self {
942 NodeOrToken::Node(n) => Some(n),
943 NodeOrToken::Token(_) => None,
944 }
945 }
946
947 pub fn as_token(&self) -> Option<&SyntaxToken> {
948 match self {
949 NodeOrToken::Node(_) => None,
950 NodeOrToken::Token(t) => Some(t),
951 }
952 }
953
954 pub fn into_token(self) -> Option<SyntaxToken> {
955 match self {
956 NodeOrToken::Token(t) => Some(t),
957 _ => None,
958 }
959 }
960
961 pub fn into_node(self) -> Option<SyntaxNode> {
962 match self {
963 NodeOrToken::Node(n) => Some(n),
964 _ => None,
965 }
966 }
967
968 pub fn text_range(&self) -> TextRange {
969 match self {
970 NodeOrToken::Node(n) => n.text_range(),
971 NodeOrToken::Token(t) => t.text_range(),
972 }
973 }
974}
975
976impl Spanned for SyntaxNode {
977 fn span(&self) -> crate::diagnostics::Span {
978 let range = self.node.text_range();
979 crate::diagnostics::Span::new(range.start().into(), range.len().into())
980 }
981
982 fn source_file(&self) -> Option<&SourceFile> {
983 Some(&self.source_file)
984 }
985}
986
987impl Spanned for Option<SyntaxNode> {
988 fn span(&self) -> crate::diagnostics::Span {
989 self.as_ref().map(|n| n.span()).unwrap_or_default()
990 }
991
992 fn source_file(&self) -> Option<&SourceFile> {
993 self.as_ref().and_then(|n| n.source_file())
994 }
995}
996
997impl Spanned for SyntaxToken {
998 fn span(&self) -> crate::diagnostics::Span {
999 let range = self.token.text_range();
1000 crate::diagnostics::Span::new(range.start().into(), range.len().into())
1001 }
1002
1003 fn source_file(&self) -> Option<&SourceFile> {
1004 Some(&self.source_file)
1005 }
1006}
1007
1008impl Spanned for NodeOrToken {
1009 fn span(&self) -> crate::diagnostics::Span {
1010 match self {
1011 NodeOrToken::Node(n) => n.span(),
1012 NodeOrToken::Token(t) => t.span(),
1013 }
1014 }
1015
1016 fn source_file(&self) -> Option<&SourceFile> {
1017 match self {
1018 NodeOrToken::Node(n) => n.source_file(),
1019 NodeOrToken::Token(t) => t.source_file(),
1020 }
1021 }
1022}
1023
1024impl Spanned for Option<NodeOrToken> {
1025 fn span(&self) -> crate::diagnostics::Span {
1026 self.as_ref().map(|t| t.span()).unwrap_or_default()
1027 }
1028 fn source_file(&self) -> Option<&SourceFile> {
1029 self.as_ref().and_then(|t| t.source_file())
1030 }
1031}
1032
1033impl Spanned for Option<SyntaxToken> {
1034 fn span(&self) -> crate::diagnostics::Span {
1035 self.as_ref().map(|t| t.span()).unwrap_or_default()
1036 }
1037 fn source_file(&self) -> Option<&SourceFile> {
1038 self.as_ref().and_then(|t| t.source_file())
1039 }
1040}
1041
1042pub fn identifier_text(node: &SyntaxNode) -> Option<SmolStr> {
1044 node.child_text(SyntaxKind::Identifier).map(|x| normalize_identifier(&x))
1045}
1046
1047pub fn normalize_identifier(ident: &str) -> SmolStr {
1048 if is_identifier_normalized(ident) {
1049 return SmolStr::new(ident);
1051 }
1052 let mut builder = smol_str::SmolStrBuilder::default();
1053 for (pos, c) in ident.chars().enumerate() {
1054 match (pos, c) {
1055 (0, '-') | (0, '_') => builder.push('_'),
1056 (_, '_') => builder.push('-'),
1057 (_, c) => builder.push(c),
1058 }
1059 }
1060 builder.finish()
1061}
1062
1063pub fn is_identifier_normalized(ident: &str) -> bool {
1066 let b = ident.as_bytes();
1068 b.first() != Some(&b'-') && !b[1.min(b.len())..].contains(&b'_')
1069}
1070
1071#[test]
1072fn test_normalize_identifier() {
1073 assert_eq!(normalize_identifier("true"), SmolStr::new("true"));
1074 assert_eq!(normalize_identifier("foo_bar"), SmolStr::new("foo-bar"));
1075 assert_eq!(normalize_identifier("-foo_bar"), SmolStr::new("_foo-bar"));
1076 assert_eq!(normalize_identifier("-foo-bar"), SmolStr::new("_foo-bar"));
1077 assert_eq!(normalize_identifier("foo_bar_"), SmolStr::new("foo-bar-"));
1078 assert_eq!(normalize_identifier("foo_bar-"), SmolStr::new("foo-bar-"));
1079 assert_eq!(normalize_identifier("_foo_bar_"), SmolStr::new("_foo-bar-"));
1080 assert_eq!(normalize_identifier("__1"), SmolStr::new("_-1"));
1081 assert_eq!(normalize_identifier("--1"), SmolStr::new("_-1"));
1082 assert_eq!(normalize_identifier("--1--"), SmolStr::new("_-1--"));
1083}
1084
1085#[test]
1086fn test_is_identifier_normalized() {
1087 for ident in
1088 ["true", "foo-bar", "foo_bar", "-foo", "_foo", "foo-bar-", "", "-", "_", "ä_ö", "ä-ö"]
1089 {
1090 assert_eq!(
1091 is_identifier_normalized(ident),
1092 normalize_identifier(ident) == ident,
1093 "{ident:?}"
1094 );
1095 }
1096}
1097
1098pub fn parse(
1100 source: String,
1101 path: Option<&std::path::Path>,
1102 build_diagnostics: &mut BuildDiagnostics,
1103) -> SyntaxNode {
1104 let mut p = DefaultParser::new(&source, build_diagnostics);
1105 p.source_file = std::sync::Arc::new(crate::diagnostics::SourceFileInner::new(
1106 path.map(crate::pathutils::clean_path).unwrap_or_default(),
1107 source,
1108 ));
1109 document::parse_document(&mut p);
1110 SyntaxNode {
1111 node: rowan::SyntaxNode::new_root(p.builder.finish()),
1112 source_file: p.source_file.clone(),
1113 }
1114}
1115
1116pub fn parse_file<P: AsRef<std::path::Path>>(
1117 path: P,
1118 build_diagnostics: &mut BuildDiagnostics,
1119) -> Option<SyntaxNode> {
1120 let path = crate::pathutils::clean_path(path.as_ref());
1121 let source = crate::diagnostics::load_from_path(&path)
1122 .map_err(|d| build_diagnostics.push_internal_error(d))
1123 .ok()?;
1124 Some(parse(source, Some(path.as_ref()), build_diagnostics))
1125}
1126
1127pub fn parse_tokens(
1128 tokens: Vec<Token>,
1129 source_file: SourceFile,
1130 diags: &mut BuildDiagnostics,
1131) -> SyntaxNode {
1132 let mut p = DefaultParser::from_tokens(tokens, diags);
1133 document::parse_document(&mut p);
1134 SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
1135}