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