1use crate::diagnostics::{BuildDiagnostics, SourceFile, Spanned};
16pub use smol_str::SmolStr;
17use std::{convert::TryFrom, fmt::Display};
18
19mod document;
20mod element;
21mod expressions;
22mod statements;
23mod r#type;
24
25mod prelude {
27 #[cfg(test)]
28 pub use super::{syntax_nodes, SyntaxNode, SyntaxNodeVerify};
29 pub use super::{DefaultParser, Parser, SyntaxKind};
30 #[cfg(test)]
31 pub use parser_test_macro::parser_test;
32}
33
34#[cfg(test)]
35pub trait SyntaxNodeVerify {
36 const KIND: SyntaxKind;
38 fn verify(node: SyntaxNode) {
41 assert_eq!(node.kind(), Self::KIND)
42 }
43}
44
45#[cfg(test)]
47macro_rules! verify_node {
48 ($node:ident, _) => {};
50 ($node:ident, [ $($t1:tt $($t2:ident)?),* ]) => {
52 $(verify_node!(@check_has_children $node, $t1 $($t2)* );)*
54
55 for c in $node.children() {
57 assert!(
58 false $(|| c.kind() == verify_node!(@extract_kind $t1 $($t2)*))*,
59 "Node is none of [{}]\n{:?}", stringify!($($t1 $($t2)*),*) ,c);
60 }
61
62 $(
64 for _c in $node.children().filter(|n| n.kind() == verify_node!(@extract_kind $t1 $($t2)*)) {
65 <verify_node!(@extract_type $t1 $($t2)*)>::verify(_c)
66 }
67 )*
68 };
69
70 (@check_has_children $node:ident, * $kind:ident) => {};
72 (@check_has_children $node:ident, ? $kind:ident) => {
74 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
75 assert!(count <= 1, "Expecting one or zero sub-node of type {}, found {}\n{:?}", stringify!($kind), count, $node);
76 };
77 (@check_has_children $node:ident, $kind:ident) => {
79 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
80 assert_eq!(count, 1, "Expecting exactly one sub-node of type {}\n{:?}", stringify!($kind), $node);
81 };
82 (@check_has_children $node:ident, $count:literal $kind:ident) => {
84 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
85 assert_eq!(count, $count, "Expecting {} sub-node of type {}, found {}\n{:?}", $count, stringify!($kind), count, $node);
86 };
87
88 (@extract_kind * $kind:ident) => {SyntaxKind::$kind};
89 (@extract_kind ? $kind:ident) => {SyntaxKind::$kind};
90 (@extract_kind $count:literal $kind:ident) => {SyntaxKind::$kind};
91 (@extract_kind $kind:ident) => {SyntaxKind::$kind};
92
93 (@extract_type * $kind:ident) => {$crate::parser::syntax_nodes::$kind};
94 (@extract_type ? $kind:ident) => {$crate::parser::syntax_nodes::$kind};
95 (@extract_type $count:literal $kind:ident) => {$crate::parser::syntax_nodes::$kind};
96 (@extract_type $kind:ident) => {$crate::parser::syntax_nodes::$kind};
97}
98
99macro_rules! node_accessors {
100 (_) => {};
102 ([ $($t1:tt $($t2:ident)?),* ]) => {
104 $(node_accessors!{@ $t1 $($t2)*} )*
105 };
106
107 (@ * $kind:ident) => {
108 #[allow(non_snake_case)]
109 pub fn $kind(&self) -> impl Iterator<Item = $kind> {
110 self.0.children().filter(|n| n.kind() == SyntaxKind::$kind).map(Into::into)
111 }
112 };
113 (@ ? $kind:ident) => {
114 #[allow(non_snake_case)]
115 pub fn $kind(&self) -> Option<$kind> {
116 self.0.child_node(SyntaxKind::$kind).map(Into::into)
117 }
118 };
119 (@ 2 $kind:ident) => {
120 #[allow(non_snake_case)]
121 pub fn $kind(&self) -> ($kind, $kind) {
122 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
123 let a = it.next().unwrap();
124 let b = it.next().unwrap();
125 debug_assert!(it.next().is_none());
126 (a.into(), b.into())
127 }
128 };
129 (@ 3 $kind:ident) => {
130 #[allow(non_snake_case)]
131 pub fn $kind(&self) -> ($kind, $kind, $kind) {
132 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
133 let a = it.next().unwrap();
134 let b = it.next().unwrap();
135 let c = it.next().unwrap();
136 debug_assert!(it.next().is_none());
137 (a.into(), b.into(), c.into())
138 }
139 };
140 (@ $kind:ident) => {
141 #[allow(non_snake_case)]
142 pub fn $kind(&self) -> $kind {
143 self.0.child_node(SyntaxKind::$kind).unwrap().into()
144 }
145 };
146
147}
148
149macro_rules! declare_syntax {
181 ({
182 $($token:ident -> $rule:expr ,)*
183 }
184 {
185 $( $(#[$attr:meta])* $nodekind:ident -> $children:tt ,)*
186 })
187 => {
188 #[repr(u16)]
189 #[derive(Debug, Copy, Clone, Eq, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
190 pub enum SyntaxKind {
191 Error,
192 Eof,
193
194 $(
196 $token,
198 )*
199
200 $(
202 $(#[$attr])*
203 $nodekind,
204 )*
205 }
206
207 impl Display for SyntaxKind {
208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 match self {
210 $(Self::$token => {
211 if let Some(character) = <dyn std::any::Any>::downcast_ref::<&str>(& $rule) {
212 return write!(f, "'{}'", character)
213 }
214 })*
215 _ => ()
216 }
217 write!(f, "{:?}", self)
218 }
219 }
220
221
222 pub fn lex_next_token(text : &str, state: &mut crate::lexer::LexState) -> Option<(usize, SyntaxKind)> {
224 use crate::lexer::LexingRule;
225 $(
226 let len = ($rule).lex(text, state);
227 if len > 0 {
228 return Some((len, SyntaxKind::$token));
229 }
230 )*
231 None
232 }
233
234 pub mod syntax_nodes {
235 use super::*;
236 use derive_more::*;
237 $(
238 #[derive(Debug, Clone, Deref, Into)]
239 pub struct $nodekind(SyntaxNode);
240 #[cfg(test)]
241 impl SyntaxNodeVerify for $nodekind {
242 const KIND: SyntaxKind = SyntaxKind::$nodekind;
243 fn verify(node: SyntaxNode) {
244 assert_eq!(node.kind(), Self::KIND);
245 verify_node!(node, $children);
246 }
247 }
248 impl $nodekind {
249 node_accessors!{$children}
250
251 pub fn new(node: SyntaxNode) -> Option<Self> {
253 (node.kind() == SyntaxKind::$nodekind).then(|| Self(node))
254 }
255 }
256
257 impl From<SyntaxNode> for $nodekind {
258 fn from(node: SyntaxNode) -> Self {
259 debug_assert_eq!(node.kind(), SyntaxKind::$nodekind);
260 Self(node)
261 }
262 }
263
264 impl Spanned for $nodekind {
265 fn span(&self) -> crate::diagnostics::Span {
266 self.0.span()
267 }
268
269 fn source_file(&self) -> Option<&SourceFile> {
270 self.0.source_file()
271 }
272 }
273 )*
274 }
275 }
276}
277declare_syntax! {
278 {
283 Whitespace -> &crate::lexer::lex_whitespace,
284 Comment -> &crate::lexer::lex_comment,
285 StringLiteral -> &crate::lexer::lex_string,
286 NumberLiteral -> &crate::lexer::lex_number,
287 ColorLiteral -> &crate::lexer::lex_color,
288 Identifier -> &crate::lexer::lex_identifier,
289 DoubleArrow -> "<=>",
290 PlusEqual -> "+=",
291 MinusEqual -> "-=",
292 StarEqual -> "*=",
293 DivEqual -> "/=",
294 LessEqual -> "<=",
295 GreaterEqual -> ">=",
296 EqualEqual -> "==",
297 NotEqual -> "!=",
298 ColonEqual -> ":=",
299 FatArrow -> "=>",
300 Arrow -> "->",
301 OrOr -> "||",
302 AndAnd -> "&&",
303 LBrace -> "{",
304 RBrace -> "}",
305 LParent -> "(",
306 RParent -> ")",
307 LAngle -> "<",
308 RAngle -> ">",
309 LBracket -> "[",
310 RBracket -> "]",
311 Plus -> "+",
312 Minus -> "-",
313 Star -> "*",
314 Div -> "/",
315 Equal -> "=",
316 Colon -> ":",
317 Comma -> ",",
318 Semicolon -> ";",
319 Bang -> "!",
320 Dot -> ".",
321 Question -> "?",
322 Dollar -> "$",
323 At -> "@",
324 }
325 {
327 Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration ],
328 Component -> [ DeclaredIdentifier, Element ],
330 SubElement -> [ Element ],
332 Element -> [ ?QualifiedName, *PropertyDeclaration, *Binding, *CallbackConnection,
333 *CallbackDeclaration, *SubElement, *RepeatedElement, *PropertyAnimation,
334 *TwoWayBinding, *States, *Transitions, ?ChildrenPlaceholder ],
335 RepeatedElement -> [ ?DeclaredIdentifier, ?RepeatedIndex, Expression , SubElement],
336 RepeatedIndex -> [],
337 ConditionalElement -> [ Expression , SubElement],
338 CallbackDeclaration -> [ DeclaredIdentifier, *Type, ?ReturnType, ?TwoWayBinding ],
339 ReturnType -> [Type],
341 CallbackConnection -> [ *DeclaredIdentifier, CodeBlock ],
342 PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
344 PropertyAnimation-> [ *QualifiedName, *Binding ],
346 QualifiedName-> [],
348 DeclaredIdentifier -> [],
350 ChildrenPlaceholder -> [],
351 Binding-> [ BindingExpression ],
352 TwoWayBinding -> [ Expression ],
354 BindingExpression-> [ ?CodeBlock, ?Expression ],
357 CodeBlock-> [ *Expression, *ReturnStatement ],
358 ReturnStatement -> [ ?Expression ],
359 Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
361 ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
362 ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtLinearGradient,
363 ?MemberAccess ],
364 StringTemplate -> [*Expression],
366 AtImageUrl -> [],
368 AtLinearGradient -> [*Expression],
370 FunctionCallExpression -> [*Expression],
372 IndexExpression -> [2 Expression],
374 SelfAssignment -> [2 Expression],
376 ConditionalExpression -> [3 Expression],
378 BinaryExpression -> [2 Expression],
380 UnaryOpExpression -> [Expression],
382 MemberAccess -> [Expression],
384 Array -> [ *Expression ],
386 ObjectLiteral -> [ *ObjectMember ],
388 ObjectMember -> [ Expression ],
390 States -> [*State],
392 State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange],
394 StatePropertyChange -> [ QualifiedName, BindingExpression ],
396 Transitions -> [*Transition],
398 Transition -> [DeclaredIdentifier, *PropertyAnimation],
400 ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration ],
402 ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
405 ExportIdentifier -> [],
406 ExportName -> [],
407 ImportSpecifier -> [ ?ImportIdentifierList ],
409 ImportIdentifierList -> [ *ImportIdentifier ],
410 ImportIdentifier -> [ ExternalName, ?InternalName ],
412 ExternalName -> [],
413 InternalName -> [],
414 Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
416 ObjectType ->[ *ObjectTypeMember ],
418 ObjectTypeMember -> [ Type ],
420 ArrayType -> [ Type ],
422 StructDeclaration -> [DeclaredIdentifier, ObjectType],
424
425 }
426}
427
428impl From<SyntaxKind> for rowan::SyntaxKind {
429 fn from(v: SyntaxKind) -> Self {
430 rowan::SyntaxKind(v.into())
431 }
432}
433
434#[derive(Clone, Debug)]
435pub struct Token {
436 pub kind: SyntaxKind,
437 pub text: SmolStr,
438 pub offset: usize,
439 #[cfg(feature = "proc_macro_span")]
440 pub span: Option<proc_macro::Span>,
441}
442
443impl Default for Token {
444 fn default() -> Self {
445 Token {
446 kind: SyntaxKind::Eof,
447 text: Default::default(),
448 offset: 0,
449 #[cfg(feature = "proc_macro_span")]
450 span: None,
451 }
452 }
453}
454
455impl Token {
456 pub fn as_str(&self) -> &str {
457 self.text.as_str()
458 }
459
460 pub fn kind(&self) -> SyntaxKind {
461 self.kind
462 }
463}
464
465mod parser_trait {
466 use super::*;
468
469 pub trait Parser: Sized {
470 type Checkpoint: Clone;
471
472 #[must_use = "The node will be finished when it is dropped"]
478 fn start_node(&mut self, kind: SyntaxKind) -> Node<Self> {
479 self.start_node_impl(kind, None, NodeToken(()));
480 Node(self)
481 }
482 #[must_use = "use start_node_at to use this checkpoint"]
483 fn checkpoint(&mut self) -> Self::Checkpoint;
484 #[must_use = "The node will be finished when it is dropped"]
485 fn start_node_at(&mut self, checkpoint: Self::Checkpoint, kind: SyntaxKind) -> Node<Self> {
486 self.start_node_impl(kind, Some(checkpoint), NodeToken(()));
487 Node(self)
488 }
489
490 fn finish_node_impl(&mut self, token: NodeToken);
492 fn start_node_impl(
494 &mut self,
495 kind: SyntaxKind,
496 checkpoint: Option<Self::Checkpoint>,
497 token: NodeToken,
498 );
499
500 fn peek(&mut self) -> Token {
502 self.nth(0)
503 }
504 fn nth(&mut self, n: usize) -> Token;
506 fn consume(&mut self);
507 fn error(&mut self, e: impl Into<String>);
508
509 fn expect(&mut self, kind: SyntaxKind) -> bool {
512 if !self.test(kind) {
513 self.error(format!("Syntax error: expected {}", kind));
514 return false;
515 }
516 true
517 }
518
519 fn test(&mut self, kind: SyntaxKind) -> bool {
521 if self.nth(0).kind() != kind {
522 return false;
523 }
524 self.consume();
525 true
526 }
527
528 fn until(&mut self, kind: SyntaxKind) {
530 while {
532 let k = self.nth(0).kind();
533 k != kind && k != SyntaxKind::Eof
534 } {
535 self.consume();
536 }
537 self.expect(kind);
538 }
539 }
540
541 pub struct NodeToken(());
546 #[derive(derive_more::DerefMut)]
549 pub struct Node<'a, P: Parser>(&'a mut P);
550 impl<'a, P: Parser> Drop for Node<'a, P> {
551 fn drop(&mut self) {
552 self.0.finish_node_impl(NodeToken(()));
553 }
554 }
555 impl<'a, P: Parser> core::ops::Deref for Node<'a, P> {
556 type Target = P;
557 fn deref(&self) -> &Self::Target {
558 self.0
559 }
560 }
561}
562#[doc(inline)]
563pub use parser_trait::*;
564
565pub struct DefaultParser<'a> {
566 builder: rowan::GreenNodeBuilder<'static>,
567 tokens: Vec<Token>,
568 cursor: usize,
569 diags: &'a mut BuildDiagnostics,
570 source_file: SourceFile,
571}
572
573impl<'a> DefaultParser<'a> {
574 fn from_tokens(tokens: Vec<Token>, diags: &'a mut BuildDiagnostics) -> Self {
575 Self {
576 builder: Default::default(),
577 tokens,
578 cursor: 0,
579 diags,
580 source_file: Default::default(),
581 }
582 }
583
584 pub fn new(source: &str, diags: &'a mut BuildDiagnostics) -> Self {
586 Self::from_tokens(crate::lexer::lex(source), diags)
587 }
588
589 fn current_token(&self) -> Token {
590 self.tokens.get(self.cursor).cloned().unwrap_or_default()
591 }
592
593 pub fn consume_ws(&mut self) {
595 while matches!(self.current_token().kind, SyntaxKind::Whitespace | SyntaxKind::Comment) {
596 self.consume()
597 }
598 }
599}
600
601impl Parser for DefaultParser<'_> {
602 fn start_node_impl(
603 &mut self,
604 kind: SyntaxKind,
605 checkpoint: Option<Self::Checkpoint>,
606 _: NodeToken,
607 ) {
608 match checkpoint {
609 None => self.builder.start_node(kind.into()),
610 Some(cp) => self.builder.start_node_at(cp, kind.into()),
611 }
612 }
613
614 fn finish_node_impl(&mut self, _: NodeToken) {
615 self.builder.finish_node();
616 }
617
618 fn nth(&mut self, mut n: usize) -> Token {
620 self.consume_ws();
621 let mut c = self.cursor;
622 while n > 0 {
623 n -= 1;
624 c += 1;
625 while c < self.tokens.len()
626 && matches!(self.tokens[c].kind, SyntaxKind::Whitespace | SyntaxKind::Comment)
627 {
628 c += 1;
629 }
630 }
631 self.tokens.get(c).cloned().unwrap_or_default()
632 }
633
634 fn consume(&mut self) {
636 let t = self.current_token();
637 self.builder.token(t.kind.into(), t.text.as_str());
638 self.cursor += 1;
639 }
640
641 fn error(&mut self, e: impl Into<String>) {
643 let current_token = self.current_token();
644 #[allow(unused_mut)]
645 let mut span = crate::diagnostics::Span::new(current_token.offset);
646 #[cfg(feature = "proc_macro_span")]
647 {
648 span.span = current_token.span;
649 }
650
651 self.diags.push_error_with_span(
652 e.into(),
653 crate::diagnostics::SourceLocation {
654 source_file: Some(self.source_file.clone()),
655 span,
656 },
657 );
658 }
659
660 type Checkpoint = rowan::Checkpoint;
661 fn checkpoint(&mut self) -> Self::Checkpoint {
662 self.builder.checkpoint()
663 }
664}
665
666#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
667pub enum Language {}
668impl rowan::Language for Language {
669 type Kind = SyntaxKind;
670 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
671 SyntaxKind::try_from(raw.0).unwrap()
672 }
673 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
674 kind.into()
675 }
676}
677
678#[derive(Debug, Clone, derive_more::Deref)]
679pub struct SyntaxNode {
680 #[deref]
681 pub node: rowan::SyntaxNode<Language>,
682 pub source_file: SourceFile,
683}
684
685#[derive(Debug, Clone, derive_more::Deref)]
686pub struct SyntaxToken {
687 #[deref]
688 pub token: rowan::SyntaxToken<Language>,
689 pub source_file: SourceFile,
690}
691
692impl SyntaxToken {
693 pub fn parent(&self) -> SyntaxNode {
694 SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
695 }
696}
697
698impl std::fmt::Display for SyntaxToken {
699 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
700 self.token.fmt(f)
701 }
702}
703
704impl SyntaxNode {
705 pub fn child_node(&self, kind: SyntaxKind) -> Option<SyntaxNode> {
706 self.node
707 .children()
708 .find(|n| n.kind() == kind)
709 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
710 }
711 pub fn child_token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
712 self.node
713 .children_with_tokens()
714 .find(|n| n.kind() == kind)
715 .and_then(|x| x.into_token())
716 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
717 }
718 pub fn child_text(&self, kind: SyntaxKind) -> Option<String> {
719 self.node
720 .children_with_tokens()
721 .find(|n| n.kind() == kind)
722 .and_then(|x| x.as_token().map(|x| x.text().to_string()))
723 }
724 pub fn kind(&self) -> SyntaxKind {
725 self.node.kind()
726 }
727 pub fn children(&self) -> impl Iterator<Item = SyntaxNode> {
728 let source_file = self.source_file.clone();
729 self.node.children().map(move |node| SyntaxNode { node, source_file: source_file.clone() })
730 }
731 pub fn children_with_tokens(&self) -> impl Iterator<Item = NodeOrToken> {
732 let source_file = self.source_file.clone();
733 self.node.children_with_tokens().map(move |token| match token {
734 rowan::NodeOrToken::Node(node) => {
735 SyntaxNode { node, source_file: source_file.clone() }.into()
736 }
737 rowan::NodeOrToken::Token(token) => {
738 SyntaxToken { token, source_file: source_file.clone() }.into()
739 }
740 })
741 }
742 pub fn text(&self) -> rowan::SyntaxText {
743 self.node.text()
744 }
745 pub fn parent(&self) -> Option<SyntaxNode> {
746 self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
747 }
748}
749
750#[derive(Debug, Clone, derive_more::From)]
751pub enum NodeOrToken {
752 Node(SyntaxNode),
753 Token(SyntaxToken),
754}
755
756impl NodeOrToken {
757 pub fn kind(&self) -> SyntaxKind {
758 match self {
759 NodeOrToken::Node(n) => n.kind(),
760 NodeOrToken::Token(t) => t.kind(),
761 }
762 }
763
764 pub fn as_node(&self) -> Option<&SyntaxNode> {
765 match self {
766 NodeOrToken::Node(n) => Some(n),
767 NodeOrToken::Token(_) => None,
768 }
769 }
770
771 pub fn as_token(&self) -> Option<&SyntaxToken> {
772 match self {
773 NodeOrToken::Node(_) => None,
774 NodeOrToken::Token(t) => Some(t),
775 }
776 }
777
778 pub fn into_token(self) -> Option<SyntaxToken> {
779 match self {
780 NodeOrToken::Token(t) => Some(t),
781 _ => None,
782 }
783 }
784
785 pub fn into_node(self) -> Option<SyntaxNode> {
786 match self {
787 NodeOrToken::Node(n) => Some(n),
788 _ => None,
789 }
790 }
791}
792
793impl Spanned for SyntaxNode {
794 fn span(&self) -> crate::diagnostics::Span {
795 crate::diagnostics::Span::new(self.node.text_range().start().into())
796 }
797
798 fn source_file(&self) -> Option<&SourceFile> {
799 Some(&self.source_file)
800 }
801}
802
803impl Spanned for Option<SyntaxNode> {
804 fn span(&self) -> crate::diagnostics::Span {
805 self.as_ref().map(|n| n.span()).unwrap_or_default()
806 }
807
808 fn source_file(&self) -> Option<&SourceFile> {
809 self.as_ref().and_then(|n| n.source_file())
810 }
811}
812
813impl Spanned for SyntaxToken {
814 fn span(&self) -> crate::diagnostics::Span {
815 crate::diagnostics::Span::new(self.token.text_range().start().into())
816 }
817
818 fn source_file(&self) -> Option<&SourceFile> {
819 Some(&self.source_file)
820 }
821}
822
823impl Spanned for NodeOrToken {
824 fn span(&self) -> crate::diagnostics::Span {
825 match self {
826 NodeOrToken::Node(n) => n.span(),
827 NodeOrToken::Token(t) => t.span(),
828 }
829 }
830
831 fn source_file(&self) -> Option<&SourceFile> {
832 match self {
833 NodeOrToken::Node(n) => n.source_file(),
834 NodeOrToken::Token(t) => t.source_file(),
835 }
836 }
837}
838
839impl Spanned for Option<NodeOrToken> {
840 fn span(&self) -> crate::diagnostics::Span {
841 self.as_ref().map(|t| t.span()).unwrap_or_default()
842 }
843 fn source_file(&self) -> Option<&SourceFile> {
844 self.as_ref().and_then(|t| t.source_file())
845 }
846}
847
848impl Spanned for Option<SyntaxToken> {
849 fn span(&self) -> crate::diagnostics::Span {
850 self.as_ref().map(|t| t.span()).unwrap_or_default()
851 }
852 fn source_file(&self) -> Option<&SourceFile> {
853 self.as_ref().and_then(|t| t.source_file())
854 }
855}
856
857pub fn identifier_text(node: &SyntaxNode) -> Option<String> {
859 node.child_text(SyntaxKind::Identifier).map(|x| normalize_identifier(&x))
860}
861
862pub fn normalize_identifier(ident: &str) -> String {
863 ident.replace('_', "-")
864}
865
866pub fn parse(
868 source: String,
869 path: Option<&std::path::Path>,
870 build_diagnostics: &mut BuildDiagnostics,
871) -> SyntaxNode {
872 let mut p = DefaultParser::new(&source, build_diagnostics);
873 let source_file = if let Some(path) = path {
874 p.source_file =
875 std::rc::Rc::new(crate::diagnostics::SourceFileInner::new(path.to_path_buf(), source));
876 p.source_file.clone()
877 } else {
878 Default::default()
879 };
880 document::parse_document(&mut p);
881 SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
882}
883
884pub fn parse_file<P: AsRef<std::path::Path>>(
885 path: P,
886 build_diagnostics: &mut BuildDiagnostics,
887) -> Option<SyntaxNode> {
888 let source = crate::diagnostics::load_from_path(path.as_ref())
889 .map_err(|d| build_diagnostics.push_internal_error(d))
890 .ok()?;
891 Some(parse(source, Some(path.as_ref()), build_diagnostics))
892}
893
894pub fn parse_tokens(
895 tokens: Vec<Token>,
896 source_file: SourceFile,
897 diags: &mut BuildDiagnostics,
898) -> SyntaxNode {
899 let mut p = DefaultParser::from_tokens(tokens, diags);
900 document::parse_document(&mut p);
901 SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
902}