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