1 //! Thread-local data specific to LR(1) processing.
2 
3 use crate::grammar::repr::TerminalSet;
4 use std::cell::RefCell;
5 use std::mem;
6 use std::sync::Arc;
7 
8 thread_local! {
9     static TERMINALS: RefCell<Option<Arc<TerminalSet>>> = RefCell::new(None)
10 }
11 
12 pub struct Lr1Tls {
13     old_value: Option<Arc<TerminalSet>>,
14 }
15 
16 impl Lr1Tls {
install(terminals: TerminalSet) -> Lr1Tls17     pub fn install(terminals: TerminalSet) -> Lr1Tls {
18         let old_value = TERMINALS.with(|s| {
19             let mut s = s.borrow_mut();
20             mem::replace(&mut *s, Some(Arc::new(terminals)))
21         });
22 
23         Lr1Tls { old_value }
24     }
25 
with<OP, RET>(op: OP) -> RET where OP: FnOnce(&TerminalSet) -> RET,26     pub fn with<OP, RET>(op: OP) -> RET
27     where
28         OP: FnOnce(&TerminalSet) -> RET,
29     {
30         TERMINALS.with(|s| op(s.borrow().as_ref().expect("LR1 TLS not installed")))
31     }
32 }
33 
34 impl Drop for Lr1Tls {
drop(&mut self)35     fn drop(&mut self) {
36         TERMINALS.with(|s| *s.borrow_mut() = self.old_value.take());
37     }
38 }
39