Skip to main content

regast_syntax/
ast.rs

1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{ClassItem, ClassSet, Cursor, NodeId, ParseError, Span};
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
8pub struct Node {
9    pub kind: AstKind,
10    pub span: Span,
11    pub parent: Option<NodeId>,
12}
13
14#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
15#[serde(tag = "type", rename_all = "snake_case")]
16pub enum AstKind {
17    Empty,
18    Anchor {
19        kind: AnchorKind,
20    },
21    Literal {
22        c: char,
23        escaped: bool,
24    },
25    Dot,
26    Class {
27        negated: bool,
28        items: Vec<ClassItem>,
29        set: ClassSet,
30    },
31    Group {
32        kind: GroupKind,
33        inner: NodeId,
34    },
35    Alt {
36        arms: Vec<NodeId>,
37    },
38    Concat {
39        parts: Vec<NodeId>,
40    },
41    Repeat {
42        inner: NodeId,
43        kind: RepKind,
44        greedy: bool,
45    },
46}
47
48impl AstKind {
49    #[must_use]
50    pub fn children(&self) -> &[NodeId] {
51        match self {
52            Self::Group { inner, .. } | Self::Repeat { inner, .. } => std::slice::from_ref(inner),
53            Self::Alt { arms } => arms,
54            Self::Concat { parts } => parts,
55            Self::Empty
56            | Self::Anchor { .. }
57            | Self::Literal { .. }
58            | Self::Dot
59            | Self::Class { .. } => &[],
60        }
61    }
62}
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
65#[serde(rename_all = "snake_case")]
66pub enum AnchorKind {
67    Start,
68    End,
69}
70
71#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
72#[serde(tag = "kind", rename_all = "snake_case")]
73pub enum GroupKind {
74    Capture { index: u32, name: Option<Box<str>> },
75    NonCapture,
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
79#[serde(tag = "kind", rename_all = "snake_case")]
80pub enum RepKind {
81    ZeroOrOne,
82    ZeroOrMore,
83    OneOrMore,
84    Range { min: u32, max: Option<u32> },
85}
86
87#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
88pub struct GroupInfo {
89    pub index: u32,
90    pub name: Option<Box<str>>,
91    pub node: NodeId,
92}
93
94/// An immutable, lossless pattern syntax tree backed by a flat arena.
95#[derive(Clone, Debug)]
96pub struct Pattern {
97    pub(crate) src: Arc<str>,
98    pub(crate) nodes: Vec<Node>,
99    pub(crate) groups: Vec<GroupInfo>,
100    pub(crate) root: NodeId,
101}
102
103impl Pattern {
104    /// Parse a pattern into its lossless syntax tree.
105    ///
106    /// # Errors
107    ///
108    /// Returns [`ParseError`] when `src` is malformed or uses an unsupported feature.
109    pub fn parse(src: &str) -> Result<Self, ParseError> {
110        crate::parse(src)
111    }
112
113    #[must_use]
114    pub fn source(&self) -> &str {
115        &self.src
116    }
117
118    #[must_use]
119    pub const fn root_id(&self) -> NodeId {
120        self.root
121    }
122
123    #[must_use]
124    pub fn root(&self) -> Cursor<'_> {
125        Cursor::new(self, self.root)
126    }
127
128    #[must_use]
129    pub fn node(&self, id: NodeId) -> &Node {
130        &self.nodes[id.0 as usize]
131    }
132
133    #[must_use]
134    pub fn nodes(&self) -> &[Node] {
135        &self.nodes
136    }
137
138    #[must_use]
139    pub fn groups(&self) -> &[GroupInfo] {
140        &self.groups
141    }
142
143    #[must_use]
144    pub fn len(&self) -> usize {
145        self.nodes.len()
146    }
147
148    #[must_use]
149    pub fn is_empty(&self) -> bool {
150        self.nodes.is_empty()
151    }
152
153    #[must_use]
154    pub fn text(&self, span: Span) -> &str {
155        &self.src[span.start as usize..span.end as usize]
156    }
157}