rnix/
lib.rs

1#[macro_use]
2mod macros;
3pub mod ast;
4mod kinds;
5pub mod parser;
6#[cfg(test)]
7mod tests;
8mod token_set;
9pub mod tokenizer;
10
11use std::marker::PhantomData;
12
13pub use self::{kinds::SyntaxKind, tokenizer::tokenize};
14
15use ast::AstNode;
16use parser::ParseError;
17use rowan::GreenNode;
18pub use rowan::{NodeOrToken, TextRange, TextSize, TokenAtOffset, WalkEvent};
19pub(crate) use token_set::TokenSet;
20
21use self::tokenizer::Tokenizer;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub enum NixLanguage {}
25
26impl rowan::Language for NixLanguage {
27    type Kind = SyntaxKind;
28    fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
29        let discriminant: u16 = raw.0;
30        assert!(discriminant <= (SyntaxKind::__LAST as u16));
31        unsafe { std::mem::transmute::<u16, SyntaxKind>(discriminant) }
32    }
33    fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
34        rowan::SyntaxKind(kind as u16)
35    }
36}
37
38pub type SyntaxNode = rowan::SyntaxNode<NixLanguage>;
39pub type SyntaxToken = rowan::SyntaxToken<NixLanguage>;
40pub type SyntaxElement = rowan::NodeOrToken<SyntaxNode, SyntaxToken>;
41pub type SyntaxElementChildren = rowan::SyntaxElementChildren<NixLanguage>;
42pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<NixLanguage>;
43
44pub use ast::Root;
45
46impl Root {
47    pub fn parse(s: &str) -> Parse<Root> {
48        let (green, errors) = parser::parse(Tokenizer::new(s));
49        Parse { green, errors, _ty: PhantomData }
50    }
51}
52
53/// The result of a parse
54#[derive(Clone)]
55pub struct Parse<T> {
56    green: GreenNode,
57    errors: Vec<ParseError>,
58    _ty: PhantomData<fn() -> T>,
59}
60
61impl<T> Parse<T> {
62    pub fn syntax(&self) -> SyntaxNode {
63        SyntaxNode::new_root(self.green.clone())
64    }
65}
66
67impl<T: AstNode> Parse<T> {
68    pub fn tree(&self) -> T {
69        T::cast(self.syntax()).unwrap()
70    }
71
72    /// Return all errors in the tree, if any
73    pub fn errors(&self) -> &[ParseError] {
74        &*self.errors
75    }
76
77    /// Either return the first error in the tree, or if there are none return self
78    pub fn ok(self) -> Result<T, ParseError> {
79        if let Some(err) = self.errors().first() {
80            return Err(err.clone());
81        }
82        Ok(self.tree())
83    }
84}
85
86/// Matches a `SyntaxNode` against an `ast` type.
87///
88/// # Example:
89///
90/// ```ignore
91/// match_ast! {
92///     match node {
93///         ast::Apply(it) => { ... },
94///         ast::Assert(it) => { ... },
95///         ast::IfElse(it) => { ... },
96///         _ => None,
97///     }
98/// }
99/// ```
100#[macro_export]
101macro_rules! match_ast {
102    (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
103
104    (match ($node:expr) {
105        $( ast::$ast:ident($it:pat) => $res:expr, )*
106        _ => $catch_all:expr $(,)?
107    }) => {{
108        $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
109        { $catch_all }
110    }};
111}