1use core::fmt;
2use iregex::automata::AnyRange;
3use std::fmt::Write;
4
5use crate::{Ast, Atom, Charset, Disjunction, Repeat, Sequence};
6
7impl fmt::Display for Ast {
8 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9 if self.start_anchor {
10 f.write_char('^')?;
11 }
12
13 self.disjunction.fmt(f)?;
14
15 if self.end_anchor {
16 f.write_char('$')
17 } else {
18 Ok(())
19 }
20 }
21}
22
23impl fmt::Display for Disjunction {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 for (i, sequence) in self.iter().enumerate() {
26 if i > 0 {
27 f.write_char('|')?;
28 }
29
30 sequence.fmt(f)?;
31 }
32
33 Ok(())
34 }
35}
36
37impl fmt::Display for Sequence {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 for atom in self {
40 atom.fmt(f)?;
41 }
42
43 Ok(())
44 }
45}
46
47impl fmt::Display for Atom {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 match self {
50 Self::Any => f.write_char('.'),
51 Self::Char(c) => fmt_char(*c, f),
52 Self::Set(charset) => charset.fmt(f),
53 Self::Repeat(atom, repeat) => {
54 atom.fmt(f)?;
55 repeat.fmt(f)
56 }
57 Self::Group(g) => {
58 f.write_char('(')?;
59 g.fmt(f)?;
60 f.write_char(')')
61 }
62 }
63 }
64}
65
66impl fmt::Display for Charset {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 if self.negative {
69 f.write_char('^')?;
70 }
71
72 for &range in &self.set {
73 fmt_range(range, f)?
74 }
75
76 Ok(())
77 }
78}
79
80impl fmt::Display for Repeat {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 if self.min == 0 && self.max == Some(1) {
83 f.write_char('?')
84 } else if self.min == 0 && self.max.is_none() {
85 f.write_char('*')
86 } else if self.min == 1 && self.max.is_some() {
87 f.write_char('+')
88 } else {
89 match self.max {
90 Some(max) => {
91 if self.min == max {
92 write!(f, "{{{}}}", self.min)
93 } else {
94 write!(f, "{{{},{}}}", self.min, max)
95 }
96 }
97 None => write!(f, "{{{},}}", self.min),
98 }
99 }
100 }
101}
102
103pub fn fmt_range(range: AnyRange<char>, f: &mut fmt::Formatter) -> fmt::Result {
104 if range.len() == 1 {
105 fmt_char(range.first().unwrap(), f)
106 } else {
107 let a = range.first().unwrap();
108 let b = range.last().unwrap();
109
110 fmt_char(a, f)?;
111 if a as u32 + 1 < b as u32 {
112 write!(f, "-")?;
113 }
114 fmt_char(b, f)
115 }
116}
117
118pub fn fmt_char(c: char, f: &mut fmt::Formatter) -> fmt::Result {
119 match c {
120 '(' => write!(f, "\\("),
121 ')' => write!(f, "\\)"),
122 '[' => write!(f, "\\["),
123 ']' => write!(f, "\\]"),
124 '{' => write!(f, "\\{{"),
125 '}' => write!(f, "\\}}"),
126 '?' => write!(f, "\\?"),
127 '*' => write!(f, "\\*"),
128 '+' => write!(f, "\\+"),
129 '-' => write!(f, "\\-"),
130 '^' => write!(f, "\\^"),
131 '|' => write!(f, "\\|"),
132 '\\' => write!(f, "\\\\"),
133 '\0' => write!(f, "\\0"),
134 '\x07' => write!(f, "\\a"),
135 '\x08' => write!(f, "\\b"),
136 '\t' => write!(f, "\\t"),
137 '\n' => write!(f, "\\n"),
138 '\x0b' => write!(f, "\\v"),
139 '\x0c' => write!(f, "\\f"),
140 '\r' => write!(f, "\\r"),
141 '\x1b' => write!(f, "\\e"),
142 _ => fmt::Display::fmt(&c, f),
143 }
144}
145
146