pomsky_syntax/exprs/
group.rs1use crate::Span;
2
3use super::Rule;
4
5#[derive(Debug, Clone)]
11#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
12pub struct Group {
13 pub parts: Vec<Rule>,
14 pub kind: GroupKind,
15 pub span: Span,
16}
17
18impl Group {
19 pub fn new(parts: Vec<Rule>, kind: GroupKind, span: Span) -> Self {
20 Group { parts, kind, span }
21 }
22
23 #[cfg(feature = "dbg")]
24 pub(super) fn pretty_print(&self, buf: &mut crate::PrettyPrinter, needs_parens: bool) {
25 let use_parens =
26 matches!(self.kind, GroupKind::Capturing(_) | GroupKind::Atomic) || needs_parens;
27
28 match &self.kind {
29 GroupKind::Capturing(capture) => {
30 buf.push(':');
31 if let Some(name) = &capture.name {
32 buf.push_str(name);
33 }
34 }
35 GroupKind::Atomic => {
36 buf.push_str("atomic ");
37 }
38 GroupKind::Normal | GroupKind::Implicit => {}
39 }
40
41 if self.parts.is_empty() {
42 buf.push_str("()");
43 } else {
44 if self.kind != GroupKind::Implicit {
45 buf.start_indentation("(");
46 }
47
48 let len = self.parts.len();
49 for (i, part) in self.parts.iter().enumerate() {
50 let child_needs_parens = if len == 1 {
51 if use_parens { false } else { needs_parens }
52 } else {
53 use Rule::*;
54 matches!(part, Lookaround(_) | StmtExpr(_) | Alternation(_) | Group(_))
55 };
56 part.pretty_print(buf, child_needs_parens);
57 if i < len - 1 {
58 buf.write("\n");
59 }
60 }
61
62 if self.kind != GroupKind::Implicit {
63 buf.end_indentation(")");
64 }
65 }
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
71pub enum GroupKind {
72 Capturing(Capture),
74 Atomic,
76 Normal,
78 Implicit,
80}
81
82impl GroupKind {
83 pub fn is_normal(&self) -> bool {
84 matches!(self, GroupKind::Normal)
85 }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct Capture {
90 pub name: Option<String>,
91}
92
93impl Capture {
94 pub fn new(name: Option<&str>) -> Self {
95 Capture { name: name.map(str::to_string) }
96 }
97}
98
99#[cfg(feature = "arbitrary")]
100impl arbitrary::Arbitrary<'_> for Capture {
101 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
102 if u.arbitrary()? {
103 Ok(Capture { name: Some(super::arbitrary::Ident::create(u)?) })
104 } else {
105 Ok(Capture { name: None })
106 }
107 }
108
109 fn size_hint(_depth: usize) -> (usize, Option<usize>) {
110 (1, None)
111 }
112}