use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Lookahead {
pub is_positive: bool,
pub pattern: String,
}
impl Lookahead {
pub fn new(is_positive: bool, pattern: String) -> Self {
Self {
is_positive,
pattern,
}
}
#[inline]
pub fn pattern(&self) -> &str {
&self.pattern
}
#[inline]
pub fn is_positive(&self) -> bool {
self.is_positive
}
}
impl std::fmt::Display for Lookahead {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_positive {
write!(f, "(?={})", self.pattern.escape_default())
} else {
write!(f, "(?!{})", self.pattern.escape_default())
}
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Pattern {
pattern: String,
token_type: usize,
#[serde(skip_serializing_if = "Option::is_none")]
lookahead: Option<Lookahead>,
}
impl Pattern {
pub fn new(pattern: String, token_type: usize) -> Self {
Self {
pattern,
token_type,
lookahead: None,
}
}
pub fn set_token_type(&mut self, token_type: usize) {
self.token_type = token_type;
}
pub fn with_lookahead(self, lookahead: Lookahead) -> Self {
Self {
pattern: self.pattern,
token_type: self.token_type,
lookahead: Some(lookahead),
}
}
#[inline]
pub fn pattern(&self) -> &str {
&self.pattern
}
#[inline]
pub fn terminal_id(&self) -> usize {
self.token_type
}
#[inline]
pub fn lookahead(&self) -> Option<&Lookahead> {
self.lookahead.as_ref()
}
}
impl std::fmt::Display for Pattern {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.pattern.escape_default())?;
if let Some(lookahead) = &self.lookahead {
write!(f, "{}", lookahead)?
}
Ok(())
}
}
impl AsRef<str> for Pattern {
fn as_ref(&self) -> &str {
&self.pattern
}
}