extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
use super::ast::{AbsentKind, Anchor, Backref, CallTarget, CharClass, Cond};
use super::callout::CalloutDir;
use super::syntax::Options;
#[derive(Clone, Debug)]
pub enum Inst {
Nop,
Char(u32),
Literal(Vec<u32>),
Any { newline: bool },
SuperAny,
Class { class: CharClass },
Split(u16, u16),
Jump(u16),
Save(u16),
Match,
Fail,
Assert(Anchor),
Repeat {
body: u16,
after: u16,
min: u32,
max: Option<u32>,
greedy: bool,
possessive: bool,
},
Look {
body: u16,
after: u16,
behind: bool,
negative: bool,
},
Atomic {
body: u16,
after: u16,
},
Backref(Backref),
Call(CallTarget),
Keep,
Absent {
stopper: u16,
expr: Option<u16>,
after: u16,
kind: AbsentKind,
},
Cond {
cond: Cond,
then_pc: u16,
else_pc: Option<u16>,
after: u16,
},
GeneralNewline,
TextSegment,
Callout {
named: bool,
name: String,
args: String,
tag: Option<String>,
body: String,
dir: CalloutDir,
},
PushOptions(Options, Options),
PopOptions,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Lead {
pub set: [u64; 4],
pub single: Option<u8>,
}
impl Lead {
#[inline(always)]
pub fn contains(&self, b: u8) -> bool {
self.set[(b >> 6) as usize] & (1u64 << (b & 63)) != 0
}
#[inline]
pub fn insert(&mut self, b: u8) {
self.set[(b >> 6) as usize] |= 1u64 << (b & 63);
}
pub fn empty() -> Self {
Self {
set: [0; 4],
single: None,
}
}
pub fn insert_non_ascii(&mut self) {
self.set[2] = 0xFFFF_FFFF_FFFF_FFFF;
self.set[3] = 0xFFFF_FFFF_FFFF_FFFF;
}
pub fn count(&self) -> u32 {
self.set.iter().map(|w| w.count_ones()).sum()
}
pub fn finish(mut self) -> Option<Self> {
let n = self.count();
if n == 0 || n >= 256 {
return None;
}
if n == 1 {
for b in 0..=255u8 {
if self.contains(b) {
self.single = Some(b);
break;
}
}
}
Some(self)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SimpleBody {
None,
Char(u32),
Class(u16),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ClassPlan {
pub ascii: [u64; 2],
pub options: Options,
}
impl ClassPlan {
#[inline(always)]
pub fn hit(&self, cp: u32) -> bool {
self.ascii[(cp >> 6) as usize] & (1u64 << (cp & 63)) != 0
}
}
#[derive(Clone, Copy, Debug)]
pub struct RepeatShape {
pub writes_caps: bool,
pub simple: SimpleBody,
pub follow_disjoint: bool,
pub follow_byte: Option<u8>,
pub follow_icase: bool,
}
impl Default for RepeatShape {
fn default() -> Self {
Self {
writes_caps: true,
simple: SimpleBody::None,
follow_disjoint: false,
follow_byte: None,
follow_icase: false,
}
}
}
#[derive(Clone, Debug)]
pub struct Program {
pub insts: Vec<Inst>,
pub capture_count: usize,
pub names: Vec<Option<String>>,
pub has_named: bool,
pub history_groups: Vec<bool>,
pub lead: Option<Lead>,
pub repeat_shapes: Vec<RepeatShape>,
pub ascii_literal: Option<Vec<u8>>,
pub group_spans: Vec<Option<(u16, u16)>>,
pub class_plans: Vec<Option<ClassPlan>>,
pub literal_bytes: Vec<Option<Vec<u8>>>,
pub req_lit: Option<super::optimize::ReqLit>,
pub anchored_bol: bool,
}