use std::borrow::Cow;
use crate::{compile::CompileResult, options::RegexFlavor, regex::Regex, span::Span};
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct Literal<'i> {
content: Cow<'i, str>,
pub(crate) span: Span,
}
impl<'i> Literal<'i> {
pub(crate) fn new(content: Cow<'i, str>, span: Span) -> Self {
Literal { content, span }
}
pub(crate) fn compile(&self) -> CompileResult<'i> {
Ok(Regex::Literal(self.content.clone()))
}
}
#[cfg(feature = "dbg")]
impl core::fmt::Debug for Literal<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.content.fmt(f)
}
}
pub(crate) fn compile_char_esc_in_class(c: char, buf: &mut String, flavor: RegexFlavor) {
match c {
'\\' => buf.push_str(r#"\\"#),
'-' => buf.push_str(r#"\-"#),
']' => buf.push_str(r#"\]"#),
'^' => buf.push_str(r#"\^"#),
c => compile_char(c, buf, flavor),
}
}
pub(crate) fn codegen_char_esc(c: char, buf: &mut String, flavor: RegexFlavor) {
match c {
'\\' => buf.push_str(r#"\\"#),
'[' => buf.push_str(r#"\["#),
'{' => buf.push_str(r#"\{"#),
'(' => buf.push_str(r#"\("#),
')' => buf.push_str(r#"\)"#),
'.' => buf.push_str(r#"\."#),
'+' => buf.push_str(r#"\+"#),
'*' => buf.push_str(r#"\*"#),
'?' => buf.push_str(r#"\?"#),
'|' => buf.push_str(r#"\|"#),
'^' => buf.push_str(r#"\^"#),
'$' => buf.push_str(r#"\$"#),
c => compile_char(c, buf, flavor),
}
}
pub(crate) fn compile_char(c: char, buf: &mut String, flavor: RegexFlavor) {
use std::fmt::Write;
match c {
'\n' => buf.push_str("\\n"),
'\r' => buf.push_str("\\r"),
'\t' => buf.push_str("\\t"),
'\x07' => buf.push_str("\\a"),
'\x1B' => buf.push_str("\\e"),
'\x0C' => buf.push_str("\\f"),
' ' => buf.push(' '),
_ if c <= '\u{FF}' => {
if c.is_ascii_graphic() {
buf.push(c);
} else {
write!(buf, "\\x{:02X}", c as u8).unwrap();
}
}
_ if c.is_alphanumeric() && c.len_utf16() == 1 => {
buf.push(c);
}
_ if c.len_utf16() == 1 && !matches!(flavor, RegexFlavor::Pcre) => {
write!(buf, "\\u{:04X}", c as u32).unwrap();
}
_ => {
match flavor {
RegexFlavor::Pcre => buf.push_str("\\x"),
_ => buf.push_str("\\u"),
}
write!(buf, "{{{:X}}}", c as u32).unwrap();
}
}
}
pub(super) fn needs_parens_before_repetition(s: &str) -> bool {
s.chars().nth(1).is_some()
}