use luau_lexer::lexer::Lexer;
#[cfg(feature = "cache")]
use std::collections::HashMap;
use crate::types::{Cst, Pointer};
#[cfg(feature = "cache")]
pub type Cache = HashMap<String, Pointer<Cst>>;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(not(feature = "cache"), derive(Copy, Hash, PartialOrd, Ord))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Parser {
#[cfg(feature = "cache")]
cache: Cache,
lexer: Lexer,
}
impl Parser {
#[inline]
pub fn new(input: &str) -> Self {
Self {
#[cfg(feature = "cache")]
cache: HashMap::new(),
lexer: Lexer::new(input),
}
}
pub fn with_input(mut self, input: &str) -> Self {
self.lexer = self.lexer.with_input(input);
self
}
pub fn set_input(&mut self, input: &str) {
self.lexer.set_input(input);
}
#[allow(clippy::missing_panics_doc)]
pub fn parse(&mut self, uri: &str) -> Pointer<Cst> {
let cst = Pointer::new(Cst::parse(self.lexer.next_token(), &mut self.lexer, uri));
#[cfg(feature = "cache")]
{
self.cache.insert(uri.to_string(), cst);
#[allow(clippy::unwrap_used)]
self.cache.get(uri).unwrap().to_owned()
}
#[cfg(not(feature = "cache"))]
cst
}
#[cfg(feature = "cache")]
#[inline]
pub fn get_ast(&self, uri: &str) -> &Cst {
#[allow(clippy::unwrap_used)]
self.cache.get(uri).unwrap()
}
#[inline]
pub fn get_or_create(&mut self, uri: &str, code: &str) -> Pointer<Cst> {
#[cfg(feature = "cache")]
if let Some(cst) = self.maybe_get_ast(uri) {
return cst;
}
self.set_input(code);
self.parse(uri)
}
#[cfg(feature = "cache")]
#[inline]
pub fn maybe_get_ast(&self, uri: &str) -> Option<Pointer<Cst>> {
self.cache.get(uri).cloned()
}
#[cfg(feature = "cache")]
#[inline]
pub const fn get_all_asts(&self) -> &Cache {
&self.cache
}
#[cfg(feature = "cache")]
#[inline]
pub fn clear_cache(&mut self) {
self.cache.clear();
}
}