//! Provides a type system for the AST, in some sense mod expr_ext; mod interpol; mod nodes; mod operators; mod path_util; pub use path_util::Path; mod str_util; mod tokens; use crate::{NixLanguage, SyntaxKind, SyntaxToken}; pub use expr_ext::LiteralKind; pub use interpol::*; pub use nodes::*; pub use operators::{BinOpKind, UnaryOpKind}; pub use tokens::*; pub trait AstNode: rowan::ast::AstNode {} impl AstNode for T where T: rowan::ast::AstNode {} pub trait AstToken { fn can_cast(from: SyntaxKind) -> bool where Self: Sized; /// Cast an untyped token into this strongly-typed token. This will return /// None if the type was not correct. fn cast(from: SyntaxToken) -> Option where Self: Sized; fn syntax(&self) -> &SyntaxToken; } mod support { use rowan::ast::AstChildren; use super::{AstNode, AstToken}; use crate::{SyntaxElement, SyntaxKind, SyntaxToken}; pub(super) fn nth(parent: &N, n: usize) -> Option { parent.syntax().children().flat_map(NN::cast).nth(n) } pub(super) fn children(parent: &N) -> AstChildren { rowan::ast::support::children(parent.syntax()) } pub(super) fn token(parent: &N) -> Option { children_tokens(parent).next() } /// Token untyped pub(super) fn token_u(parent: &N, kind: SyntaxKind) -> Option { children_tokens_u(parent).find(|it| it.kind() == kind) } pub(super) fn children_tokens(parent: &N) -> impl Iterator { parent .syntax() .children_with_tokens() .filter_map(SyntaxElement::into_token) .filter_map(T::cast) } pub(super) fn children_tokens_u(parent: &N) -> impl Iterator { parent.syntax().children_with_tokens().filter_map(SyntaxElement::into_token) } }