cfg_sequence/
rewrite.rs

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