1use luau_lexer::lexer::Lexer;
4#[cfg(feature = "cache")]
5use std::collections::HashMap;
6
7use crate::types::{Cst, Pointer};
8
9#[cfg(feature = "cache")]
11pub type Cache = HashMap<String, Pointer<Cst>>;
12
13#[derive(Clone, Debug, Default, PartialEq, Eq)]
15#[cfg_attr(not(feature = "cache"), derive(Copy, Hash, PartialOrd, Ord))]
16#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
17pub struct Parser {
18 #[cfg(feature = "cache")]
22 cache: Cache,
23
24 lexer: Lexer,
26}
27
28impl Parser {
29 #[inline]
31 pub fn new(input: &str) -> Self {
32 Self {
33 #[cfg(feature = "cache")]
34 cache: HashMap::new(),
35 lexer: Lexer::new(input),
36 }
37 }
38
39 pub fn with_input(mut self, input: &str) -> Self {
41 self.lexer = self.lexer.with_input(input);
42 self
43 }
44
45 pub fn set_input(&mut self, input: &str) {
47 self.lexer.set_input(input);
48 }
49
50 #[allow(clippy::missing_panics_doc)]
53 pub fn parse(&mut self, uri: &str) -> Pointer<Cst> {
54 let cst = Pointer::new(Cst::parse(self.lexer.next_token(), &mut self.lexer, uri));
55
56 #[cfg(feature = "cache")]
57 {
58 self.cache.insert(uri.to_string(), cst);
59
60 #[allow(clippy::unwrap_used)]
62 self.cache.get(uri).unwrap().to_owned()
63 }
64
65 #[cfg(not(feature = "cache"))]
66 cst
67 }
68
69 #[cfg(feature = "cache")]
77 #[inline]
78 pub fn get_ast(&self, uri: &str) -> &Cst {
79 #[allow(clippy::unwrap_used)]
81 self.cache.get(uri).unwrap()
82 }
83
84 #[inline]
87 pub fn get_or_create(&mut self, uri: &str, code: &str) -> Pointer<Cst> {
88 #[cfg(feature = "cache")]
89 if let Some(cst) = self.maybe_get_ast(uri) {
90 return cst;
91 }
92
93 self.set_input(code);
94 self.parse(uri)
95 }
96
97 #[cfg(feature = "cache")]
101 #[inline]
102 pub fn maybe_get_ast(&self, uri: &str) -> Option<Pointer<Cst>> {
103 self.cache.get(uri).cloned()
104 }
105
106 #[cfg(feature = "cache")]
108 #[inline]
109 pub const fn get_all_asts(&self) -> &Cache {
110 &self.cache
111 }
112
113 #[cfg(feature = "cache")]
115 #[inline]
116 pub fn clear_cache(&mut self) {
117 self.cache.clear();
118 }
119}