build(rust): vendor rnix parser crate
This commit was merged in pull request #57.
This commit is contained in:
1 parent
cbdf482422
commit
82ad65a3a4
492 files changed
+67785
-1
No files matched your search
+111
@@ -0,0 +1,111 @@
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
pub mod ast;
|
||||
mod kinds;
|
||||
mod parser;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod token_set;
|
||||
mod tokenizer;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use self::kinds::SYNTAX_KIND_MAX;
|
||||
pub use self::{kinds::ParseSyntaxKindError, kinds::SyntaxKind, tokenizer::tokenize};
|
||||
|
||||
use ast::AstNode;
|
||||
pub use parser::ParseError;
|
||||
use rowan::GreenNode;
|
||||
pub use rowan::{NodeOrToken, TextRange, TextSize, TokenAtOffset, WalkEvent};
|
||||
pub(crate) use token_set::TokenSet;
|
||||
pub use tokenizer::Token;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum NixLanguage {}
|
||||
|
||||
impl rowan::Language for NixLanguage {
|
||||
type Kind = SyntaxKind;
|
||||
fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
|
||||
let discriminant: u16 = raw.0;
|
||||
assert!(discriminant <= SYNTAX_KIND_MAX);
|
||||
unsafe { std::mem::transmute::<u16, SyntaxKind>(discriminant) }
|
||||
}
|
||||
fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
|
||||
rowan::SyntaxKind(kind as u16)
|
||||
}
|
||||
}
|
||||
|
||||
pub type SyntaxNode = rowan::SyntaxNode<NixLanguage>;
|
||||
pub type SyntaxToken = rowan::SyntaxToken<NixLanguage>;
|
||||
pub type SyntaxElement = rowan::NodeOrToken<SyntaxNode, SyntaxToken>;
|
||||
pub type SyntaxElementChildren = rowan::SyntaxElementChildren<NixLanguage>;
|
||||
pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<NixLanguage>;
|
||||
|
||||
pub use ast::Root;
|
||||
|
||||
impl Root {
|
||||
pub fn parse(s: &str) -> Parse<Root> {
|
||||
let (green, errors) = parser::parse(tokenize(s));
|
||||
Parse { green, errors, _ty: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a parse
|
||||
#[derive(Clone)]
|
||||
pub struct Parse<T> {
|
||||
green: GreenNode,
|
||||
errors: Vec<ParseError>,
|
||||
_ty: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
impl<T> Parse<T> {
|
||||
pub fn syntax(&self) -> SyntaxNode {
|
||||
SyntaxNode::new_root(self.green.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AstNode> Parse<T> {
|
||||
pub fn tree(&self) -> T {
|
||||
T::cast(self.syntax()).unwrap()
|
||||
}
|
||||
|
||||
/// Return all errors in the tree, if any
|
||||
pub fn errors(&self) -> &[ParseError] {
|
||||
&self.errors
|
||||
}
|
||||
|
||||
/// Either return the first error in the tree, or if there are none return self
|
||||
pub fn ok(self) -> Result<T, ParseError> {
|
||||
if let Some(err) = self.errors().first() {
|
||||
return Err(err.clone());
|
||||
}
|
||||
Ok(self.tree())
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a `SyntaxNode` against an `ast` type.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// match_ast! {
|
||||
/// match node {
|
||||
/// ast::Apply(it) => { ... },
|
||||
/// ast::Assert(it) => { ... },
|
||||
/// ast::IfElse(it) => { ... },
|
||||
/// _ => None,
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! match_ast {
|
||||
(match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
|
||||
|
||||
(match ($node:expr) {
|
||||
$( ast::$ast:ident($it:pat) => $res:expr, )*
|
||||
_ => $catch_all:expr $(,)?
|
||||
}) => {{
|
||||
$( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
|
||||
{ $catch_all }
|
||||
}};
|
||||
}
|
||||
Reference in new issue
Block a user