use std::sync::Arc;
use serde::{Deserialize, Serialize};
use crate::{ClassItem, ClassSet, Cursor, NodeId, ParseError, Span};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Node {
pub kind: AstKind,
pub span: Span,
pub parent: Option<NodeId>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AstKind {
Empty,
Anchor {
kind: AnchorKind,
},
Literal {
c: char,
escaped: bool,
},
Dot,
Class {
negated: bool,
items: Vec<ClassItem>,
set: ClassSet,
},
Group {
kind: GroupKind,
inner: NodeId,
},
Alt {
arms: Vec<NodeId>,
},
Concat {
parts: Vec<NodeId>,
},
Repeat {
inner: NodeId,
kind: RepKind,
greedy: bool,
},
}
impl AstKind {
#[must_use]
pub fn children(&self) -> &[NodeId] {
match self {
Self::Group { inner, .. } | Self::Repeat { inner, .. } => std::slice::from_ref(inner),
Self::Alt { arms } => arms,
Self::Concat { parts } => parts,
Self::Empty
| Self::Anchor { .. }
| Self::Literal { .. }
| Self::Dot
| Self::Class { .. } => &[],
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AnchorKind {
Start,
End,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum GroupKind {
Capture { index: u32, name: Option<Box<str>> },
NonCapture,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum RepKind {
ZeroOrOne,
ZeroOrMore,
OneOrMore,
Range { min: u32, max: Option<u32> },
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct GroupInfo {
pub index: u32,
pub name: Option<Box<str>>,
pub node: NodeId,
}
#[derive(Clone, Debug)]
pub struct Pattern {
pub(crate) src: Arc<str>,
pub(crate) nodes: Vec<Node>,
pub(crate) groups: Vec<GroupInfo>,
pub(crate) root: NodeId,
}
impl Pattern {
pub fn parse(src: &str) -> Result<Self, ParseError> {
crate::parse(src)
}
#[must_use]
pub fn source(&self) -> &str {
&self.src
}
#[must_use]
pub const fn root_id(&self) -> NodeId {
self.root
}
#[must_use]
pub fn root(&self) -> Cursor<'_> {
Cursor::new(self, self.root)
}
#[must_use]
pub fn node(&self, id: NodeId) -> &Node {
&self.nodes[id.0 as usize]
}
#[must_use]
pub fn nodes(&self) -> &[Node] {
&self.nodes
}
#[must_use]
pub fn groups(&self) -> &[GroupInfo] {
&self.groups
}
#[must_use]
pub fn len(&self) -> usize {
self.nodes.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
#[must_use]
pub fn text(&self, span: Span) -> &str {
&self.src[span.start as usize..span.end as usize]
}
}