1use luau_lexer::lexer::Lexer;
4use std::borrow::Cow;
5#[cfg(feature = "cache")]
6use std::collections::HashMap;
7
8use crate::types::{Cst, Pointer};
9
10#[cfg(feature = "cache")]
12pub type ParserCache = HashMap<String, Pointer<Cst>>;
13
14#[derive(Clone, Debug, Default, PartialEq, Eq)]
16#[cfg_attr(not(feature = "cache"), derive(Copy, Hash, PartialOrd, Ord))]
17#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
18pub struct Parser<'a> {
19 #[cfg(feature = "cache")]
23 cache: ParserCache,
24
25 lexer: Lexer<'a>,
27}
28
29impl<'a> Parser<'a> {
30 #[inline]
32 pub fn new(input: impl Into<Cow<'a, str>>) -> Self {
33 Self {
34 #[cfg(feature = "cache")]
35 cache: HashMap::new(),
36 lexer: Lexer::new(input),
37 }
38 }
39
40 pub fn with_input(mut self, input: impl Into<Cow<'a, str>>) -> Self {
42 self.lexer = self.lexer.with_input(input);
43 self
44 }
45
46 pub fn set_input(&mut self, input: impl Into<Cow<'a, str>>) {
48 self.lexer.set_input(input);
49 }
50
51 pub fn parse(&mut self, uri: &str) -> Pointer<Cst> {
53 let cst = Pointer::new(Cst::parse(self.lexer.next_token(), &mut self.lexer, uri));
54
55 #[cfg(feature = "cache")]
56 {
57 self.cache.insert(uri.to_string(), cst);
58
59 self.cache.get(uri).unwrap().to_owned()
60 }
61
62 #[cfg(not(feature = "cache"))]
63 cst
64 }
65
66 #[cfg(feature = "cache")]
70 #[inline]
71 pub fn get_ast(&self, uri: &str) -> &Cst {
72 self.cache.get(uri).unwrap()
73 }
74
75 #[inline]
78 pub fn get_or_create(&mut self, uri: &str, code: impl Into<Cow<'a, str>>) -> Pointer<Cst> {
79 #[cfg(feature = "cache")]
80 if let Some(cst) = self.maybe_get_ast(uri) {
81 return cst;
82 }
83
84 self.set_input(code);
85 self.parse(uri)
86 }
87
88 #[cfg(feature = "cache")]
92 #[inline]
93 pub fn maybe_get_ast(&self, uri: &str) -> Option<Pointer<Cst>> {
94 self.cache.get(uri).cloned()
95 }
96
97 #[cfg(feature = "cache")]
99 #[inline]
100 pub fn get_all_asts(&self) -> &ParserCache {
101 &self.cache
102 }
103
104 #[cfg(feature = "cache")]
106 #[inline]
107 pub fn clear_cache(&mut self) {
108 self.cache.clear();
109 }
110}