1use std::fmt;
4
5use super::{CharClassItem, Grammar, GrammarExpr, GrammarFormat, GrammarRule, RuleKind};
6
7const MAX_SAFE_INTEGER: u64 = (1 << 53) - 1;
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
12pub struct ExprBuilder;
13
14impl ExprBuilder {
15 #[must_use]
17 pub const fn empty(self) -> GrammarExpr {
18 GrammarExpr::Empty
19 }
20
21 #[must_use]
23 pub fn term(self, value: impl Into<String>) -> GrammarExpr {
24 GrammarExpr::terminal(value)
25 }
26
27 #[must_use]
29 pub fn terminal(self, value: impl Into<String>) -> GrammarExpr {
30 GrammarExpr::terminal(value)
31 }
32
33 #[must_use]
35 pub fn terminal_insensitive(self, value: impl Into<String>) -> GrammarExpr {
36 GrammarExpr::terminal_insensitive(value)
37 }
38
39 #[must_use]
41 pub const fn char(self, value: char) -> GrammarExpr {
42 GrammarExpr::CharRange(value, value)
43 }
44
45 #[must_use]
47 pub const fn char_range(self, start: char, end: char) -> GrammarExpr {
48 GrammarExpr::CharRange(start, end)
49 }
50
51 #[must_use]
53 pub fn char_class<I>(self, negated: bool, items: I) -> GrammarExpr
54 where
55 I: IntoIterator<Item = CharClassItem>,
56 {
57 GrammarExpr::char_class(negated, items)
58 }
59
60 #[must_use]
62 pub const fn any(self) -> GrammarExpr {
63 GrammarExpr::AnyChar
64 }
65
66 #[must_use]
68 pub fn nt(self, value: impl Into<String>) -> GrammarExpr {
69 GrammarExpr::non_terminal(value)
70 }
71
72 #[must_use]
74 pub fn non_terminal(self, value: impl Into<String>) -> GrammarExpr {
75 GrammarExpr::non_terminal(value)
76 }
77
78 #[must_use]
80 pub fn choice<I>(self, ordered: bool, alternatives: I) -> GrammarExpr
81 where
82 I: IntoIterator<Item = GrammarExpr>,
83 {
84 GrammarExpr::choice(ordered, alternatives)
85 }
86
87 #[must_use]
89 pub fn choice_ordered<I>(self, alternatives: I) -> GrammarExpr
90 where
91 I: IntoIterator<Item = GrammarExpr>,
92 {
93 GrammarExpr::choice(true, alternatives)
94 }
95
96 #[must_use]
98 pub fn choice_unordered<I>(self, alternatives: I) -> GrammarExpr
99 where
100 I: IntoIterator<Item = GrammarExpr>,
101 {
102 GrammarExpr::choice(false, alternatives)
103 }
104
105 #[must_use]
107 pub fn seq<I>(self, items: I) -> GrammarExpr
108 where
109 I: IntoIterator<Item = GrammarExpr>,
110 {
111 GrammarExpr::sequence(items)
112 }
113
114 #[must_use]
116 pub fn opt(self, expr: GrammarExpr) -> GrammarExpr {
117 GrammarExpr::optional(expr)
118 }
119
120 #[must_use]
122 pub fn rep0(self, expr: GrammarExpr) -> GrammarExpr {
123 GrammarExpr::zero_or_more(expr)
124 }
125
126 #[must_use]
128 pub fn rep1(self, expr: GrammarExpr) -> GrammarExpr {
129 GrammarExpr::one_or_more(expr)
130 }
131
132 #[must_use]
134 pub fn repeat(self, expr: GrammarExpr, min: usize, max: Option<usize>) -> GrammarExpr {
135 GrammarExpr::repeat(expr, min, max)
136 }
137
138 #[must_use]
140 pub fn and(self, expr: GrammarExpr) -> GrammarExpr {
141 GrammarExpr::and(expr)
142 }
143
144 #[must_use]
146 pub fn not(self, expr: GrammarExpr) -> GrammarExpr {
147 GrammarExpr::not(expr)
148 }
149
150 #[must_use]
152 pub fn capture(self, label: Option<impl Into<String>>, expr: GrammarExpr) -> GrammarExpr {
153 match label {
154 Some(label) => GrammarExpr::capture(label, expr),
155 None => GrammarExpr::capture_unlabeled(expr),
156 }
157 }
158
159 #[must_use]
161 pub fn capture_unlabeled(self, expr: GrammarExpr) -> GrammarExpr {
162 GrammarExpr::capture_unlabeled(expr)
163 }
164}
165
166#[must_use]
170pub fn sequence(items: Vec<GrammarExpr>) -> GrammarExpr {
171 let mut flattened = Vec::with_capacity(items.len());
172 for item in items {
173 match item {
174 GrammarExpr::Empty => {}
175 GrammarExpr::Sequence(nested) => flattened.extend(nested),
176 item => flattened.push(item),
177 }
178 }
179 match flattened.len() {
180 0 => GrammarExpr::Empty,
181 1 => flattened.remove(0),
182 _ => GrammarExpr::Sequence(flattened),
183 }
184}
185
186#[must_use]
190pub fn choice(alternatives: Vec<GrammarExpr>, ordered: bool) -> GrammarExpr {
191 let mut flattened = Vec::with_capacity(alternatives.len());
192 for alternative in alternatives {
193 match alternative {
194 GrammarExpr::Choice {
195 ordered: nested_ordered,
196 alternatives: nested,
197 } if nested_ordered == ordered => flattened.extend(nested),
198 alternative => flattened.push(alternative),
199 }
200 }
201 match flattened.len() {
202 0 => GrammarExpr::Empty,
203 1 => flattened.remove(0),
204 _ => GrammarExpr::Choice {
205 ordered,
206 alternatives: flattened,
207 },
208 }
209}
210
211#[derive(Clone, Copy, Debug, PartialEq, Eq)]
214pub struct RepetitionBoundsError {
215 pub min: u64,
217 pub max: Option<u64>,
219}
220
221impl fmt::Display for RepetitionBoundsError {
222 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
223 let max = self.max.map_or_else(String::new, |max| max.to_string());
224 write!(formatter, "invalid repetition bounds {}..{max}", self.min)
225 }
226}
227
228impl std::error::Error for RepetitionBoundsError {}
229
230pub fn canonical_repeat(
241 expr: GrammarExpr,
242 min: u64,
243 max: Option<u64>,
244) -> Result<GrammarExpr, RepetitionBoundsError> {
245 let invalid = RepetitionBoundsError { min, max };
246 if min > MAX_SAFE_INTEGER || max.is_some_and(|max| max > MAX_SAFE_INTEGER || max < min) {
247 return Err(invalid);
248 }
249 let bound = |value: u64| usize::try_from(value).map_err(|_| invalid);
250 Ok(match (min, max) {
251 (0, None) => GrammarExpr::zero_or_more(expr),
252 (1, None) => GrammarExpr::one_or_more(expr),
253 (0, Some(1)) => GrammarExpr::optional(expr),
254 (min, max) => GrammarExpr::repeat(expr, bound(min)?, max.map(bound).transpose()?),
255 })
256}
257
258#[derive(Clone, Debug, Default, PartialEq, Eq)]
260pub struct GrammarBuilder {
261 grammar: Grammar,
262}
263
264impl GrammarBuilder {
265 #[must_use]
267 pub const fn new() -> Self {
268 Self {
269 grammar: Grammar::new(),
270 }
271 }
272
273 #[must_use]
275 pub const fn source_format(mut self, source_format: GrammarFormat) -> Self {
276 self.grammar.source_format = Some(source_format);
277 self
278 }
279
280 #[must_use]
282 pub fn start(mut self, start: impl Into<String>) -> Self {
283 self.grammar.start = Some(start.into());
284 self
285 }
286
287 #[must_use]
289 pub fn rule(mut self, name: impl Into<String>, expr: GrammarExpr) -> Self {
290 self.grammar.rules.push(GrammarRule::new(name, expr));
291 self
292 }
293
294 #[must_use]
296 pub fn grammar_rule(mut self, rule: GrammarRule) -> Self {
297 self.grammar.rules.push(rule);
298 self
299 }
300
301 #[must_use]
303 pub fn rule_with_kind(
304 mut self,
305 name: impl Into<String>,
306 expr: GrammarExpr,
307 kind: RuleKind,
308 ) -> Self {
309 self.grammar
310 .rules
311 .push(GrammarRule::new(name, expr).with_kind(kind));
312 self
313 }
314
315 #[must_use]
317 pub fn build(self) -> Grammar {
318 self.grammar
319 }
320}