1#![deny(unsafe_code)]
4#![deny(missing_docs)]
5
6pub mod builder;
7pub mod destination;
8mod ext;
9pub mod rewrite;
10
11pub use crate::ext::CfgSequenceExt;
12
13use std::ops::{Bound, RangeBounds};
14
15use cfg_history::earley::History;
16use cfg_symbol::Symbol;
17
18use self::Separator::*;
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub struct Sequence {
23 pub lhs: Symbol,
25 pub rhs: Symbol,
27 pub start: u32,
29 pub end: Option<u32>,
32 pub separator: Separator,
34 pub history: Option<History>,
36}
37
38#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
40pub enum Separator {
41 Trailing(Symbol),
44 Proper(Symbol),
46 Liberal(Symbol),
49 Null,
51}
52
53impl Sequence {
54 pub fn inclusive(mut self, start: u32, end: Option<u32>) -> Self {
56 self.start = start;
57 self.end = end;
58 self
59 }
60
61 pub fn separator(mut self, sep: Separator) -> Self {
63 self.separator = sep;
64 self
65 }
66
67 pub fn range(self, range: impl RangeBounds<u32>) -> Self {
69 let to_option = |bound: Bound<u32>, diff| match bound {
70 Bound::Included(included) => Some(included),
71 Bound::Excluded(excluded) => Some((excluded as i64 + diff) as u32),
72 Bound::Unbounded => None,
73 };
74 self.inclusive(
75 to_option(range.start_bound().cloned(), 1).unwrap_or(0),
76 to_option(range.end_bound().cloned(), -1),
77 )
78 }
79}
80
81impl Separator {
82 pub fn prefix_separator(self) -> Self {
84 match self {
85 Proper(sep) | Liberal(sep) => Trailing(sep),
86 other => other,
87 }
88 }
89}
90
91impl From<Separator> for Option<Symbol> {
92 fn from(val: Separator) -> Option<Symbol> {
93 match val {
94 Trailing(sep) => Some(sep),
95 _ => None,
96 }
97 }
98}