1use std::ops::{Bound, RangeBounds};
4
5use crate::destination::SequenceDestination;
6use crate::{Separator, Sequence};
7use cfg_grammar::history::HistoryId;
8use cfg_symbol::Symbol;
9
10pub struct SequenceRuleBuilder<D: SequenceDestination> {
12 lhs: Option<Symbol>,
13 range: Option<(u32, Option<u32>)>,
14 separator: Separator,
15 history: Option<HistoryId>,
16 default_history: Option<HistoryId>,
17 destination: D,
18}
19
20impl<D> SequenceRuleBuilder<D>
21where
22 D: SequenceDestination,
23{
24 pub fn new(destination: D) -> Self {
26 SequenceRuleBuilder {
27 lhs: None,
28 range: None,
29 history: None,
30 default_history: None,
31 separator: Separator::Null,
32 destination,
33 }
34 }
35
36 pub fn default_history(self, default_history: HistoryId) -> Self {
38 SequenceRuleBuilder {
39 lhs: self.lhs,
40 range: self.range,
41 history: self.history,
42 default_history: Some(default_history),
43 separator: self.separator,
44 destination: self.destination,
45 }
46 }
47
48 pub fn sequence(mut self, lhs: Symbol) -> Self {
50 self.lhs = Some(lhs);
51 self.separator = Separator::Null;
52 self
53 }
54
55 pub fn separator(mut self, sep: Separator) -> Self {
57 self.separator = sep;
58 self
59 }
60
61 pub fn intersperse(self, sym: Symbol) -> Self {
63 self.separator(Separator::Proper(sym))
64 }
65
66 pub fn history(mut self, history: HistoryId) -> Self {
69 self.history = Some(history);
70 self
71 }
72
73 pub fn inclusive(mut self, start: u32, end: Option<u32>) -> Self {
75 self.range = Some((start, end));
76 self
77 }
78
79 pub fn rhs(mut self, rhs: Symbol) -> Self {
81 let history = self.history.take().or(self.default_history);
82 self.rhs_with_history(rhs, history)
83 }
84
85 pub fn range(self, range: impl RangeBounds<u32>) -> Self {
87 let to_option = |bound: Bound<u32>, diff| match bound {
88 Bound::Included(included) => Some(included),
89 Bound::Excluded(excluded) => Some((excluded as i64 + diff) as u32),
90 Bound::Unbounded => None,
91 };
92 self.inclusive(
93 to_option(range.start_bound().cloned(), 1).unwrap_or(0),
94 to_option(range.end_bound().cloned(), -1),
95 )
96 }
97
98 pub fn rhs_with_range(self, rhs: Symbol, range: impl RangeBounds<u32>) -> Self {
100 self.range(range).rhs(rhs)
101 }
102
103 pub fn rhs_with_history(mut self, rhs: Symbol, history_id: Option<HistoryId>) -> Self {
105 let (start, end) = self.range.take().expect("expected inclusive(n, m)");
106 self.destination.add_sequence(Sequence {
107 lhs: self.lhs.unwrap(),
108 rhs,
109 start,
110 end,
111 separator: self.separator,
112 history_id,
113 });
114 self
115 }
116}