cfg_sequence/
rewrite.rs

1//! Rewrites sequence rules into production rules.
2
3// #[cfg(feature = "nightly")]
4// use collections::range::RangeArgument;
5use std::collections::HashMap;
6use std::collections::hash_map::Entry;
7
8use crate::Separator::{self, Liberal, Proper, Trailing};
9use crate::Sequence;
10use crate::Symbol;
11use crate::destination::SequenceDestination;
12use cfg_grammar::Cfg;
13use cfg_grammar::rule_builder::RuleBuilder;
14use cfg_history::{
15    HistoryNodeRewriteSequence, HistoryNodeSequenceRhs, RootHistoryNode, earley::History,
16};
17
18/// Rewrites sequence rules into production rules.
19pub struct SequencesToProductions<'a> {
20    destination: &'a mut Cfg,
21    stack: Vec<Sequence>,
22    map: HashMap<PartialSequence, Symbol>,
23    top: Option<History>,
24    lhs: Option<Symbol>,
25}
26
27// A key into a private map.
28#[derive(Clone, Debug, Eq, Hash, PartialEq)]
29struct PartialSequence {
30    rhs: Symbol,
31    start: u32,
32    end: Option<u32>,
33    separator: Separator,
34}
35
36impl<'a> SequenceDestination for SequencesToProductions<'a> {
37    fn add_sequence(&mut self, seq: Sequence) {
38        self.rewrite(seq);
39    }
40}
41
42impl From<Sequence> for PartialSequence {
43    fn from(value: Sequence) -> Self {
44        PartialSequence {
45            rhs: value.rhs,
46            start: value.start,
47            end: value.end,
48            separator: value.separator,
49        }
50    }
51}
52
53impl<'a> SequencesToProductions<'a> {
54    /// Initializes a rewrite.
55    pub fn new(destination: &'a mut Cfg) -> Self {
56        SequencesToProductions {
57            destination,
58            stack: vec![],
59            map: HashMap::new(),
60            top: None,
61            lhs: None,
62        }
63    }
64
65    /// Rewrites a sequence rule.
66    pub fn rewrite(&mut self, top: Sequence) {
67        self.stack.clear();
68        self.map.clear();
69        let prev = top
70            .history
71            .unwrap_or_else(|| RootHistoryNode::Rule { lhs: top.lhs }.into());
72        let history_top = Into::into(HistoryNodeRewriteSequence {
73            top: true,
74            rhs: top.rhs,
75            sep: top.separator.into(),
76            prev,
77        });
78        self.top = Some(history_top);
79        self.reduce(top);
80        let prev = top.history.unwrap_or_else(|| RootHistoryNode::NoOp.into());
81        let history_bottom = Into::into(HistoryNodeRewriteSequence {
82            top: false,
83            rhs: top.rhs,
84            sep: top.separator.into(),
85            prev,
86        });
87        *self.top.as_mut().unwrap() = history_bottom;
88        while let Some(seq) = self.stack.pop() {
89            assert!(seq.start <= seq.end.unwrap_or(!0));
90            self.reduce(seq);
91        }
92    }
93
94    fn recurse(&mut self, seq: &Sequence) -> Symbol {
95        let sym_source = &mut self.destination;
96        // As a placeholder
97        let partial: PartialSequence = (*seq).into();
98
99        match self.map.entry(partial) {
100            Entry::Vacant(vacant) => {
101                let lhs = sym_source.next_sym(None);
102                vacant.insert(lhs);
103                self.stack.push(Sequence { lhs, ..*seq });
104                lhs
105            }
106            Entry::Occupied(lhs) => *lhs.get(),
107        }
108    }
109
110    fn rhs<A: AsRef<[Symbol]>>(&mut self, rhs: A) {
111        assert!(rhs.as_ref().len() <= 3);
112        let history = Into::into(HistoryNodeSequenceRhs {
113            prev: self.top.unwrap(),
114            rhs: [
115                rhs.as_ref().get(0).copied(),
116                rhs.as_ref().get(1).copied(),
117                rhs.as_ref().get(2).copied(),
118            ],
119        });
120        RuleBuilder::new(self.destination)
121            .rule(self.lhs.unwrap())
122            .history(history)
123            .rhs(rhs);
124    }
125
126    fn reduce(&mut self, sequence: Sequence) {
127        let Sequence {
128            lhs,
129            rhs,
130            start,
131            end,
132            separator,
133            ..
134        } = sequence;
135        self.lhs = Some(lhs);
136        // TODO optimize reductions
137        match (separator, start, end) {
138            (Liberal(sep), _, _) => {
139                let sym1 = self.recurse(&sequence.separator(Proper(sep)));
140                let sym2 = self.recurse(&sequence.separator(Trailing(sep)));
141                // seq ::= sym1 | sym2
142                self.rhs([sym1]);
143                self.rhs([sym2]);
144            }
145            (_, 0, Some(0)) => {
146                // seq ::= epsilon | sym
147                self.rhs([]);
148            }
149            (_, 0, end) => {
150                // seq ::= epsilon | sym
151                self.rhs([]);
152                let sym = self.recurse(&sequence.inclusive(1, end));
153                self.rhs([sym]);
154            }
155            (Trailing(sep), _, _) => {
156                let sym = self.recurse(&sequence.separator(Proper(sep)));
157                // seq ::= sym sep
158                self.rhs([sym, sep]);
159            }
160            (_, 1, None) => {
161                // ???
162                // seq ::= item
163                self.rhs([rhs]);
164                // Left recursive
165                // seq ::= seq sep item
166                if let Proper(sep) = separator {
167                    self.rhs([lhs, sep, rhs]);
168                } else {
169                    self.rhs([lhs, rhs]);
170                }
171            }
172            (_, 1, Some(1)) => {
173                self.rhs([rhs]);
174            }
175            (_, 1, Some(2)) => {
176                let sym1 = self.recurse(&sequence.range(1..=1));
177                let sym2 = self.recurse(&sequence.range(2..=2));
178                // seq ::= sym1 | sym2
179                self.rhs([sym1]);
180                self.rhs([sym2]);
181            }
182            (_, 1, Some(end)) => {
183                // end >= 3
184                let pow2 = end.next_power_of_two() / 2;
185                let (seq1, block, seq2) = (
186                    sequence.range(1..=pow2),
187                    sequence.range(pow2..=pow2),
188                    sequence.range(1..=end - pow2),
189                );
190                let rhs1 = self.recurse(&seq1);
191                let block = self.recurse(&block.separator(separator.prefix_separator()));
192                let rhs2 = self.recurse(&seq2);
193                // seq ::= sym1 sym2
194                self.rhs([rhs1]);
195                self.rhs([block, rhs2]);
196            }
197            (Proper(sep), 2, Some(2)) => {
198                self.rhs([rhs, sep, rhs]);
199            }
200            (_, 2, Some(2)) => {
201                self.rhs([rhs, rhs]);
202            }
203            (_, 2.., end) => {
204                // to do infinity
205                let (seq1, seq2) = if Some(start) == end {
206                    // A "block"
207                    let pow2 = start.next_power_of_two() / 2;
208                    (
209                        sequence.range(pow2..=pow2),
210                        sequence.range(start - pow2..=start - pow2),
211                    )
212                } else {
213                    // A "span"
214                    (
215                        sequence.range(start - 1..=start - 1),
216                        sequence.inclusive(1, end.map(|end| end - start + 1)),
217                    )
218                };
219                let (rhs1, rhs2) = (
220                    self.recurse(&seq1.separator(separator.prefix_separator())),
221                    self.recurse(&seq2.separator(separator)),
222                );
223                // seq ::= sym1 sym2
224                self.rhs([rhs1, rhs2]);
225            }
226        }
227    }
228}