huff_neo_lexer/
context_stack.rs1use huff_neo_utils::error::LexicalErrorKind;
2use huff_neo_utils::lexer_context::Context;
3
4pub struct ContextStack {
24 stack: Vec<Context>,
26}
27
28impl ContextStack {
29 pub fn new() -> Self {
31 ContextStack { stack: vec![Context::Global] }
32 }
33
34 pub fn replace(&mut self, context: Context) {
36 let last = self.stack.last_mut().unwrap();
37 *last = context;
38 }
39
40 pub fn push(&mut self, context: Context) {
42 self.stack.push(context);
43 }
44
45 pub fn pop(&mut self, count: u8) -> Result<(), LexicalErrorKind> {
47 for _ in 0..count {
48 self.stack.pop();
49 if self.stack.is_empty() {
50 return Err(LexicalErrorKind::StackUnderflow);
51 }
52 }
53
54 Ok(())
55 }
56
57 pub fn top(&self) -> &Context {
59 self.stack.last().unwrap()
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use huff_neo_utils::lexer_context::Context;
67
68 #[test]
69 fn test_context_stack_new() {
70 let stack = ContextStack::new();
71 assert_eq!(stack.top(), &Context::Global);
72 }
73
74 #[test]
75 fn test_context_stack_replace() {
76 let mut stack = ContextStack::new();
77 stack.push(Context::MacroDefinition);
78 assert_eq!(stack.top(), &Context::MacroDefinition);
79
80 stack.replace(Context::MacroBody);
81 assert_eq!(stack.top(), &Context::MacroBody);
82 }
83
84 #[test]
85 fn test_context_stack_push_pop() {
86 let mut stack = ContextStack::new();
87 stack.push(Context::MacroDefinition);
88 assert_eq!(stack.top(), &Context::MacroDefinition);
89
90 stack.pop(1).unwrap();
91 assert_eq!(stack.top(), &Context::Global);
92 }
93
94 #[test]
95 fn test_context_stack_underflow() {
96 let mut stack = ContextStack::new();
97 stack.pop(1).unwrap_err();
98 }
99
100 #[test]
101 fn test_context_stack_push_pop_multiple() {
102 let mut stack = ContextStack::new();
103 stack.push(Context::Abi);
104 stack.push(Context::AbiArgs);
105 assert_eq!(stack.top(), &Context::AbiArgs);
106
107 stack.pop(1).unwrap();
108 assert_eq!(stack.top(), &Context::Abi);
109
110 stack.pop(1).unwrap();
111 assert_eq!(stack.top(), &Context::Global);
112 }
113}