1pub mod builder;
4pub mod destination;
5pub mod rewrite;
6
7use std::ops::{Bound, RangeBounds};
8
9use cfg_grammar::HistoryId;
10use cfg_symbol::Symbol;
11
12use self::Separator::*;
13
14#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
16pub struct Sequence {
17 pub lhs: Symbol,
19 pub rhs: Symbol,
21 pub start: u32,
23 pub end: Option<u32>,
26 pub separator: Separator,
28 pub history_id: Option<HistoryId>,
30}
31
32#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
34pub enum Separator {
35 Trailing(Symbol),
38 Proper(Symbol),
40 Liberal(Symbol),
43 Null,
45}
46
47impl Sequence {
48 pub fn inclusive(mut self, start: u32, end: Option<u32>) -> Self {
50 self.start = start;
51 self.end = end;
52 self
53 }
54
55 pub fn separator(mut self, sep: Separator) -> Self {
57 self.separator = sep;
58 self
59 }
60
61 pub fn range(self, range: impl RangeBounds<u32>) -> Self {
63 let to_option = |bound: Bound<u32>, diff| match bound {
64 Bound::Included(included) => Some(included),
65 Bound::Excluded(excluded) => Some((excluded as i64 + diff) as u32),
66 Bound::Unbounded => None,
67 };
68 self.inclusive(
69 to_option(range.start_bound().cloned(), 1).unwrap_or(0),
70 to_option(range.end_bound().cloned(), -1),
71 )
72 }
73}
74
75impl Separator {
76 pub fn prefix_separator(self) -> Self {
78 match self {
79 Proper(sep) | Liberal(sep) => Trailing(sep),
80 other => other,
81 }
82 }
83}
84
85impl Into<Option<Symbol>> for Separator {
86 fn into(self) -> Option<Symbol> {
87 match self {
88 Trailing(sep) => Some(sep),
89 _ => None,
90 }
91 }
92}