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 ParserCache = 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: ParserCache,
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 pub fn parse(&mut self, uri: &str) -> Pointer<Cst> {
52 let cst = Pointer::new(Cst::parse(self.lexer.next_token(), &mut self.lexer, uri));
53
54 #[cfg(feature = "cache")]
55 {
56 self.cache.insert(uri.to_string(), cst);
57
58 self.cache.get(uri).unwrap().to_owned()
59 }
60
61 #[cfg(not(feature = "cache"))]
62 cst
63 }
64
65 #[cfg(feature = "cache")]
69 #[inline]
70 pub fn get_ast(&self, uri: &str) -> &Cst {
71 self.cache.get(uri).unwrap()
72 }
73
74 #[inline]
77 pub fn get_or_create(&mut self, uri: &str, code: &str) -> Pointer<Cst> {
78 #[cfg(feature = "cache")]
79 if let Some(cst) = self.maybe_get_ast(uri) {
80 return cst;
81 }
82
83 self.set_input(code);
84 self.parse(uri)
85 }
86
87 #[cfg(feature = "cache")]
91 #[inline]
92 pub fn maybe_get_ast(&self, uri: &str) -> Option<Pointer<Cst>> {
93 self.cache.get(uri).cloned()
94 }
95
96 #[cfg(feature = "cache")]
98 #[inline]
99 pub fn get_all_asts(&self) -> &ParserCache {
100 &self.cache
101 }
102
103 #[cfg(feature = "cache")]
105 #[inline]
106 pub fn clear_cache(&mut self) {
107 self.cache.clear();
108 }
109}