type_sitter_lib/node/parser.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
use std::marker::PhantomData;
use crate::{raw, IncludedRangesError, Language, LanguageError, Node, Range, Tree};
#[cfg(feature = "yak-sitter")]
use crate::TreeParseError;
#[cfg(feature = "yak-sitter")]
use std::path::Path;
/// A stateful object that this is used to produce a tree based on some source code.
#[repr(transparent)]
pub struct Parser<Root: Node<'static>>(pub raw::Parser, PhantomData<Root>);
impl<Root: Node<'static>> Parser<Root> {
/// Convert a tree-sitter parser into a typed parser by specifying the correct root node type.
///
/// This will succeed even if `Root` is not the language's root node, because
/// [`Tree::root_node`] checks that the root node is the correct type.
pub fn wrap(parser: raw::Parser) -> Self {
Self(parser, PhantomData)
}
/// Version of [`wrap`](Self::wrap) for an immutable reference.
pub fn wrap_ref(parser: &raw::Parser) -> &Self {
// SAFETY: Same repr
unsafe { &*(parser as *const raw::Parser as *const Self) }
}
/// Version of [`wrap`](Self::wrap) for a mutable reference.
pub fn wrap_mut(parser: &mut raw::Parser) -> &mut Self {
// SAFETY: Same repr
unsafe { &mut *(parser as *mut raw::Parser as *mut Self) }
}
/// Create a new parser for the given language. See
/// [tree-sitter's `Parser::set_language`](tree_sitter::Parser::set_language).
///
/// This will succeed even if `Root` is not the language's root node, because
/// [`Tree::root_node`] checks that the root node is the correct type.
///
/// If the language changes, the root node should change as well, so `set_language` isn't
/// exposed by this wrapper. Instead, unwrap the parser, call `set_language`, and re-wrap.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn new(language: &Language) -> Result<Self, LanguageError> {
Ok(Self(raw::Parser::new(language)?, PhantomData))
}
/// Create a new parser for the given language. See [`tree_sitter::Parser::set_language`]
#[inline]
#[cfg(not(feature = "yak-sitter"))]
pub fn new(language: &Language) -> Result<Self, LanguageError> {
let mut parser = raw::Parser::new();
parser.set_language(language)?;
Ok(Self(parser, PhantomData))
}
/// Set the ranges of text the parser should include when parsing. See
/// [`tree_sitter::Parser::set_included_ranges`]
#[inline]
pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
self.0.set_included_ranges(ranges)
}
/// Parse a file. See [`tree_sitter::Parser::parse`].
///
/// Additionally, file must be valid utf-8 or this will return `Err`. The file's path is used
/// for stable node comparison between trees.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn parse_file(
&mut self,
path: &Path,
old_tree: Option<&Tree<Root>>
) -> Result<Tree<Root>, TreeParseError> {
self.0.parse_file(path, old_tree.map(|t| &t.0)).map(Tree::wrap)
}
/// Parse a string. See [`tree_sitter::Parser::parse`].
///
/// The path is stored as metadata that can be accessed from nodes. If you don't need this, pass
/// `None`.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn parse_string(
&mut self,
text: String,
path: Option<&Path>,
old_tree: Option<&Tree<Root>>
) -> Result<Tree<Root>, TreeParseError> {
self.0.parse_string(text, path, old_tree.map(|t| &t.0)).map(Tree::wrap)
}
/// Parse a byte string. See [`tree_sitter::Parser::parse`].
///
/// Note that the wrappers expect and assume UTF-8, so this will fail if the text is not valid
/// UTF-8.
///
/// The path is stored as metadata that can be accessed from nodes. If you don't need this, pass
/// `None`.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn parse_bytes(
&mut self,
byte_text: Vec<u8>,
path: Option<&Path>,
old_tree: Option<&Tree<Root>>
) -> Result<Tree<Root>, TreeParseError> {
self.0.parse_bytes(byte_text, path, old_tree.map(|t| &t.0)).map(Tree::wrap)
}
/// Parse a byte string. See [`tree_sitter::Parser::parse`]
#[inline]
#[cfg(not(feature = "yak-sitter"))]
pub fn parse(
&mut self,
text: impl AsRef<[u8]>,
old_tree: Option<&Tree<Root>>
) -> Result<Tree<Root>, ()> {
self.0.parse(text, old_tree.map(|t| &t.0)).ok_or(()).map(Tree::wrap)
}
}