1use std::ops::{Bound, RangeBounds};
4
5use crate::destination::SequenceDestination;
6use crate::{Separator, Sequence};
7use cfg_history::earley::History;
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<History>,
16 destination: D,
17}
18
19impl<D> SequenceRuleBuilder<D>
20where
21 D: SequenceDestination,
22{
23 pub fn new(destination: D) -> Self {
25 SequenceRuleBuilder {
26 lhs: None,
27 range: None,
28 history: None,
29 separator: Separator::Null,
30 destination,
31 }
32 }
33
34 pub fn sequence(mut self, lhs: Symbol) -> Self {
36 self.lhs = Some(lhs);
37 self.separator = Separator::Null;
38 self
39 }
40
41 pub fn separator(mut self, sep: Separator) -> Self {
43 self.separator = sep;
44 self
45 }
46
47 pub fn intersperse(self, sym: Symbol) -> Self {
49 self.separator(Separator::Proper(sym))
50 }
51
52 pub fn history(mut self, history: History) -> Self {
55 self.history = Some(history);
56 self
57 }
58
59 pub fn inclusive(mut self, start: u32, end: Option<u32>) -> Self {
61 self.range = Some((start, end));
62 self
63 }
64
65 pub fn rhs(mut self, rhs: Symbol) -> Self {
67 let history = self.history.take();
68 self.rhs_with_history(rhs, history)
69 }
70
71 pub fn range(self, range: impl RangeBounds<u32>) -> Self {
73 let to_option = |bound: Bound<u32>, diff| match bound {
74 Bound::Included(included) => Some(included),
75 Bound::Excluded(excluded) => Some((excluded as i64 + diff) as u32),
76 Bound::Unbounded => None,
77 };
78 self.inclusive(
79 to_option(range.start_bound().cloned(), 1).unwrap_or(0),
80 to_option(range.end_bound().cloned(), -1),
81 )
82 }
83
84 pub fn rhs_with_range(self, rhs: Symbol, range: impl RangeBounds<u32>) -> Self {
86 self.range(range).rhs(rhs)
87 }
88
89 pub fn rhs_with_history(mut self, rhs: Symbol, history: Option<History>) -> Self {
91 let (start, end) = self.range.take().expect("expected inclusive(n, m)");
92 self.destination.add_sequence(Sequence {
93 lhs: self.lhs.unwrap(),
94 rhs,
95 start,
96 end,
97 separator: self.separator,
98 history,
99 });
100 self
101 }
102}