1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! Sequence rules can be built with the builder pattern.

use std::ops::{Bound, RangeBounds};

use crate::history::HistoryId;
use crate::sequence::destination::SequenceDestination;
use crate::sequence::{Separator, Sequence};
use crate::symbol::Symbol;

/// Sequence rule builder.
pub struct SequenceRuleBuilder<D> {
    lhs: Option<Symbol>,
    range: Option<(u32, Option<u32>)>,
    separator: Separator,
    history: Option<HistoryId>,
    default_history: Option<HistoryId>,
    destination: D,
}

impl<D> SequenceRuleBuilder<D>
where
    D: SequenceDestination,
{
    /// Creates a sequence rule builder.
    pub fn new(destination: D) -> Self {
        SequenceRuleBuilder {
            lhs: None,
            range: None,
            history: None,
            default_history: None,
            separator: Separator::Null,
            destination: destination,
        }
    }

    /// Sets the default history source.
    pub fn default_history(self, default_history: HistoryId) -> SequenceRuleBuilder<D> {
        SequenceRuleBuilder {
            lhs: self.lhs,
            range: self.range,
            history: self.history,
            default_history: Some(default_history),
            separator: self.separator,
            destination: self.destination,
        }
    }

    /// Starts building a sequence rule.
    pub fn sequence(mut self, lhs: Symbol) -> Self {
        self.lhs = Some(lhs);
        self.separator = Separator::Null;
        self
    }

    /// Assigns the separator symbol and mode of separation.
    pub fn separator(mut self, sep: Separator) -> Self {
        self.separator = sep;
        self
    }

    /// Sets proper separation with the given separator symbol.
    pub fn intersperse(self, sym: Symbol) -> Self {
        self.separator(Separator::Proper(sym))
    }

    /// Assigns the rule history, which is used on the next call to `rhs`, or overwritten by a call
    /// to `rhs_with_history`.
    pub fn history(mut self, history: HistoryId) -> Self {
        self.history = Some(history);
        self
    }

    /// Assigns the inclusive range of the number of repetitions.
    pub fn inclusive(mut self, start: u32, end: Option<u32>) -> Self {
        self.range = Some((start, end));
        self
    }

    /// Adds a sequence rule to the grammar.
    pub fn rhs(mut self, rhs: Symbol) -> Self {
        let history = self.history.take().or(self.default_history);
        self.rhs_with_history(rhs, history)
    }

    /// Adds a range to the sequence.
    pub fn range(self, range: impl RangeBounds<u32>) -> Self {
        let to_option = |bound: Bound<u32>, diff| match bound {
            Bound::Included(included) => Some(included),
            Bound::Excluded(excluded) => Some((excluded as i64 + diff) as u32),
            Bound::Unbounded => None,
        };
        self.inclusive(
            to_option(range.start_bound().cloned(), 1).unwrap_or(0),
            to_option(range.end_bound().cloned(), -1),
        )
    }

    /// Adds a sequence rule to the grammar.
    pub fn rhs_with_range(self, rhs: Symbol, range: impl RangeBounds<u32>) -> Self {
        self.range(range).rhs(rhs)
    }

    /// Adds a sequence rule to the grammar.
    pub fn rhs_with_history(mut self, rhs: Symbol, history_id: Option<HistoryId>) -> Self {
        let (start, end) = self.range.take().expect("expected inclusive(n, m)");
        self.destination.add_sequence(Sequence {
            lhs: self.lhs.unwrap(),
            rhs,
            start,
            end,
            separator: self.separator,
            history_id,
        });
        self
    }
}