1pub use nom_recursive_macros::recursive_parser;
45use std::collections::HashMap;
46
47#[cfg(all(not(feature = "tracer128"), not(feature = "tracer256"),))]
48const RECURSIVE_FLAG_WORDS: usize = 1;
49#[cfg(all(feature = "tracer128", not(feature = "tracer256"),))]
50const RECURSIVE_FLAG_WORDS: usize = 2;
51#[cfg(feature = "tracer256")]
52const RECURSIVE_FLAG_WORDS: usize = 4;
53
54pub struct RecursiveIndexes {
55 indexes: HashMap<&'static str, usize>,
56 next: usize,
57}
58
59impl RecursiveIndexes {
60 pub fn new() -> Self {
61 RecursiveIndexes {
62 indexes: HashMap::new(),
63 next: 0,
64 }
65 }
66
67 pub fn get(&mut self, key: &'static str) -> usize {
68 if let Some(x) = self.indexes.get(key) {
69 *x
70 } else {
71 let new_index = self.next;
72 assert!(new_index < RECURSIVE_FLAG_WORDS * 64, "Recursive tracers exceed the maximum number({}). Consider use feature `tracer128` or `tracer256` to extend it.", RECURSIVE_FLAG_WORDS * 64);
73 self.next += 1;
74 self.indexes.insert(key, new_index);
75 new_index
76 }
77 }
78}
79
80thread_local!(
81 pub static RECURSIVE_STORAGE: core::cell::RefCell<crate::RecursiveIndexes> = {
82 core::cell::RefCell::new(crate::RecursiveIndexes::new())
83 }
84);
85
86#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
88pub struct RecursiveInfo {
89 flag: [u64; RECURSIVE_FLAG_WORDS],
90 ptr: *const u8,
91}
92
93impl Default for RecursiveInfo {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99impl RecursiveInfo {
100 pub fn new() -> Self {
101 RecursiveInfo {
102 flag: [0; RECURSIVE_FLAG_WORDS],
103 ptr: std::ptr::null(),
104 }
105 }
106
107 pub fn check_flag(&self, id: usize) -> bool {
108 let upper = id / 64;
109 let lower = id % 64;
110 ((self.flag[upper] >> lower) & 1) == 1
111 }
112
113 pub fn set_flag(&mut self, id: usize) {
114 let upper = id / 64;
115 let lower = id % 64;
116
117 let val = 1u64 << lower;
118 let mask = !(1u64 << lower);
119
120 self.flag[upper] = (self.flag[upper] & mask) | val;
121 }
122
123 pub fn clear_flags(&mut self) {
124 for i in 0..self.flag.len() {
125 self.flag[i] = 0u64;
126 }
127 }
128
129 pub fn get_ptr(&self) -> *const u8 {
130 self.ptr
131 }
132
133 pub fn set_ptr(&mut self, ptr: *const u8) {
134 self.ptr = ptr;
135 }
136}
137
138pub trait HasRecursiveInfo {
142 fn get_recursive_info(&self) -> RecursiveInfo;
143 fn set_recursive_info(self, info: RecursiveInfo) -> Self;
144}
145
146impl HasRecursiveInfo for RecursiveInfo {
147 fn get_recursive_info(&self) -> RecursiveInfo {
148 *self
149 }
150
151 fn set_recursive_info(self, info: RecursiveInfo) -> Self {
152 info
153 }
154}
155
156impl<T, U> HasRecursiveInfo for nom_locate::LocatedSpan<T, U>
157where
158 U: HasRecursiveInfo,
159{
160 fn get_recursive_info(&self) -> RecursiveInfo {
161 self.extra.get_recursive_info()
162 }
163
164 fn set_recursive_info(mut self, info: RecursiveInfo) -> Self {
165 self.extra = self.extra.set_recursive_info(info);
166 self
167 }
168}