1use crate::SyntaxKind::{
8 self, AMP, AMP_AMP, BANG, BANG_EQ, BANG_QUESTION, CARET, COLON, DIVERT, DOLLAR, EQ, EQ_EQ,
9 FLOAT, GT, GT_EQ, HASH, IDENT, INTEGER, KW_AND, KW_CYCLE, KW_DONE, KW_ELSE, KW_END, KW_FALSE,
10 KW_FUNCTION, KW_HAS, KW_HASNT, KW_MOD, KW_NOT, KW_ONCE, KW_OR, KW_REF, KW_SHUFFLE, KW_STOPPING,
11 KW_TODO, KW_TRUE, LT, LT_EQ, MINUS, MINUS_EQ, NEWLINE, PERCENT, PIPE, PLUS, PLUS_EQ, QUESTION,
12 SLASH, STAR, TILDE,
13};
14use crate::ast::AstNode as _;
15use crate::ast::ast_node;
16use crate::ast::support;
17use crate::{SyntaxNode, SyntaxToken};
18
19ast_node!(SourceFile, SOURCE_FILE);
22ast_node!(IncludeStmt, INCLUDE_STMT);
23ast_node!(FilePath, FILE_PATH);
24ast_node!(ExternalDecl, EXTERNAL_DECL);
25
26ast_node!(KnotDef, KNOT_DEF);
29ast_node!(KnotHeader, KNOT_HEADER);
30ast_node!(KnotBody, KNOT_BODY);
31ast_node!(KnotParams, KNOT_PARAMS);
32ast_node!(KnotParamDecl, KNOT_PARAM_DECL);
33ast_node!(StitchDef, STITCH_DEF);
34ast_node!(StitchHeader, STITCH_HEADER);
35ast_node!(StitchBody, STITCH_BODY);
36
37ast_node!(EmptyLine, EMPTY_LINE);
40ast_node!(AuthorWarning, AUTHOR_WARNING);
41ast_node!(LogicLine, LOGIC_LINE);
42ast_node!(ContentLine, CONTENT_LINE);
43ast_node!(TagLine, TAG_LINE);
44ast_node!(StrayClosingBrace, STRAY_CLOSING_BRACE);
45
46ast_node!(ReturnStmt, RETURN_STMT);
49ast_node!(TempDecl, TEMP_DECL);
50ast_node!(Assignment, ASSIGNMENT);
51
52ast_node!(MixedContent, MIXED_CONTENT);
55ast_node!(Text, TEXT);
56ast_node!(Escape, ESCAPE);
57ast_node!(GlueNode, GLUE_NODE);
58
59ast_node!(Choice, CHOICE);
62ast_node!(ChoiceBullets, CHOICE_BULLETS);
63ast_node!(Label, LABEL);
64ast_node!(ChoiceCondition, CHOICE_CONDITION);
65ast_node!(ChoiceStartContent, CHOICE_START_CONTENT);
66ast_node!(ChoiceBracketContent, CHOICE_BRACKET_CONTENT);
67ast_node!(ChoiceInnerContent, CHOICE_INNER_CONTENT);
68
69ast_node!(Gather, GATHER);
72ast_node!(GatherDashes, GATHER_DASHES);
73
74ast_node!(Tags, TAGS);
77ast_node!(Tag, TAG);
78
79ast_node!(InlineLogic, INLINE_LOGIC);
82ast_node!(MultilineBlock, MULTILINE_BLOCK);
83ast_node!(SequenceWithAnnotation, SEQUENCE_WITH_ANNOTATION);
84ast_node!(SequenceSymbolAnnotation, SEQUENCE_SYMBOL_ANNOTATION);
85ast_node!(SequenceWordAnnotation, SEQUENCE_WORD_ANNOTATION);
86ast_node!(InlineBranchesSeq, INLINE_BRANCHES_SEQ);
87ast_node!(MultilineBranchesSeq, MULTILINE_BRANCHES_SEQ);
88ast_node!(MultilineBranchSeq, MULTILINE_BRANCH_SEQ);
89ast_node!(BranchContent, BRANCH_CONTENT);
90
91ast_node!(ConditionalWithExpr, CONDITIONAL_WITH_EXPR);
94ast_node!(BranchlessCondBody, BRANCHLESS_COND_BODY);
95ast_node!(ElseBranch, ELSE_BRANCH);
96ast_node!(InlineBranchesCond, INLINE_BRANCHES_COND);
97ast_node!(MultilineBranchesCond, MULTILINE_BRANCHES_COND);
98ast_node!(MultilineConditional, MULTILINE_CONDITIONAL);
99ast_node!(MultilineBranchCond, MULTILINE_BRANCH_COND);
100ast_node!(MultilineBranchBody, MULTILINE_BRANCH_BODY);
101ast_node!(ImplicitSequence, IMPLICIT_SEQUENCE);
102
103ast_node!(InnerExpression, INNER_EXPRESSION);
106ast_node!(PrefixExpr, PREFIX_EXPR);
107ast_node!(PostfixExpr, POSTFIX_EXPR);
108ast_node!(InfixExpr, INFIX_EXPR);
109ast_node!(ParenExpr, PAREN_EXPR);
110ast_node!(FunctionCall, FUNCTION_CALL);
111ast_node!(ArgList, ARG_LIST);
112ast_node!(DivertTargetExpr, DIVERT_TARGET_EXPR);
113ast_node!(ListExpr, LIST_EXPR);
114
115ast_node!(DivertNode, DIVERT_NODE);
118ast_node!(SimpleDivert, SIMPLE_DIVERT);
119ast_node!(DivertTargetWithArgs, DIVERT_TARGET_WITH_ARGS);
120ast_node!(ThreadStart, THREAD_START);
121ast_node!(TunnelOnwardsNode, TUNNEL_ONWARDS_NODE);
122ast_node!(TunnelCallNode, TUNNEL_CALL_NODE);
123
124ast_node!(Identifier, IDENTIFIER);
127ast_node!(Path, PATH);
128
129ast_node!(VarDecl, VAR_DECL);
132ast_node!(ConstDecl, CONST_DECL);
133ast_node!(ListDecl, LIST_DECL);
134ast_node!(ListDef, LIST_DEF);
135ast_node!(ListMember, LIST_MEMBER);
136ast_node!(ListMemberOn, LIST_MEMBER_ON);
137ast_node!(ListMemberOff, LIST_MEMBER_OFF);
138ast_node!(FunctionParamList, FUNCTION_PARAM_LIST);
139
140ast_node!(IntegerLit, INTEGER_LIT);
143ast_node!(FloatLit, FLOAT_LIT);
144ast_node!(StringLit, STRING_LIT);
145ast_node!(BooleanLit, BOOLEAN_LIT);
146
147ast_node!(Error, ERROR);
150
151#[derive(Clone, PartialEq, Eq, Hash)]
157pub enum Expr {
158 Prefix(PrefixExpr),
159 Postfix(PostfixExpr),
160 Infix(InfixExpr),
161 Paren(ParenExpr),
162 FunctionCall(FunctionCall),
163 IntegerLit(IntegerLit),
164 FloatLit(FloatLit),
165 StringLit(StringLit),
166 BooleanLit(BooleanLit),
167 Path(Path),
168 ListExpr(ListExpr),
169 DivertTarget(DivertTargetExpr),
170}
171
172impl std::fmt::Debug for Expr {
173 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174 std::fmt::Debug::fmt(self.syntax(), f)
175 }
176}
177
178impl std::fmt::Display for Expr {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 std::fmt::Display::fmt(&self.syntax().text(), f)
181 }
182}
183
184impl crate::ast::AstNode for Expr {
185 fn can_cast(kind: SyntaxKind) -> bool {
186 matches!(
187 kind,
188 SyntaxKind::PREFIX_EXPR
189 | SyntaxKind::POSTFIX_EXPR
190 | SyntaxKind::INFIX_EXPR
191 | SyntaxKind::PAREN_EXPR
192 | SyntaxKind::FUNCTION_CALL
193 | SyntaxKind::INTEGER_LIT
194 | SyntaxKind::FLOAT_LIT
195 | SyntaxKind::STRING_LIT
196 | SyntaxKind::BOOLEAN_LIT
197 | SyntaxKind::PATH
198 | SyntaxKind::LIST_EXPR
199 | SyntaxKind::DIVERT_TARGET_EXPR
200 )
201 }
202
203 fn cast(node: SyntaxNode) -> Option<Self> {
204 match node.kind() {
205 SyntaxKind::PREFIX_EXPR => PrefixExpr::cast(node).map(Expr::Prefix),
206 SyntaxKind::POSTFIX_EXPR => PostfixExpr::cast(node).map(Expr::Postfix),
207 SyntaxKind::INFIX_EXPR => InfixExpr::cast(node).map(Expr::Infix),
208 SyntaxKind::PAREN_EXPR => ParenExpr::cast(node).map(Expr::Paren),
209 SyntaxKind::FUNCTION_CALL => FunctionCall::cast(node).map(Expr::FunctionCall),
210 SyntaxKind::INTEGER_LIT => IntegerLit::cast(node).map(Expr::IntegerLit),
211 SyntaxKind::FLOAT_LIT => FloatLit::cast(node).map(Expr::FloatLit),
212 SyntaxKind::STRING_LIT => StringLit::cast(node).map(Expr::StringLit),
213 SyntaxKind::BOOLEAN_LIT => BooleanLit::cast(node).map(Expr::BooleanLit),
214 SyntaxKind::PATH => Path::cast(node).map(Expr::Path),
215 SyntaxKind::LIST_EXPR => ListExpr::cast(node).map(Expr::ListExpr),
216 SyntaxKind::DIVERT_TARGET_EXPR => DivertTargetExpr::cast(node).map(Expr::DivertTarget),
217 _ => None,
218 }
219 }
220
221 fn syntax(&self) -> &SyntaxNode {
222 match self {
223 Expr::Prefix(n) => n.syntax(),
224 Expr::Postfix(n) => n.syntax(),
225 Expr::Infix(n) => n.syntax(),
226 Expr::Paren(n) => n.syntax(),
227 Expr::FunctionCall(n) => n.syntax(),
228 Expr::IntegerLit(n) => n.syntax(),
229 Expr::FloatLit(n) => n.syntax(),
230 Expr::StringLit(n) => n.syntax(),
231 Expr::BooleanLit(n) => n.syntax(),
232 Expr::Path(n) => n.syntax(),
233 Expr::ListExpr(n) => n.syntax(),
234 Expr::DivertTarget(n) => n.syntax(),
235 }
236 }
237}
238
239macro_rules! content_node_accessors {
244 ($name:ident) => {
245 impl $name {
246 pub fn texts(&self) -> impl Iterator<Item = Text> {
247 support::children(&self.syntax)
248 }
249
250 pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
251 support::children(&self.syntax)
252 }
253
254 pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
255 support::children(&self.syntax)
256 }
257
258 pub fn escapes(&self) -> impl Iterator<Item = Escape> {
259 support::children(&self.syntax)
260 }
261 }
262 };
263}
264
265content_node_accessors!(ChoiceStartContent);
266content_node_accessors!(ChoiceBracketContent);
267content_node_accessors!(ChoiceInnerContent);
268content_node_accessors!(BranchContent);
269
270impl SourceFile {
277 pub fn knots(&self) -> impl Iterator<Item = KnotDef> {
278 support::children(&self.syntax)
279 }
280
281 pub fn includes(&self) -> impl Iterator<Item = IncludeStmt> {
282 support::children(&self.syntax)
283 }
284
285 pub fn externals(&self) -> impl Iterator<Item = ExternalDecl> {
286 support::children(&self.syntax)
287 }
288
289 pub fn stitches(&self) -> impl Iterator<Item = StitchDef> {
290 support::children(&self.syntax)
291 }
292
293 pub fn var_decls(&self) -> impl Iterator<Item = VarDecl> {
294 support::children(&self.syntax)
295 }
296
297 pub fn const_decls(&self) -> impl Iterator<Item = ConstDecl> {
298 support::children(&self.syntax)
299 }
300
301 pub fn list_decls(&self) -> impl Iterator<Item = ListDecl> {
302 support::children(&self.syntax)
303 }
304
305 pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
306 support::children(&self.syntax)
307 }
308
309 pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
310 support::children(&self.syntax)
311 }
312
313 pub fn choices(&self) -> impl Iterator<Item = Choice> {
314 support::children(&self.syntax)
315 }
316
317 pub fn gathers(&self) -> impl Iterator<Item = Gather> {
318 support::children(&self.syntax)
319 }
320}
321
322impl IncludeStmt {
325 pub fn file_path(&self) -> Option<FilePath> {
326 support::child(&self.syntax)
327 }
328}
329
330impl FilePath {
333 pub fn text(&self) -> String {
335 self.syntax.text().to_string()
336 }
337}
338
339impl ExternalDecl {
342 pub fn identifier(&self) -> Option<Identifier> {
343 support::child(&self.syntax)
344 }
345
346 pub fn name(&self) -> Option<String> {
347 self.identifier().and_then(|id| id.name())
348 }
349
350 pub fn param_list(&self) -> Option<FunctionParamList> {
351 support::child(&self.syntax)
352 }
353}
354
355impl KnotDef {
358 pub fn header(&self) -> Option<KnotHeader> {
359 support::child(&self.syntax)
360 }
361
362 pub fn body(&self) -> Option<KnotBody> {
363 support::child(&self.syntax)
364 }
365}
366
367impl KnotHeader {
370 pub fn function_kw(&self) -> Option<SyntaxToken> {
371 support::token(&self.syntax, KW_FUNCTION)
372 }
373
374 pub fn is_function(&self) -> bool {
375 self.function_kw().is_some()
376 }
377
378 pub fn identifier(&self) -> Option<Identifier> {
379 support::child(&self.syntax)
380 }
381
382 pub fn name(&self) -> Option<String> {
383 self.identifier().and_then(|id| id.name())
384 }
385
386 pub fn params(&self) -> Option<KnotParams> {
387 support::child(&self.syntax)
388 }
389}
390
391impl KnotBody {
394 pub fn stitches(&self) -> impl Iterator<Item = StitchDef> {
395 support::children(&self.syntax)
396 }
397
398 pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
399 support::children(&self.syntax)
400 }
401
402 pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
403 support::children(&self.syntax)
404 }
405
406 pub fn choices(&self) -> impl Iterator<Item = Choice> {
407 support::children(&self.syntax)
408 }
409
410 pub fn gathers(&self) -> impl Iterator<Item = Gather> {
411 support::children(&self.syntax)
412 }
413}
414
415impl KnotParams {
418 pub fn params(&self) -> impl Iterator<Item = KnotParamDecl> {
419 support::children(&self.syntax)
420 }
421}
422
423impl KnotParamDecl {
426 pub fn divert_token(&self) -> Option<SyntaxToken> {
427 support::token(&self.syntax, DIVERT)
428 }
429
430 pub fn is_divert(&self) -> bool {
431 self.divert_token().is_some()
432 }
433
434 pub fn ref_kw(&self) -> Option<SyntaxToken> {
435 support::token(&self.syntax, KW_REF)
436 }
437
438 pub fn is_ref(&self) -> bool {
439 self.ref_kw().is_some()
440 }
441
442 pub fn identifier(&self) -> Option<Identifier> {
443 support::child(&self.syntax)
444 }
445
446 pub fn name(&self) -> Option<String> {
447 self.identifier().and_then(|id| id.name())
448 }
449}
450
451impl StitchDef {
454 pub fn header(&self) -> Option<StitchHeader> {
455 support::child(&self.syntax)
456 }
457
458 pub fn body(&self) -> Option<StitchBody> {
459 support::child(&self.syntax)
460 }
461}
462
463impl StitchHeader {
466 pub fn identifier(&self) -> Option<Identifier> {
467 support::child(&self.syntax)
468 }
469
470 pub fn name(&self) -> Option<String> {
471 self.identifier().and_then(|id| id.name())
472 }
473
474 pub fn params(&self) -> Option<KnotParams> {
475 support::child(&self.syntax)
476 }
477}
478
479impl StitchBody {
482 pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
483 support::children(&self.syntax)
484 }
485
486 pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
487 support::children(&self.syntax)
488 }
489
490 pub fn choices(&self) -> impl Iterator<Item = Choice> {
491 support::children(&self.syntax)
492 }
493
494 pub fn gathers(&self) -> impl Iterator<Item = Gather> {
495 support::children(&self.syntax)
496 }
497}
498
499impl ContentLine {
502 pub fn mixed_content(&self) -> Option<MixedContent> {
503 support::child(&self.syntax)
504 }
505
506 pub fn divert(&self) -> Option<DivertNode> {
507 support::child(&self.syntax)
508 }
509
510 pub fn tags(&self) -> Option<Tags> {
511 support::child(&self.syntax)
512 }
513}
514
515impl LogicLine {
518 pub fn return_stmt(&self) -> Option<ReturnStmt> {
519 support::child(&self.syntax)
520 }
521
522 pub fn temp_decl(&self) -> Option<TempDecl> {
523 support::child(&self.syntax)
524 }
525
526 pub fn assignment(&self) -> Option<Assignment> {
527 support::child(&self.syntax)
528 }
529}
530
531impl TagLine {
534 pub fn tags(&self) -> Option<Tags> {
535 support::child(&self.syntax)
536 }
537}
538
539impl ReturnStmt {
542 pub fn value(&self) -> Option<Expr> {
547 support::child(&self.syntax)
548 }
549
550 pub fn has_value(&self) -> bool {
552 self.value().is_some()
553 }
554}
555
556impl TempDecl {
559 pub fn identifier(&self) -> Option<Identifier> {
560 support::child(&self.syntax)
561 }
562
563 pub fn name(&self) -> Option<String> {
564 self.identifier().and_then(|id| id.name())
565 }
566
567 pub fn eq_token(&self) -> Option<SyntaxToken> {
568 support::token(&self.syntax, EQ)
569 }
570
571 pub fn value(&self) -> Option<Expr> {
573 support::child(&self.syntax)
574 }
575}
576
577impl Assignment {
580 pub fn target(&self) -> Option<Expr> {
581 self.syntax.children().find_map(Expr::cast)
582 }
583
584 pub fn op_token(&self) -> Option<SyntaxToken> {
586 self.syntax
587 .children_with_tokens()
588 .filter_map(rowan::NodeOrToken::into_token)
589 .find(|tok| matches!(tok.kind(), EQ | PLUS_EQ | MINUS_EQ))
590 }
591
592 pub fn value(&self) -> Option<Expr> {
594 self.syntax.children().filter_map(Expr::cast).nth(1)
595 }
596}
597
598impl MixedContent {
601 pub fn texts(&self) -> impl Iterator<Item = Text> {
602 support::children(&self.syntax)
603 }
604
605 pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
606 support::children(&self.syntax)
607 }
608
609 pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
610 support::children(&self.syntax)
611 }
612
613 pub fn escapes(&self) -> impl Iterator<Item = Escape> {
614 support::children(&self.syntax)
615 }
616}
617
618impl Choice {
621 pub fn bullets(&self) -> Option<ChoiceBullets> {
622 support::child(&self.syntax)
623 }
624
625 pub fn label(&self) -> Option<Label> {
626 support::child(&self.syntax)
627 }
628
629 pub fn conditions(&self) -> impl Iterator<Item = ChoiceCondition> {
630 support::children(&self.syntax)
631 }
632
633 pub fn start_content(&self) -> Option<ChoiceStartContent> {
634 support::child(&self.syntax)
635 }
636
637 pub fn bracket_content(&self) -> Option<ChoiceBracketContent> {
638 support::child(&self.syntax)
639 }
640
641 pub fn inner_content(&self) -> Option<ChoiceInnerContent> {
642 support::child(&self.syntax)
643 }
644
645 pub fn divert(&self) -> Option<DivertNode> {
646 support::child(&self.syntax)
647 }
648
649 pub fn tags(&self) -> Option<Tags> {
650 support::child(&self.syntax)
651 }
652
653 pub fn all_tags(&self) -> impl Iterator<Item = Tags> {
656 support::children(&self.syntax)
657 }
658}
659
660impl ChoiceBullets {
663 pub fn depth(&self) -> usize {
665 self.syntax
666 .children_with_tokens()
667 .filter_map(rowan::NodeOrToken::into_token)
668 .filter(|tok| matches!(tok.kind(), STAR | PLUS))
669 .count()
670 }
671
672 pub fn is_sticky(&self) -> bool {
677 self.syntax
678 .children_with_tokens()
679 .filter_map(rowan::NodeOrToken::into_token)
680 .find(|tok| matches!(tok.kind(), STAR | PLUS))
681 .is_some_and(|tok| tok.kind() == PLUS)
682 }
683
684 pub fn is_mixed(&self) -> bool {
688 let mut has_star = false;
689 let mut has_plus = false;
690 for tok in self
691 .syntax
692 .children_with_tokens()
693 .filter_map(rowan::NodeOrToken::into_token)
694 {
695 match tok.kind() {
696 STAR => has_star = true,
697 PLUS => has_plus = true,
698 _ => {}
699 }
700 }
701 has_star && has_plus
702 }
703}
704
705impl Label {
708 pub fn identifier(&self) -> Option<Identifier> {
709 support::child(&self.syntax)
710 }
711
712 pub fn name(&self) -> Option<String> {
713 self.identifier().and_then(|id| id.name())
714 }
715}
716
717impl Gather {
720 pub fn dashes(&self) -> Option<GatherDashes> {
721 support::child(&self.syntax)
722 }
723
724 pub fn label(&self) -> Option<Label> {
725 support::child(&self.syntax)
726 }
727
728 pub fn mixed_content(&self) -> Option<MixedContent> {
729 support::child(&self.syntax)
730 }
731
732 pub fn choice(&self) -> Option<Choice> {
734 support::child(&self.syntax)
735 }
736
737 pub fn divert(&self) -> Option<DivertNode> {
738 support::child(&self.syntax)
739 }
740
741 pub fn tags(&self) -> Option<Tags> {
742 support::child(&self.syntax)
743 }
744}
745
746impl GatherDashes {
749 pub fn depth(&self) -> usize {
751 support::tokens(&self.syntax, MINUS).count()
752 }
753}
754
755impl Tags {
758 pub fn tags(&self) -> impl Iterator<Item = Tag> {
759 support::children(&self.syntax)
760 }
761}
762
763impl Tag {
766 pub fn text(&self) -> String {
771 self.syntax
772 .children_with_tokens()
773 .filter_map(rowan::NodeOrToken::into_token)
774 .filter(|tok| tok.kind() != HASH)
775 .map(|tok| tok.text().to_string())
776 .collect::<String>()
777 .trim()
778 .to_string()
779 }
780}
781
782impl InlineLogic {
785 pub fn inner_expression(&self) -> Option<InnerExpression> {
786 support::child(&self.syntax)
787 }
788
789 pub fn conditional(&self) -> Option<ConditionalWithExpr> {
790 support::child(&self.syntax)
791 }
792
793 pub fn sequence(&self) -> Option<SequenceWithAnnotation> {
794 support::child(&self.syntax)
795 }
796
797 pub fn implicit_sequence(&self) -> Option<ImplicitSequence> {
798 support::child(&self.syntax)
799 }
800
801 pub fn multiline_conditional(&self) -> Option<MultilineConditional> {
802 support::child(&self.syntax)
803 }
804}
805
806impl MultilineBlock {
809 pub fn conditional(&self) -> Option<ConditionalWithExpr> {
810 support::child(&self.syntax)
811 }
812
813 pub fn sequence(&self) -> Option<SequenceWithAnnotation> {
814 support::child(&self.syntax)
815 }
816
817 pub fn branches_cond(&self) -> Option<MultilineBranchesCond> {
818 support::child(&self.syntax)
819 }
820}
821
822impl SequenceWithAnnotation {
825 pub fn symbol_annotation(&self) -> Option<SequenceSymbolAnnotation> {
826 support::child(&self.syntax)
827 }
828
829 pub fn word_annotation(&self) -> Option<SequenceWordAnnotation> {
830 support::child(&self.syntax)
831 }
832
833 pub fn inline_branches(&self) -> Option<InlineBranchesSeq> {
834 support::child(&self.syntax)
835 }
836
837 pub fn multiline_branches(&self) -> Option<MultilineBranchesSeq> {
838 support::child(&self.syntax)
839 }
840}
841
842impl SequenceSymbolAnnotation {
845 pub fn amp_token(&self) -> Option<SyntaxToken> {
846 support::token(&self.syntax, AMP)
847 }
848
849 pub fn bang_token(&self) -> Option<SyntaxToken> {
850 support::token(&self.syntax, BANG)
851 }
852
853 pub fn tilde_token(&self) -> Option<SyntaxToken> {
854 support::token(&self.syntax, TILDE)
855 }
856
857 pub fn dollar_token(&self) -> Option<SyntaxToken> {
858 support::token(&self.syntax, DOLLAR)
859 }
860}
861
862impl SequenceWordAnnotation {
865 pub fn stopping_kw(&self) -> Option<SyntaxToken> {
866 support::token(&self.syntax, KW_STOPPING)
867 }
868
869 pub fn cycle_kw(&self) -> Option<SyntaxToken> {
870 support::token(&self.syntax, KW_CYCLE)
871 }
872
873 pub fn shuffle_kw(&self) -> Option<SyntaxToken> {
874 support::token(&self.syntax, KW_SHUFFLE)
875 }
876
877 pub fn once_kw(&self) -> Option<SyntaxToken> {
878 support::token(&self.syntax, KW_ONCE)
879 }
880}
881
882impl InlineBranchesSeq {
885 pub fn branches(&self) -> impl Iterator<Item = BranchContent> {
886 support::children(&self.syntax)
887 }
888}
889
890impl InlineBranchesCond {
893 pub fn branches(&self) -> impl Iterator<Item = BranchContent> {
894 support::children(&self.syntax)
895 }
896}
897
898impl MultilineBranchesSeq {
901 pub fn branches(&self) -> impl Iterator<Item = MultilineBranchSeq> {
902 support::children(&self.syntax)
903 }
904}
905
906impl MultilineBranchesCond {
909 pub fn branches(&self) -> impl Iterator<Item = MultilineBranchCond> {
910 support::children(&self.syntax)
911 }
912}
913
914impl MultilineBranchSeq {
917 pub fn body(&self) -> Option<MultilineBranchBody> {
918 support::child(&self.syntax)
919 }
920}
921
922impl MultilineBranchCond {
925 pub fn condition(&self) -> Option<Expr> {
927 support::child(&self.syntax)
928 }
929
930 pub fn body(&self) -> Option<MultilineBranchBody> {
931 support::child(&self.syntax)
932 }
933
934 pub fn else_kw(&self) -> Option<SyntaxToken> {
935 support::token(&self.syntax, KW_ELSE)
936 }
937
938 pub fn is_else(&self) -> bool {
939 self.else_kw().is_some()
940 }
941}
942
943impl ConditionalWithExpr {
946 pub fn condition(&self) -> Option<Expr> {
948 support::child(&self.syntax)
949 }
950
951 pub fn inline_branches(&self) -> Option<InlineBranchesCond> {
952 support::child(&self.syntax)
953 }
954
955 pub fn multiline_branches(&self) -> Option<MultilineBranchesCond> {
956 support::child(&self.syntax)
957 }
958
959 pub fn branchless_body(&self) -> Option<BranchlessCondBody> {
960 support::child(&self.syntax)
961 }
962}
963
964impl BranchlessCondBody {
967 pub fn texts(&self) -> impl Iterator<Item = Text> {
968 support::children(&self.syntax)
969 }
970
971 pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
972 support::children(&self.syntax)
973 }
974
975 pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
976 support::children(&self.syntax)
977 }
978
979 pub fn escapes(&self) -> impl Iterator<Item = Escape> {
980 support::children(&self.syntax)
981 }
982
983 pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
984 support::children(&self.syntax)
985 }
986
987 pub fn divert(&self) -> Option<DivertNode> {
988 support::child(&self.syntax)
989 }
990
991 pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
992 support::children(&self.syntax)
993 }
994
995 pub fn else_branch(&self) -> Option<ElseBranch> {
996 support::child(&self.syntax)
997 }
998}
999
1000impl ElseBranch {
1003 pub fn branch(&self) -> Option<MultilineBranchCond> {
1004 support::child(&self.syntax)
1005 }
1006}
1007
1008impl MultilineConditional {
1011 pub fn branches(&self) -> impl Iterator<Item = MultilineBranchCond> {
1012 support::children(&self.syntax)
1013 }
1014}
1015
1016impl ImplicitSequence {
1019 pub fn branches(&self) -> impl Iterator<Item = BranchContent> {
1020 support::children(&self.syntax)
1021 }
1022}
1023
1024impl PrefixExpr {
1027 pub fn op_token(&self) -> Option<SyntaxToken> {
1028 self.syntax
1029 .children_with_tokens()
1030 .filter_map(rowan::NodeOrToken::into_token)
1031 .find(|tok| matches!(tok.kind(), MINUS | BANG | KW_NOT))
1032 }
1033
1034 pub fn operand(&self) -> Option<Expr> {
1036 support::child(&self.syntax)
1037 }
1038}
1039
1040impl PostfixExpr {
1043 pub fn op_token(&self) -> Option<SyntaxToken> {
1046 self.syntax
1047 .children_with_tokens()
1048 .filter_map(rowan::NodeOrToken::into_token)
1049 .find(|tok| matches!(tok.kind(), PLUS | MINUS))
1050 }
1051
1052 pub fn operand(&self) -> Option<Expr> {
1054 support::child(&self.syntax)
1055 }
1056}
1057
1058impl InfixExpr {
1061 pub fn op_token(&self) -> Option<SyntaxToken> {
1062 self.syntax
1063 .children_with_tokens()
1064 .filter_map(rowan::NodeOrToken::into_token)
1065 .find(|tok| {
1066 matches!(
1067 tok.kind(),
1068 PLUS | MINUS
1069 | STAR
1070 | SLASH
1071 | PERCENT
1072 | CARET
1073 | EQ_EQ
1074 | BANG_EQ
1075 | LT
1076 | GT
1077 | LT_EQ
1078 | GT_EQ
1079 | KW_AND
1080 | AMP_AMP
1081 | KW_OR
1082 | PIPE
1083 | KW_MOD
1084 | KW_HAS
1085 | KW_HASNT
1086 | QUESTION
1087 | BANG_QUESTION
1088 | PLUS_EQ
1089 | MINUS_EQ
1090 )
1091 })
1092 }
1093
1094 pub fn lhs(&self) -> Option<Expr> {
1095 self.syntax.children().find_map(Expr::cast)
1096 }
1097
1098 pub fn rhs(&self) -> Option<Expr> {
1099 self.syntax.children().filter_map(Expr::cast).nth(1)
1100 }
1101}
1102
1103impl FunctionCall {
1106 pub fn identifier(&self) -> Option<Identifier> {
1107 support::child(&self.syntax)
1108 }
1109
1110 pub fn name(&self) -> Option<String> {
1111 self.identifier().and_then(|id| id.name())
1112 }
1113
1114 pub fn arg_list(&self) -> Option<ArgList> {
1115 support::child(&self.syntax)
1116 }
1117}
1118
1119impl ArgList {
1122 pub fn arg_count(&self) -> usize {
1124 self.syntax
1125 .children()
1126 .filter(|child| child.kind() != SyntaxKind::ERROR)
1127 .count()
1128 }
1129
1130 pub fn args(&self) -> impl Iterator<Item = Expr> {
1132 support::children(&self.syntax)
1133 }
1134}
1135
1136impl DivertTargetExpr {
1139 pub fn target(&self) -> Option<Path> {
1140 support::child(&self.syntax)
1141 }
1142}
1143
1144impl ListExpr {
1147 pub fn items(&self) -> impl Iterator<Item = Path> {
1148 support::children(&self.syntax)
1149 }
1150}
1151
1152impl DivertNode {
1155 pub fn thread_start(&self) -> Option<ThreadStart> {
1156 support::child(&self.syntax)
1157 }
1158
1159 pub fn tunnel_onwards(&self) -> Option<TunnelOnwardsNode> {
1160 support::child(&self.syntax)
1161 }
1162
1163 pub fn tunnel_call(&self) -> Option<TunnelCallNode> {
1164 support::child(&self.syntax)
1165 }
1166
1167 pub fn simple_divert(&self) -> Option<SimpleDivert> {
1168 support::child(&self.syntax)
1169 }
1170}
1171
1172impl SimpleDivert {
1175 pub fn targets(&self) -> impl Iterator<Item = DivertTargetWithArgs> {
1176 support::children(&self.syntax)
1177 }
1178}
1179
1180impl DivertTargetWithArgs {
1183 pub fn path(&self) -> Option<Path> {
1184 support::child(&self.syntax)
1185 }
1186
1187 pub fn done_kw(&self) -> Option<SyntaxToken> {
1188 support::token(&self.syntax, KW_DONE)
1189 }
1190
1191 pub fn end_kw(&self) -> Option<SyntaxToken> {
1192 support::token(&self.syntax, KW_END)
1193 }
1194
1195 pub fn arg_list(&self) -> Option<ArgList> {
1196 support::child(&self.syntax)
1197 }
1198}
1199
1200impl ThreadStart {
1203 pub fn target(&self) -> Option<Path> {
1208 support::child(&self.syntax)
1209 }
1210
1211 pub fn arg_list(&self) -> Option<ArgList> {
1212 support::child(&self.syntax)
1213 }
1214}
1215
1216impl TunnelOnwardsNode {
1219 pub fn targets(&self) -> impl Iterator<Item = DivertTargetWithArgs> {
1220 support::children(&self.syntax)
1221 }
1222
1223 pub fn tunnel_call(&self) -> Option<TunnelCallNode> {
1224 support::child(&self.syntax)
1225 }
1226}
1227
1228impl TunnelCallNode {
1231 pub fn targets(&self) -> impl Iterator<Item = DivertTargetWithArgs> {
1232 support::children(&self.syntax)
1233 }
1234}
1235
1236impl Identifier {
1239 pub fn ident_token(&self) -> Option<SyntaxToken> {
1240 support::token(&self.syntax, IDENT)
1241 }
1242
1243 pub fn name(&self) -> Option<String> {
1246 self.ident_token()
1247 .or_else(|| {
1248 self.syntax
1249 .children_with_tokens()
1250 .filter_map(rowan::NodeOrToken::into_token)
1251 .find(|t| t.kind().is_keyword())
1252 })
1253 .map(|t| t.text().to_string())
1254 }
1255}
1256
1257impl Path {
1260 pub fn segments(&self) -> impl Iterator<Item = SyntaxToken> {
1262 self.syntax
1263 .children_with_tokens()
1264 .filter_map(rowan::NodeOrToken::into_token)
1265 .filter(|t| t.kind() == IDENT || t.kind().is_keyword())
1266 }
1267
1268 pub fn full_name(&self) -> String {
1270 self.segments()
1271 .map(|t| t.text().to_string())
1272 .collect::<Vec<_>>()
1273 .join(".")
1274 }
1275}
1276
1277impl VarDecl {
1280 pub fn identifier(&self) -> Option<Identifier> {
1281 support::child(&self.syntax)
1282 }
1283
1284 pub fn name(&self) -> Option<String> {
1285 self.identifier().and_then(|id| id.name())
1286 }
1287
1288 pub fn value(&self) -> Option<Expr> {
1290 support::child(&self.syntax)
1291 }
1292}
1293
1294impl ConstDecl {
1297 pub fn identifier(&self) -> Option<Identifier> {
1298 support::child(&self.syntax)
1299 }
1300
1301 pub fn name(&self) -> Option<String> {
1302 self.identifier().and_then(|id| id.name())
1303 }
1304
1305 pub fn value(&self) -> Option<Expr> {
1307 support::child(&self.syntax)
1308 }
1309}
1310
1311impl ListDecl {
1314 pub fn identifier(&self) -> Option<Identifier> {
1315 support::child(&self.syntax)
1316 }
1317
1318 pub fn name(&self) -> Option<String> {
1319 self.identifier().and_then(|id| id.name())
1320 }
1321
1322 pub fn definition(&self) -> Option<ListDef> {
1323 support::child(&self.syntax)
1324 }
1325}
1326
1327impl ListDef {
1330 pub fn members(&self) -> impl Iterator<Item = ListMember> {
1331 support::children(&self.syntax)
1332 }
1333}
1334
1335impl ListMember {
1338 pub fn on_member(&self) -> Option<ListMemberOn> {
1339 support::child(&self.syntax)
1340 }
1341
1342 pub fn off_member(&self) -> Option<ListMemberOff> {
1343 support::child(&self.syntax)
1344 }
1345}
1346
1347impl ListMemberOn {
1350 pub fn name_token(&self) -> Option<SyntaxToken> {
1351 support::ident_or_keyword_token(&self.syntax)
1353 }
1354
1355 pub fn name(&self) -> Option<String> {
1356 self.name_token().map(|t| t.text().to_string())
1357 }
1358
1359 pub fn value_token(&self) -> Option<SyntaxToken> {
1360 support::token(&self.syntax, INTEGER)
1361 }
1362
1363 pub fn value(&self) -> Option<i64> {
1365 self.value_token()
1366 .and_then(|t| t.text().parse::<i64>().ok())
1367 }
1368}
1369
1370impl ListMemberOff {
1373 pub fn name_token(&self) -> Option<SyntaxToken> {
1374 support::ident_or_keyword_token(&self.syntax)
1376 }
1377
1378 pub fn name(&self) -> Option<String> {
1379 self.name_token().map(|t| t.text().to_string())
1380 }
1381
1382 pub fn value_token(&self) -> Option<SyntaxToken> {
1383 support::token(&self.syntax, INTEGER)
1384 }
1385
1386 pub fn value(&self) -> Option<i64> {
1388 self.value_token()
1389 .and_then(|t| t.text().parse::<i64>().ok())
1390 }
1391}
1392
1393impl FunctionParamList {
1396 pub fn params(&self) -> impl Iterator<Item = Identifier> {
1398 support::children(&self.syntax)
1399 }
1400}
1401
1402impl IntegerLit {
1405 pub fn value_token(&self) -> Option<SyntaxToken> {
1406 support::token(&self.syntax, INTEGER)
1407 }
1408
1409 pub fn value(&self) -> Option<i64> {
1410 self.value_token()
1411 .and_then(|t| t.text().parse::<i64>().ok())
1412 }
1413}
1414
1415impl FloatLit {
1418 pub fn value_token(&self) -> Option<SyntaxToken> {
1419 support::token(&self.syntax, FLOAT)
1420 }
1421
1422 pub fn value(&self) -> Option<f64> {
1423 self.value_token()
1424 .and_then(|t| t.text().parse::<f64>().ok())
1425 }
1426}
1427
1428impl StringLit {
1431 pub fn raw_text(&self) -> String {
1439 let full = self.syntax.text().to_string();
1440 let trimmed = full.strip_prefix('"').unwrap_or(&full);
1441 trimmed.strip_suffix('"').unwrap_or(trimmed).to_string()
1442 }
1443}
1444
1445impl BooleanLit {
1448 pub fn value(&self) -> Option<bool> {
1449 let tok = self
1450 .syntax
1451 .children_with_tokens()
1452 .filter_map(rowan::NodeOrToken::into_token)
1453 .find(|tok| matches!(tok.kind(), KW_TRUE | KW_FALSE))?;
1454 match tok.kind() {
1455 KW_TRUE => Some(true),
1456 KW_FALSE => Some(false),
1457 _ => None,
1458 }
1459 }
1460}
1461
1462impl AuthorWarning {
1465 pub fn text(&self) -> String {
1470 self.syntax
1471 .children_with_tokens()
1472 .filter_map(rowan::NodeOrToken::into_token)
1473 .skip_while(|tok| matches!(tok.kind(), KW_TODO | COLON) || tok.kind().is_trivia())
1474 .take_while(|tok| tok.kind() != NEWLINE)
1475 .map(|tok| tok.text().to_string())
1476 .collect::<String>()
1477 .trim()
1478 .to_string()
1479 }
1480}
1481
1482impl ChoiceCondition {
1485 pub fn expr(&self) -> Option<Expr> {
1487 support::child(&self.syntax)
1488 }
1489}
1490
1491impl InnerExpression {
1494 pub fn expr(&self) -> Option<Expr> {
1496 support::child(&self.syntax)
1497 }
1498}
1499
1500impl ParenExpr {
1503 pub fn inner(&self) -> Option<Expr> {
1505 support::child(&self.syntax)
1506 }
1507}
1508
1509impl BranchContent {
1512 pub fn divert(&self) -> Option<DivertNode> {
1513 support::child(&self.syntax)
1514 }
1515}
1516
1517impl MultilineBranchBody {
1520 pub fn texts(&self) -> impl Iterator<Item = Text> {
1521 support::children(&self.syntax)
1522 }
1523
1524 pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
1525 support::children(&self.syntax)
1526 }
1527
1528 pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
1529 support::children(&self.syntax)
1530 }
1531
1532 pub fn escapes(&self) -> impl Iterator<Item = Escape> {
1533 support::children(&self.syntax)
1534 }
1535
1536 pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
1537 support::children(&self.syntax)
1538 }
1539
1540 pub fn divert(&self) -> Option<DivertNode> {
1541 support::child(&self.syntax)
1542 }
1543
1544 pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
1545 support::children(&self.syntax)
1546 }
1547
1548 pub fn choices(&self) -> impl Iterator<Item = Choice> {
1549 support::children(&self.syntax)
1550 }
1551}