use crate::SyntaxKind::{
self, AMP, AMP_AMP, BANG, BANG_EQ, BANG_QUESTION, CARET, COLON, DIVERT, DOLLAR, EQ, EQ_EQ,
FLOAT, GT, GT_EQ, HASH, IDENT, INTEGER, KW_AND, KW_CYCLE, KW_DONE, KW_ELSE, KW_END, KW_FALSE,
KW_FUNCTION, KW_HAS, KW_HASNT, KW_MOD, KW_NOT, KW_ONCE, KW_OR, KW_REF, KW_SHUFFLE, KW_STOPPING,
KW_TODO, KW_TRUE, L_PAREN, LT, LT_EQ, MINUS, MINUS_EQ, NEWLINE, PERCENT, PIPE, PLUS, PLUS_EQ,
QUESTION, R_PAREN, SLASH, STAR, TILDE,
};
use crate::ast::AstNode as _;
use crate::ast::ast_node;
use crate::ast::support;
use crate::{SyntaxNode, SyntaxToken};
ast_node!(SourceFile, SOURCE_FILE);
ast_node!(IncludeStmt, INCLUDE_STMT);
ast_node!(ImportStmt, IMPORT_STMT);
ast_node!(ImportList, IMPORT_LIST);
ast_node!(ImportItem, IMPORT_ITEM);
ast_node!(ImportModule, IMPORT_MODULE);
ast_node!(FilePath, FILE_PATH);
ast_node!(ExternalDecl, EXTERNAL_DECL);
ast_node!(KnotDef, KNOT_DEF);
ast_node!(KnotHeader, KNOT_HEADER);
ast_node!(KnotBody, KNOT_BODY);
ast_node!(KnotParams, KNOT_PARAMS);
ast_node!(KnotParamDecl, KNOT_PARAM_DECL);
ast_node!(StitchDef, STITCH_DEF);
ast_node!(StitchHeader, STITCH_HEADER);
ast_node!(StitchBody, STITCH_BODY);
ast_node!(EmptyLine, EMPTY_LINE);
ast_node!(AuthorWarning, AUTHOR_WARNING);
ast_node!(LogicLine, LOGIC_LINE);
ast_node!(ContentLine, CONTENT_LINE);
ast_node!(TagLine, TAG_LINE);
ast_node!(AnnotationLine, ANNOTATION_LINE);
ast_node!(StrayClosingBrace, STRAY_CLOSING_BRACE);
ast_node!(ReturnStmt, RETURN_STMT);
ast_node!(TempDecl, TEMP_DECL);
ast_node!(Assignment, ASSIGNMENT);
ast_node!(AwaitStmt, AWAIT_STMT);
ast_node!(MixedContent, MIXED_CONTENT);
ast_node!(Text, TEXT);
ast_node!(Escape, ESCAPE);
ast_node!(GlueNode, GLUE_NODE);
ast_node!(Choice, CHOICE);
ast_node!(ChoiceBullets, CHOICE_BULLETS);
ast_node!(Label, LABEL);
ast_node!(ChoiceCondition, CHOICE_CONDITION);
ast_node!(ChoiceStartContent, CHOICE_START_CONTENT);
ast_node!(ChoiceBracketContent, CHOICE_BRACKET_CONTENT);
ast_node!(ChoiceInnerContent, CHOICE_INNER_CONTENT);
ast_node!(Gather, GATHER);
ast_node!(GatherDashes, GATHER_DASHES);
ast_node!(Tags, TAGS);
ast_node!(Tag, TAG);
ast_node!(InlineLogic, INLINE_LOGIC);
ast_node!(MultilineBlock, MULTILINE_BLOCK);
ast_node!(SequenceWithAnnotation, SEQUENCE_WITH_ANNOTATION);
ast_node!(SequenceSymbolAnnotation, SEQUENCE_SYMBOL_ANNOTATION);
ast_node!(SequenceWordAnnotation, SEQUENCE_WORD_ANNOTATION);
ast_node!(InlineBranchesSeq, INLINE_BRANCHES_SEQ);
ast_node!(MultilineBranchesSeq, MULTILINE_BRANCHES_SEQ);
ast_node!(MultilineBranchSeq, MULTILINE_BRANCH_SEQ);
ast_node!(BranchContent, BRANCH_CONTENT);
ast_node!(ConditionalWithExpr, CONDITIONAL_WITH_EXPR);
ast_node!(BranchlessCondBody, BRANCHLESS_COND_BODY);
ast_node!(ElseBranch, ELSE_BRANCH);
ast_node!(InlineBranchesCond, INLINE_BRANCHES_COND);
ast_node!(MultilineBranchesCond, MULTILINE_BRANCHES_COND);
ast_node!(MultilineConditional, MULTILINE_CONDITIONAL);
ast_node!(MultilineBranchCond, MULTILINE_BRANCH_COND);
ast_node!(MultilineBranchBody, MULTILINE_BRANCH_BODY);
ast_node!(ImplicitSequence, IMPLICIT_SEQUENCE);
ast_node!(InnerExpression, INNER_EXPRESSION);
ast_node!(PrefixExpr, PREFIX_EXPR);
ast_node!(PostfixExpr, POSTFIX_EXPR);
ast_node!(InfixExpr, INFIX_EXPR);
ast_node!(ParenExpr, PAREN_EXPR);
ast_node!(FunctionCall, FUNCTION_CALL);
ast_node!(ArgList, ARG_LIST);
ast_node!(DivertTargetExpr, DIVERT_TARGET_EXPR);
ast_node!(ListExpr, LIST_EXPR);
ast_node!(ArrayLiteral, ARRAY_LITERAL);
ast_node!(MapLiteral, MAP_LITERAL);
ast_node!(MapEntry, MAP_ENTRY);
ast_node!(IndexExpr, INDEX_EXPR);
ast_node!(RangeExpr, RANGE_EXPR);
ast_node!(StmtBlock, STMT_BLOCK);
ast_node!(IfStmt, IF_STMT);
ast_node!(ElseClause, ELSE_CLAUSE);
ast_node!(WhileStmt, WHILE_STMT);
ast_node!(ForStmt, FOR_STMT);
ast_node!(BreakStmt, BREAK_STMT);
ast_node!(ContinueStmt, CONTINUE_STMT);
ast_node!(ExprStmt, EXPR_STMT);
ast_node!(TypeAnnotation, TYPE_ANNOTATION);
ast_node!(TypeExpr, TYPE_EXPR);
ast_node!(TypeName, TYPE_NAME);
ast_node!(TypeGeneric, TYPE_GENERIC);
ast_node!(TypeFn, TYPE_FN);
ast_node!(StructDecl, STRUCT_DECL);
ast_node!(StructFieldDecl, STRUCT_FIELD_DECL);
ast_node!(StructLiteral, STRUCT_LITERAL);
ast_node!(StructFieldInit, STRUCT_FIELD_INIT);
ast_node!(FieldAccessExpr, FIELD_ACCESS_EXPR);
ast_node!(FnLiteral, FN_LITERAL);
ast_node!(RefExpr, REF_EXPR);
ast_node!(CallExpr, CALL_EXPR);
ast_node!(DivertNode, DIVERT_NODE);
ast_node!(SimpleDivert, SIMPLE_DIVERT);
ast_node!(DivertTargetWithArgs, DIVERT_TARGET_WITH_ARGS);
ast_node!(ThreadStart, THREAD_START);
ast_node!(TunnelOnwardsNode, TUNNEL_ONWARDS_NODE);
ast_node!(TunnelCallNode, TUNNEL_CALL_NODE);
impl TypeAnnotation {
pub fn type_expr(&self) -> Option<TypeExpr> {
support::child(&self.syntax)
}
}
pub enum TypeExprKind {
Name(TypeName),
Generic(TypeGeneric),
Fn(TypeFn),
}
impl TypeExpr {
pub fn kind(&self) -> Option<TypeExprKind> {
if let Some(n) = support::child::<TypeName>(&self.syntax) {
Some(TypeExprKind::Name(n))
} else if let Some(g) = support::child::<TypeGeneric>(&self.syntax) {
Some(TypeExprKind::Generic(g))
} else {
support::child::<TypeFn>(&self.syntax).map(TypeExprKind::Fn)
}
}
}
impl TypeName {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
}
impl TypeGeneric {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn args(&self) -> impl Iterator<Item = TypeExpr> {
support::children(&self.syntax)
}
}
impl TypeFn {
fn type_exprs(&self) -> Vec<TypeExpr> {
support::children(&self.syntax).collect()
}
pub fn params(&self) -> Vec<TypeExpr> {
let mut exprs = self.type_exprs();
if exprs.is_empty() {
return exprs;
}
exprs.pop(); exprs
}
pub fn return_type(&self) -> Option<TypeExpr> {
self.type_exprs().pop()
}
}
ast_node!(Identifier, IDENTIFIER);
ast_node!(Path, PATH);
ast_node!(VarDecl, VAR_DECL);
ast_node!(ConstDecl, CONST_DECL);
ast_node!(ListDecl, LIST_DECL);
ast_node!(ListDef, LIST_DEF);
ast_node!(ListMember, LIST_MEMBER);
ast_node!(ListMemberOn, LIST_MEMBER_ON);
ast_node!(ListMemberOff, LIST_MEMBER_OFF);
ast_node!(FunctionParamList, FUNCTION_PARAM_LIST);
ast_node!(IntegerLit, INTEGER_LIT);
ast_node!(FloatLit, FLOAT_LIT);
ast_node!(StringLit, STRING_LIT);
ast_node!(BooleanLit, BOOLEAN_LIT);
ast_node!(Error, ERROR);
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Expr {
Prefix(PrefixExpr),
Postfix(PostfixExpr),
Infix(InfixExpr),
Paren(ParenExpr),
FunctionCall(FunctionCall),
IntegerLit(IntegerLit),
FloatLit(FloatLit),
StringLit(StringLit),
BooleanLit(BooleanLit),
Path(Path),
ListExpr(ListExpr),
DivertTarget(DivertTargetExpr),
ArrayLiteral(ArrayLiteral),
MapLiteral(MapLiteral),
Index(IndexExpr),
StructLiteral(StructLiteral),
FieldAccess(FieldAccessExpr),
FnLiteral(FnLiteral),
RefExpr(RefExpr),
ComputedCall(CallExpr),
Range(RangeExpr),
}
impl std::fmt::Debug for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.syntax().text(), f)
}
}
impl crate::ast::AstNode for Expr {
fn can_cast(kind: SyntaxKind) -> bool {
matches!(
kind,
SyntaxKind::PREFIX_EXPR
| SyntaxKind::POSTFIX_EXPR
| SyntaxKind::INFIX_EXPR
| SyntaxKind::PAREN_EXPR
| SyntaxKind::FUNCTION_CALL
| SyntaxKind::INTEGER_LIT
| SyntaxKind::FLOAT_LIT
| SyntaxKind::STRING_LIT
| SyntaxKind::BOOLEAN_LIT
| SyntaxKind::PATH
| SyntaxKind::LIST_EXPR
| SyntaxKind::DIVERT_TARGET_EXPR
| SyntaxKind::ARRAY_LITERAL
| SyntaxKind::MAP_LITERAL
| SyntaxKind::INDEX_EXPR
| SyntaxKind::STRUCT_LITERAL
| SyntaxKind::FIELD_ACCESS_EXPR
| SyntaxKind::FN_LITERAL
| SyntaxKind::REF_EXPR
| SyntaxKind::CALL_EXPR
| SyntaxKind::RANGE_EXPR
)
}
fn cast(node: SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::PREFIX_EXPR => PrefixExpr::cast(node).map(Expr::Prefix),
SyntaxKind::POSTFIX_EXPR => PostfixExpr::cast(node).map(Expr::Postfix),
SyntaxKind::INFIX_EXPR => InfixExpr::cast(node).map(Expr::Infix),
SyntaxKind::PAREN_EXPR => ParenExpr::cast(node).map(Expr::Paren),
SyntaxKind::FUNCTION_CALL => FunctionCall::cast(node).map(Expr::FunctionCall),
SyntaxKind::INTEGER_LIT => IntegerLit::cast(node).map(Expr::IntegerLit),
SyntaxKind::FLOAT_LIT => FloatLit::cast(node).map(Expr::FloatLit),
SyntaxKind::STRING_LIT => StringLit::cast(node).map(Expr::StringLit),
SyntaxKind::BOOLEAN_LIT => BooleanLit::cast(node).map(Expr::BooleanLit),
SyntaxKind::PATH => Path::cast(node).map(Expr::Path),
SyntaxKind::LIST_EXPR => ListExpr::cast(node).map(Expr::ListExpr),
SyntaxKind::DIVERT_TARGET_EXPR => DivertTargetExpr::cast(node).map(Expr::DivertTarget),
SyntaxKind::ARRAY_LITERAL => ArrayLiteral::cast(node).map(Expr::ArrayLiteral),
SyntaxKind::MAP_LITERAL => MapLiteral::cast(node).map(Expr::MapLiteral),
SyntaxKind::INDEX_EXPR => IndexExpr::cast(node).map(Expr::Index),
SyntaxKind::STRUCT_LITERAL => StructLiteral::cast(node).map(Expr::StructLiteral),
SyntaxKind::FIELD_ACCESS_EXPR => FieldAccessExpr::cast(node).map(Expr::FieldAccess),
SyntaxKind::FN_LITERAL => FnLiteral::cast(node).map(Expr::FnLiteral),
SyntaxKind::REF_EXPR => RefExpr::cast(node).map(Expr::RefExpr),
SyntaxKind::CALL_EXPR => CallExpr::cast(node).map(Expr::ComputedCall),
SyntaxKind::RANGE_EXPR => RangeExpr::cast(node).map(Expr::Range),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode {
match self {
Expr::Prefix(n) => n.syntax(),
Expr::Postfix(n) => n.syntax(),
Expr::Infix(n) => n.syntax(),
Expr::Paren(n) => n.syntax(),
Expr::FunctionCall(n) => n.syntax(),
Expr::IntegerLit(n) => n.syntax(),
Expr::FloatLit(n) => n.syntax(),
Expr::StringLit(n) => n.syntax(),
Expr::BooleanLit(n) => n.syntax(),
Expr::Path(n) => n.syntax(),
Expr::ListExpr(n) => n.syntax(),
Expr::DivertTarget(n) => n.syntax(),
Expr::ArrayLiteral(n) => n.syntax(),
Expr::MapLiteral(n) => n.syntax(),
Expr::Index(n) => n.syntax(),
Expr::StructLiteral(n) => n.syntax(),
Expr::FieldAccess(n) => n.syntax(),
Expr::FnLiteral(n) => n.syntax(),
Expr::RefExpr(n) => n.syntax(),
Expr::ComputedCall(n) => n.syntax(),
Expr::Range(n) => n.syntax(),
}
}
}
macro_rules! content_node_accessors {
($name:ident) => {
impl $name {
pub fn texts(&self) -> impl Iterator<Item = Text> {
support::children(&self.syntax)
}
pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
support::children(&self.syntax)
}
pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
support::children(&self.syntax)
}
pub fn escapes(&self) -> impl Iterator<Item = Escape> {
support::children(&self.syntax)
}
}
};
}
content_node_accessors!(ChoiceStartContent);
content_node_accessors!(ChoiceBracketContent);
content_node_accessors!(ChoiceInnerContent);
content_node_accessors!(BranchContent);
impl SourceFile {
pub fn knots(&self) -> impl Iterator<Item = KnotDef> {
support::children(&self.syntax)
}
pub fn includes(&self) -> impl Iterator<Item = IncludeStmt> {
support::children(&self.syntax)
}
pub fn imports(&self) -> impl Iterator<Item = ImportStmt> {
support::children(&self.syntax)
}
pub fn externals(&self) -> impl Iterator<Item = ExternalDecl> {
support::children(&self.syntax)
}
pub fn stitches(&self) -> impl Iterator<Item = StitchDef> {
support::children(&self.syntax)
}
pub fn var_decls(&self) -> impl Iterator<Item = VarDecl> {
support::children(&self.syntax)
}
pub fn const_decls(&self) -> impl Iterator<Item = ConstDecl> {
support::children(&self.syntax)
}
pub fn list_decls(&self) -> impl Iterator<Item = ListDecl> {
support::children(&self.syntax)
}
pub fn struct_decls(&self) -> impl Iterator<Item = StructDecl> {
support::children(&self.syntax)
}
pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
support::children(&self.syntax)
}
pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
support::children(&self.syntax)
}
pub fn choices(&self) -> impl Iterator<Item = Choice> {
support::children(&self.syntax)
}
pub fn gathers(&self) -> impl Iterator<Item = Gather> {
support::children(&self.syntax)
}
}
impl IncludeStmt {
pub fn file_path(&self) -> Option<FilePath> {
support::child(&self.syntax)
}
}
impl ImportStmt {
pub fn list(&self) -> Option<ImportList> {
support::child(&self.syntax)
}
pub fn module(&self) -> Option<ImportModule> {
support::child(&self.syntax)
}
}
impl ImportList {
pub fn items(&self) -> impl Iterator<Item = ImportItem> {
support::children(&self.syntax)
}
}
impl ImportItem {
fn identifiers(&self) -> impl Iterator<Item = Identifier> {
support::children(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifiers().next().and_then(|id| id.name())
}
pub fn alias(&self) -> Option<String> {
self.identifiers().nth(1).and_then(|id| id.name())
}
}
impl ImportModule {
pub fn name(&self) -> Option<String> {
support::child::<Identifier>(&self.syntax).and_then(|id| id.name())
}
}
impl FilePath {
pub fn text(&self) -> String {
self.syntax.text().to_string()
}
}
impl ExternalDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn param_list(&self) -> Option<FunctionParamList> {
support::child(&self.syntax)
}
}
impl KnotDef {
pub fn header(&self) -> Option<KnotHeader> {
support::child(&self.syntax)
}
pub fn body(&self) -> Option<KnotBody> {
support::child(&self.syntax)
}
}
impl KnotHeader {
pub fn function_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_FUNCTION)
}
pub fn is_function(&self) -> bool {
self.function_kw().is_some()
}
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn params(&self) -> Option<KnotParams> {
support::child(&self.syntax)
}
pub fn return_type(&self) -> Option<TypeAnnotation> {
support::child(&self.syntax)
}
}
impl KnotBody {
pub fn stitches(&self) -> impl Iterator<Item = StitchDef> {
support::children(&self.syntax)
}
pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
support::children(&self.syntax)
}
pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
support::children(&self.syntax)
}
pub fn choices(&self) -> impl Iterator<Item = Choice> {
support::children(&self.syntax)
}
pub fn gathers(&self) -> impl Iterator<Item = Gather> {
support::children(&self.syntax)
}
}
impl KnotParams {
pub fn params(&self) -> impl Iterator<Item = KnotParamDecl> {
support::children(&self.syntax)
}
}
impl KnotParamDecl {
pub fn divert_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, DIVERT)
}
pub fn is_divert(&self) -> bool {
self.divert_token().is_some()
}
pub fn ref_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_REF)
}
pub fn is_ref(&self) -> bool {
self.ref_kw().is_some()
}
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn type_annotation(&self) -> Option<TypeAnnotation> {
support::child(&self.syntax)
}
}
impl StitchDef {
pub fn header(&self) -> Option<StitchHeader> {
support::child(&self.syntax)
}
pub fn body(&self) -> Option<StitchBody> {
support::child(&self.syntax)
}
}
impl StitchHeader {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn params(&self) -> Option<KnotParams> {
support::child(&self.syntax)
}
pub fn return_type(&self) -> Option<TypeAnnotation> {
support::child(&self.syntax)
}
}
impl StitchBody {
pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
support::children(&self.syntax)
}
pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
support::children(&self.syntax)
}
pub fn choices(&self) -> impl Iterator<Item = Choice> {
support::children(&self.syntax)
}
pub fn gathers(&self) -> impl Iterator<Item = Gather> {
support::children(&self.syntax)
}
}
impl ContentLine {
pub fn mixed_content(&self) -> Option<MixedContent> {
support::child(&self.syntax)
}
pub fn divert(&self) -> Option<DivertNode> {
support::child(&self.syntax)
}
pub fn tags(&self) -> Option<Tags> {
support::child(&self.syntax)
}
}
impl LogicLine {
pub fn return_stmt(&self) -> Option<ReturnStmt> {
support::child(&self.syntax)
}
pub fn temp_decl(&self) -> Option<TempDecl> {
support::child(&self.syntax)
}
pub fn assignment(&self) -> Option<Assignment> {
support::child(&self.syntax)
}
pub fn await_stmt(&self) -> Option<AwaitStmt> {
support::child(&self.syntax)
}
pub fn stmt_block(&self) -> Option<StmtBlock> {
support::child(&self.syntax)
}
}
impl TagLine {
pub fn tags(&self) -> Option<Tags> {
support::child(&self.syntax)
}
}
impl AnnotationLine {
pub fn name_token(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|t| t.kind() == IDENT)
}
pub fn arg_text(&self) -> Option<String> {
let mut depth = 0usize;
let mut collecting = false;
let mut out = String::new();
for el in self.syntax.children_with_tokens() {
let rowan::NodeOrToken::Token(tok) = el else {
continue;
};
match tok.kind() {
L_PAREN => {
if collecting {
out.push_str(tok.text());
}
depth += 1;
collecting = true;
}
R_PAREN => {
depth = depth.saturating_sub(1);
if depth == 0 {
return Some(out);
}
out.push_str(tok.text());
}
_ if collecting => out.push_str(tok.text()),
_ => {}
}
}
collecting.then_some(out)
}
}
impl ReturnStmt {
pub fn value(&self) -> Option<Expr> {
support::child(&self.syntax)
}
pub fn has_value(&self) -> bool {
self.value().is_some()
}
}
impl AwaitStmt {
pub fn condition(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
}
impl TempDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn type_annotation(&self) -> Option<TypeAnnotation> {
support::child(&self.syntax)
}
pub fn eq_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, EQ)
}
pub fn value(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl Assignment {
pub fn target(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn op_token(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|tok| matches!(tok.kind(), EQ | PLUS_EQ | MINUS_EQ))
}
pub fn value(&self) -> Option<Expr> {
self.syntax.children().filter_map(Expr::cast).nth(1)
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum BlockStmt {
TempDecl(TempDecl),
Assignment(Assignment),
Return(ReturnStmt),
If(IfStmt),
While(WhileStmt),
For(ForStmt),
Break(BreakStmt),
Continue(ContinueStmt),
ExprStmt(ExprStmt),
Await(AwaitStmt),
}
impl std::fmt::Debug for BlockStmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self.syntax(), f)
}
}
impl crate::ast::AstNode for BlockStmt {
fn can_cast(kind: SyntaxKind) -> bool {
matches!(
kind,
SyntaxKind::TEMP_DECL
| SyntaxKind::ASSIGNMENT
| SyntaxKind::RETURN_STMT
| SyntaxKind::IF_STMT
| SyntaxKind::WHILE_STMT
| SyntaxKind::FOR_STMT
| SyntaxKind::BREAK_STMT
| SyntaxKind::CONTINUE_STMT
| SyntaxKind::EXPR_STMT
| SyntaxKind::AWAIT_STMT
)
}
fn cast(node: SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::TEMP_DECL => TempDecl::cast(node).map(BlockStmt::TempDecl),
SyntaxKind::ASSIGNMENT => Assignment::cast(node).map(BlockStmt::Assignment),
SyntaxKind::RETURN_STMT => ReturnStmt::cast(node).map(BlockStmt::Return),
SyntaxKind::IF_STMT => IfStmt::cast(node).map(BlockStmt::If),
SyntaxKind::WHILE_STMT => WhileStmt::cast(node).map(BlockStmt::While),
SyntaxKind::FOR_STMT => ForStmt::cast(node).map(BlockStmt::For),
SyntaxKind::BREAK_STMT => BreakStmt::cast(node).map(BlockStmt::Break),
SyntaxKind::CONTINUE_STMT => ContinueStmt::cast(node).map(BlockStmt::Continue),
SyntaxKind::EXPR_STMT => ExprStmt::cast(node).map(BlockStmt::ExprStmt),
SyntaxKind::AWAIT_STMT => AwaitStmt::cast(node).map(BlockStmt::Await),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode {
match self {
BlockStmt::TempDecl(n) => n.syntax(),
BlockStmt::Assignment(n) => n.syntax(),
BlockStmt::Return(n) => n.syntax(),
BlockStmt::If(n) => n.syntax(),
BlockStmt::While(n) => n.syntax(),
BlockStmt::For(n) => n.syntax(),
BlockStmt::Break(n) => n.syntax(),
BlockStmt::Continue(n) => n.syntax(),
BlockStmt::ExprStmt(n) => n.syntax(),
BlockStmt::Await(n) => n.syntax(),
}
}
}
impl StmtBlock {
pub fn stmts(&self) -> impl Iterator<Item = BlockStmt> {
support::children(&self.syntax)
}
}
impl IfStmt {
pub fn condition(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn body(&self) -> Option<StmtBlock> {
support::child(&self.syntax)
}
pub fn else_clause(&self) -> Option<ElseClause> {
support::child(&self.syntax)
}
}
impl ElseClause {
pub fn if_stmt(&self) -> Option<IfStmt> {
support::child(&self.syntax)
}
pub fn body(&self) -> Option<StmtBlock> {
support::child(&self.syntax)
}
}
impl WhileStmt {
pub fn condition(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn body(&self) -> Option<StmtBlock> {
support::child(&self.syntax)
}
pub fn is_await(&self) -> bool {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.any(|tok| tok.kind() == SyntaxKind::IDENT && tok.text() == "await")
}
}
impl ForStmt {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn iterable(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn body(&self) -> Option<StmtBlock> {
support::child(&self.syntax)
}
}
impl ExprStmt {
pub fn expr(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl ArrayLiteral {
pub fn elements(&self) -> impl Iterator<Item = Expr> {
support::children(&self.syntax)
}
}
impl MapLiteral {
pub fn entries(&self) -> impl Iterator<Item = MapEntry> {
support::children(&self.syntax)
}
}
impl MapEntry {
pub fn key(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn value(&self) -> Option<Expr> {
self.syntax.children().filter_map(Expr::cast).nth(1)
}
}
impl IndexExpr {
pub fn base(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn index(&self) -> Option<Expr> {
self.syntax.children().filter_map(Expr::cast).nth(1)
}
}
impl RangeExpr {
pub fn start(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn end(&self) -> Option<Expr> {
self.syntax.children().filter_map(Expr::cast).nth(1)
}
pub fn is_inclusive(&self) -> bool {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.any(|t| t.kind() == SyntaxKind::EQ)
}
}
impl StructDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn fields(&self) -> impl Iterator<Item = StructFieldDecl> {
support::children(&self.syntax)
}
}
impl StructFieldDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn type_expr(&self) -> Option<TypeExpr> {
support::child(&self.syntax)
}
}
impl StructLiteral {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn shape_name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn fields(&self) -> impl Iterator<Item = StructFieldInit> {
support::children(&self.syntax)
}
}
impl StructFieldInit {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn value(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl FieldAccessExpr {
pub fn base(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn field(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn field_name(&self) -> Option<String> {
self.field().and_then(|id| id.name())
}
}
impl FnLiteral {
pub fn target(&self) -> Option<Path> {
support::child(&self.syntax)
}
pub fn args(&self) -> impl Iterator<Item = Expr> {
let target_node = self.target().map(|t| t.syntax().clone());
self.syntax
.children()
.filter_map(Expr::cast)
.filter(move |e| Some(e.syntax()) != target_node.as_ref())
}
}
impl RefExpr {
pub fn ref_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_REF)
}
pub fn operand(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl MixedContent {
pub fn texts(&self) -> impl Iterator<Item = Text> {
support::children(&self.syntax)
}
pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
support::children(&self.syntax)
}
pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
support::children(&self.syntax)
}
pub fn escapes(&self) -> impl Iterator<Item = Escape> {
support::children(&self.syntax)
}
}
impl Choice {
pub fn bullets(&self) -> Option<ChoiceBullets> {
support::child(&self.syntax)
}
pub fn label(&self) -> Option<Label> {
support::child(&self.syntax)
}
pub fn conditions(&self) -> impl Iterator<Item = ChoiceCondition> {
support::children(&self.syntax)
}
pub fn start_content(&self) -> Option<ChoiceStartContent> {
support::child(&self.syntax)
}
pub fn bracket_content(&self) -> Option<ChoiceBracketContent> {
support::child(&self.syntax)
}
pub fn inner_content(&self) -> Option<ChoiceInnerContent> {
support::child(&self.syntax)
}
pub fn divert(&self) -> Option<DivertNode> {
support::child(&self.syntax)
}
pub fn tags(&self) -> Option<Tags> {
support::child(&self.syntax)
}
pub fn all_tags(&self) -> impl Iterator<Item = Tags> {
support::children(&self.syntax)
}
}
impl ChoiceBullets {
pub fn depth(&self) -> usize {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.filter(|tok| matches!(tok.kind(), STAR | PLUS))
.count()
}
pub fn is_sticky(&self) -> bool {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|tok| matches!(tok.kind(), STAR | PLUS))
.is_some_and(|tok| tok.kind() == PLUS)
}
pub fn is_mixed(&self) -> bool {
let mut has_star = false;
let mut has_plus = false;
for tok in self
.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
{
match tok.kind() {
STAR => has_star = true,
PLUS => has_plus = true,
_ => {}
}
}
has_star && has_plus
}
}
impl Label {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
}
impl Gather {
pub fn dashes(&self) -> Option<GatherDashes> {
support::child(&self.syntax)
}
pub fn label(&self) -> Option<Label> {
support::child(&self.syntax)
}
pub fn mixed_content(&self) -> Option<MixedContent> {
support::child(&self.syntax)
}
pub fn choice(&self) -> Option<Choice> {
support::child(&self.syntax)
}
pub fn divert(&self) -> Option<DivertNode> {
support::child(&self.syntax)
}
pub fn tags(&self) -> Option<Tags> {
support::child(&self.syntax)
}
}
impl GatherDashes {
pub fn depth(&self) -> usize {
support::tokens(&self.syntax, MINUS).count()
}
}
impl Tags {
pub fn tags(&self) -> impl Iterator<Item = Tag> {
support::children(&self.syntax)
}
}
impl Tag {
pub fn text(&self) -> String {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.filter(|tok| tok.kind() != HASH)
.map(|tok| tok.text().to_string())
.collect::<String>()
.trim()
.to_string()
}
}
impl InlineLogic {
pub fn inner_expression(&self) -> Option<InnerExpression> {
support::child(&self.syntax)
}
pub fn conditional(&self) -> Option<ConditionalWithExpr> {
support::child(&self.syntax)
}
pub fn sequence(&self) -> Option<SequenceWithAnnotation> {
support::child(&self.syntax)
}
pub fn implicit_sequence(&self) -> Option<ImplicitSequence> {
support::child(&self.syntax)
}
pub fn multiline_conditional(&self) -> Option<MultilineConditional> {
support::child(&self.syntax)
}
}
impl MultilineBlock {
pub fn conditional(&self) -> Option<ConditionalWithExpr> {
support::child(&self.syntax)
}
pub fn sequence(&self) -> Option<SequenceWithAnnotation> {
support::child(&self.syntax)
}
pub fn branches_cond(&self) -> Option<MultilineBranchesCond> {
support::child(&self.syntax)
}
}
impl SequenceWithAnnotation {
pub fn symbol_annotation(&self) -> Option<SequenceSymbolAnnotation> {
support::child(&self.syntax)
}
pub fn word_annotation(&self) -> Option<SequenceWordAnnotation> {
support::child(&self.syntax)
}
pub fn inline_branches(&self) -> Option<InlineBranchesSeq> {
support::child(&self.syntax)
}
pub fn multiline_branches(&self) -> Option<MultilineBranchesSeq> {
support::child(&self.syntax)
}
}
impl SequenceSymbolAnnotation {
pub fn amp_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, AMP)
}
pub fn bang_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, BANG)
}
pub fn tilde_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, TILDE)
}
pub fn dollar_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, DOLLAR)
}
}
impl SequenceWordAnnotation {
pub fn stopping_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_STOPPING)
}
pub fn cycle_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_CYCLE)
}
pub fn shuffle_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_SHUFFLE)
}
pub fn once_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_ONCE)
}
}
impl InlineBranchesSeq {
pub fn branches(&self) -> impl Iterator<Item = BranchContent> {
support::children(&self.syntax)
}
}
impl InlineBranchesCond {
pub fn branches(&self) -> impl Iterator<Item = BranchContent> {
support::children(&self.syntax)
}
}
impl MultilineBranchesSeq {
pub fn branches(&self) -> impl Iterator<Item = MultilineBranchSeq> {
support::children(&self.syntax)
}
}
impl MultilineBranchesCond {
pub fn branches(&self) -> impl Iterator<Item = MultilineBranchCond> {
support::children(&self.syntax)
}
}
impl MultilineBranchSeq {
pub fn body(&self) -> Option<MultilineBranchBody> {
support::child(&self.syntax)
}
}
impl MultilineBranchCond {
pub fn condition(&self) -> Option<Expr> {
support::child(&self.syntax)
}
pub fn body(&self) -> Option<MultilineBranchBody> {
support::child(&self.syntax)
}
pub fn else_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_ELSE)
}
pub fn is_else(&self) -> bool {
self.else_kw().is_some()
}
}
impl ConditionalWithExpr {
pub fn condition(&self) -> Option<Expr> {
support::child(&self.syntax)
}
pub fn inline_branches(&self) -> Option<InlineBranchesCond> {
support::child(&self.syntax)
}
pub fn multiline_branches(&self) -> Option<MultilineBranchesCond> {
support::child(&self.syntax)
}
pub fn branchless_body(&self) -> Option<BranchlessCondBody> {
support::child(&self.syntax)
}
}
impl BranchlessCondBody {
pub fn texts(&self) -> impl Iterator<Item = Text> {
support::children(&self.syntax)
}
pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
support::children(&self.syntax)
}
pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
support::children(&self.syntax)
}
pub fn escapes(&self) -> impl Iterator<Item = Escape> {
support::children(&self.syntax)
}
pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
support::children(&self.syntax)
}
pub fn divert(&self) -> Option<DivertNode> {
support::child(&self.syntax)
}
pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
support::children(&self.syntax)
}
pub fn else_branch(&self) -> Option<ElseBranch> {
support::child(&self.syntax)
}
}
impl ElseBranch {
pub fn branch(&self) -> Option<MultilineBranchCond> {
support::child(&self.syntax)
}
}
impl MultilineConditional {
pub fn branches(&self) -> impl Iterator<Item = MultilineBranchCond> {
support::children(&self.syntax)
}
}
impl ImplicitSequence {
pub fn branches(&self) -> impl Iterator<Item = BranchContent> {
support::children(&self.syntax)
}
}
impl PrefixExpr {
pub fn op_token(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|tok| matches!(tok.kind(), MINUS | BANG | KW_NOT))
}
pub fn operand(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl PostfixExpr {
pub fn op_token(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|tok| matches!(tok.kind(), PLUS | MINUS))
}
pub fn operand(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl InfixExpr {
pub fn op_token(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|tok| {
matches!(
tok.kind(),
PLUS | MINUS
| STAR
| SLASH
| PERCENT
| CARET
| EQ_EQ
| BANG_EQ
| LT
| GT
| LT_EQ
| GT_EQ
| KW_AND
| AMP_AMP
| KW_OR
| PIPE
| KW_MOD
| KW_HAS
| KW_HASNT
| QUESTION
| BANG_QUESTION
| PLUS_EQ
| MINUS_EQ
)
})
}
pub fn lhs(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn rhs(&self) -> Option<Expr> {
self.syntax.children().filter_map(Expr::cast).nth(1)
}
}
impl FunctionCall {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn arg_list(&self) -> Option<ArgList> {
support::child(&self.syntax)
}
}
impl CallExpr {
pub fn callee(&self) -> Option<Expr> {
self.syntax.children().find_map(Expr::cast)
}
pub fn arg_list(&self) -> Option<ArgList> {
support::child(&self.syntax)
}
}
impl ArgList {
pub fn arg_count(&self) -> usize {
self.syntax
.children()
.filter(|child| child.kind() != SyntaxKind::ERROR)
.count()
}
pub fn args(&self) -> impl Iterator<Item = Expr> {
support::children(&self.syntax)
}
}
impl DivertTargetExpr {
pub fn target(&self) -> Option<Path> {
support::child(&self.syntax)
}
}
impl ListExpr {
pub fn items(&self) -> impl Iterator<Item = Path> {
support::children(&self.syntax)
}
}
impl DivertNode {
pub fn thread_start(&self) -> Option<ThreadStart> {
support::child(&self.syntax)
}
pub fn tunnel_onwards(&self) -> Option<TunnelOnwardsNode> {
support::child(&self.syntax)
}
pub fn tunnel_call(&self) -> Option<TunnelCallNode> {
support::child(&self.syntax)
}
pub fn simple_divert(&self) -> Option<SimpleDivert> {
support::child(&self.syntax)
}
}
impl SimpleDivert {
pub fn targets(&self) -> impl Iterator<Item = DivertTargetWithArgs> {
support::children(&self.syntax)
}
}
impl DivertTargetWithArgs {
pub fn path(&self) -> Option<Path> {
support::child(&self.syntax)
}
pub fn done_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_DONE)
}
pub fn end_kw(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, KW_END)
}
pub fn arg_list(&self) -> Option<ArgList> {
support::child(&self.syntax)
}
}
impl ThreadStart {
pub fn target(&self) -> Option<Path> {
support::child(&self.syntax)
}
pub fn arg_list(&self) -> Option<ArgList> {
support::child(&self.syntax)
}
}
impl TunnelOnwardsNode {
pub fn targets(&self) -> impl Iterator<Item = DivertTargetWithArgs> {
support::children(&self.syntax)
}
pub fn tunnel_call(&self) -> Option<TunnelCallNode> {
support::child(&self.syntax)
}
}
impl TunnelCallNode {
pub fn targets(&self) -> impl Iterator<Item = DivertTargetWithArgs> {
support::children(&self.syntax)
}
}
impl Identifier {
pub fn ident_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, IDENT)
}
pub fn name(&self) -> Option<String> {
self.ident_token()
.or_else(|| {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|t| t.kind().is_keyword())
})
.map(|t| t.text().to_string())
}
}
impl Path {
pub fn segments(&self) -> impl Iterator<Item = SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.filter(|t| t.kind() == IDENT || t.kind().is_keyword())
}
pub fn full_name(&self) -> String {
self.segments()
.map(|t| t.text().to_string())
.collect::<Vec<_>>()
.join(".")
}
}
impl VarDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn type_annotation(&self) -> Option<TypeAnnotation> {
support::child(&self.syntax)
}
pub fn value(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl ConstDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn type_annotation(&self) -> Option<TypeAnnotation> {
support::child(&self.syntax)
}
pub fn value(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl ListDecl {
pub fn identifier(&self) -> Option<Identifier> {
support::child(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.identifier().and_then(|id| id.name())
}
pub fn definition(&self) -> Option<ListDef> {
support::child(&self.syntax)
}
}
impl ListDef {
pub fn members(&self) -> impl Iterator<Item = ListMember> {
support::children(&self.syntax)
}
}
impl ListMember {
pub fn on_member(&self) -> Option<ListMemberOn> {
support::child(&self.syntax)
}
pub fn off_member(&self) -> Option<ListMemberOff> {
support::child(&self.syntax)
}
}
impl ListMemberOn {
pub fn name_token(&self) -> Option<SyntaxToken> {
support::ident_or_keyword_token(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.name_token().map(|t| t.text().to_string())
}
pub fn value_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, INTEGER)
}
pub fn value(&self) -> Option<i64> {
self.value_token()
.and_then(|t| t.text().parse::<i64>().ok())
}
}
impl ListMemberOff {
pub fn name_token(&self) -> Option<SyntaxToken> {
support::ident_or_keyword_token(&self.syntax)
}
pub fn name(&self) -> Option<String> {
self.name_token().map(|t| t.text().to_string())
}
pub fn value_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, INTEGER)
}
pub fn value(&self) -> Option<i64> {
self.value_token()
.and_then(|t| t.text().parse::<i64>().ok())
}
}
impl FunctionParamList {
pub fn params(&self) -> impl Iterator<Item = Identifier> {
support::children(&self.syntax)
}
}
impl IntegerLit {
pub fn value_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, INTEGER)
}
pub fn value(&self) -> Option<i64> {
self.value_token()
.and_then(|t| t.text().parse::<i64>().ok())
}
}
impl FloatLit {
pub fn value_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, FLOAT)
}
pub fn value(&self) -> Option<f64> {
self.value_token()
.and_then(|t| t.text().parse::<f64>().ok())
}
}
impl StringLit {
pub fn raw_text(&self) -> String {
let full = self.syntax.text().to_string();
let trimmed = full.strip_prefix('"').unwrap_or(&full);
trimmed.strip_suffix('"').unwrap_or(trimmed).to_string()
}
}
impl BooleanLit {
pub fn value(&self) -> Option<bool> {
let tok = self
.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.find(|tok| matches!(tok.kind(), KW_TRUE | KW_FALSE))?;
match tok.kind() {
KW_TRUE => Some(true),
KW_FALSE => Some(false),
_ => None,
}
}
}
impl AuthorWarning {
pub fn text(&self) -> String {
self.syntax
.children_with_tokens()
.filter_map(rowan::NodeOrToken::into_token)
.skip_while(|tok| matches!(tok.kind(), KW_TODO | COLON) || tok.kind().is_trivia())
.take_while(|tok| tok.kind() != NEWLINE)
.map(|tok| tok.text().to_string())
.collect::<String>()
.trim()
.to_string()
}
}
impl ChoiceCondition {
pub fn expr(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl InnerExpression {
pub fn expr(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl ParenExpr {
pub fn inner(&self) -> Option<Expr> {
support::child(&self.syntax)
}
}
impl BranchContent {
pub fn divert(&self) -> Option<DivertNode> {
support::child(&self.syntax)
}
}
impl MultilineBranchBody {
pub fn texts(&self) -> impl Iterator<Item = Text> {
support::children(&self.syntax)
}
pub fn inline_logics(&self) -> impl Iterator<Item = InlineLogic> {
support::children(&self.syntax)
}
pub fn glue_nodes(&self) -> impl Iterator<Item = GlueNode> {
support::children(&self.syntax)
}
pub fn escapes(&self) -> impl Iterator<Item = Escape> {
support::children(&self.syntax)
}
pub fn logic_lines(&self) -> impl Iterator<Item = LogicLine> {
support::children(&self.syntax)
}
pub fn divert(&self) -> Option<DivertNode> {
support::child(&self.syntax)
}
pub fn content_lines(&self) -> impl Iterator<Item = ContentLine> {
support::children(&self.syntax)
}
pub fn choices(&self) -> impl Iterator<Item = Choice> {
support::children(&self.syntax)
}
}