pub use nom_recursive_macros::recursive_parser;
use std::collections::HashMap;
#[cfg(all(not(feature = "tracer128"), not(feature = "tracer256"),))]
const RECURSIVE_FLAG_WORDS: usize = 1;
#[cfg(all(feature = "tracer128", not(feature = "tracer256"),))]
const RECURSIVE_FLAG_WORDS: usize = 2;
#[cfg(feature = "tracer256")]
const RECURSIVE_FLAG_WORDS: usize = 4;
pub struct RecursiveIndexes {
indexes: HashMap<&'static str, usize>,
next: usize,
}
impl RecursiveIndexes {
pub fn new() -> Self {
RecursiveIndexes {
indexes: HashMap::new(),
next: 0,
}
}
pub fn get(&mut self, key: &'static str) -> usize {
if let Some(x) = self.indexes.get(key) {
*x
} else {
let new_index = self.next;
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);
self.next += 1;
self.indexes.insert(key, new_index);
new_index
}
}
}
thread_local!(
pub static RECURSIVE_STORAGE: core::cell::RefCell<crate::RecursiveIndexes> = {
core::cell::RefCell::new(crate::RecursiveIndexes::new())
}
);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct RecursiveInfo {
flag: [u64; RECURSIVE_FLAG_WORDS],
ptr: *const u8,
}
impl Default for RecursiveInfo {
fn default() -> Self {
Self::new()
}
}
impl RecursiveInfo {
pub fn new() -> Self {
RecursiveInfo {
flag: [0; RECURSIVE_FLAG_WORDS],
ptr: std::ptr::null(),
}
}
pub fn check_flag(&self, id: usize) -> bool {
let upper = id / 64;
let lower = id % 64;
((self.flag[upper] >> lower) & 1) == 1
}
pub fn set_flag(&mut self, id: usize) {
let upper = id / 64;
let lower = id % 64;
let val = 1u64 << lower;
let mask = !(1u64 << lower);
self.flag[upper] = (self.flag[upper] & mask) | val;
}
pub fn clear_flags(&mut self) {
for i in 0..self.flag.len() {
self.flag[i] = 0u64;
}
}
pub fn get_ptr(&self) -> *const u8 {
self.ptr
}
pub fn set_ptr(&mut self, ptr: *const u8) {
self.ptr = ptr;
}
}
pub trait HasRecursiveInfo {
fn get_recursive_info(&self) -> RecursiveInfo;
fn set_recursive_info(self, info: RecursiveInfo) -> Self;
}
impl HasRecursiveInfo for RecursiveInfo {
fn get_recursive_info(&self) -> RecursiveInfo {
*self
}
fn set_recursive_info(self, info: RecursiveInfo) -> Self {
info
}
}
impl<T, U> HasRecursiveInfo for nom_locate::LocatedSpan<T, U>
where
U: HasRecursiveInfo,
{
fn get_recursive_info(&self) -> RecursiveInfo {
self.extra.get_recursive_info()
}
fn set_recursive_info(mut self, info: RecursiveInfo) -> Self {
self.extra = self.extra.set_recursive_info(info);
self
}
}