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