luau_parser/
parser.rs

1//! The main item of this crate, the actual [`parser`](Parser).
2
3use luau_lexer::lexer::Lexer;
4#[cfg(feature = "cache")]
5use std::collections::HashMap;
6
7use crate::types::Cst;
8
9/// A Luau parser.
10pub struct Parser<'a> {
11    /// Cache, only works with the `cache` feature, this is useful when you need
12    /// to use the [`CST`](Cst) more than once in 2 different places without
13    /// re-parsing.
14    #[cfg(feature = "cache")]
15    cache: HashMap<String, Cst>,
16
17    /// The `tree-sitter` parser.
18    lexer: Lexer<'a>,
19}
20
21impl<'a> Parser<'a> {
22    /// Create a new [`parser`](Parser).
23    #[inline]
24    pub fn new(input: &'a str) -> Self {
25        Self {
26            #[cfg(feature = "cache")]
27            cache: HashMap::new(),
28            lexer: Lexer::new(input),
29        }
30    }
31
32    /// Set the parser's input. Meant to be chained.
33    pub fn with_input(mut self, input: &'a str) -> Self {
34        self.lexer = self.lexer.with_input(input);
35        self
36    }
37
38    /// Set the parser's input.
39    pub fn set_input(&mut self, input: &'a str) {
40        self.lexer.set_input(input);
41    }
42
43    /// Parse Luau code into an [`CST`](Cst).
44    pub fn parse(&mut self, uri: &str) -> Cst {
45        let cst = Cst::parse(self.lexer.next_token(), &mut self.lexer, uri);
46
47        #[cfg(feature = "cache")]
48        {
49            self.cache.insert(uri.to_string(), cst);
50
51            self.cache.get(uri).unwrap().to_owned()
52        }
53
54        #[cfg(not(feature = "cache"))]
55        cst
56    }
57
58    /// Get a specific [`CST`](Cst) from the cache, this function assumes the
59    /// cst does exist. If it may or may not exist, use
60    /// [`maybe_get_ast`](Self::maybe_get_ast).
61    #[cfg(feature = "cache")]
62    #[inline]
63    pub fn get_ast(&self, uri: &str) -> &Cst {
64        self.cache.get(uri).unwrap()
65    }
66
67    /// Get a specific [`CST`](Cst) from the cache, or parse `code` and return the
68    #[inline]
69    pub fn get_or_create(&mut self, uri: &str, code: &'a str) -> Cst {
70        #[cfg(feature = "cache")]
71        if let Some(cst) = self.maybe_get_ast(uri) {
72            return cst.to_owned();
73        }
74
75        self.lexer.set_input(code);
76        self.parse(uri)
77    }
78
79    /// Get a specific [`CST`](Cst) from the cache, this function, unlike
80    /// [`get_ast`](Self::get_ast), doesn't error when the [`CST`](Cst) isn't
81    /// there.
82    #[cfg(feature = "cache")]
83    #[inline]
84    pub fn maybe_get_ast(&self, uri: &str) -> Option<&Cst> {
85        self.cache.get(uri)
86    }
87
88    /// Get all cached [`CST`](Cst)s.
89    #[cfg(feature = "cache")]
90    #[inline]
91    pub fn get_all_asts(&self) -> &HashMap<String, Cst> {
92        &self.cache
93    }
94
95    /// Clear the cache.
96    #[cfg(feature = "cache")]
97    #[inline]
98    pub fn clear_cache(&mut self) {
99        self.cache.clear();
100    }
101}