1use std::borrow::{Borrow, BorrowMut};
4use std::collections::BTreeMap;
5
6use cfg_grammar::{Cfg, CfgRule, SymbolBitSet};
7use cfg_symbol::SymbolSource;
8use cfg_symbol_bit_matrix::{CfgSymbolBitMatrixExt, UnitDerivationMatrix};
9
10pub struct Cycles<G: Borrow<Cfg>> {
13 grammar: G,
14 unit_derivation: UnitDerivationMatrix,
15 cycle_free: Option<bool>,
16}
17
18impl<G: Borrow<Cfg>> Cycles<G> {
19 pub fn new(grammar: G) -> Self {
21 Cycles {
22 unit_derivation: grammar.borrow().unit_derivation_matrix(),
23 cycle_free: None,
24 grammar,
25 }
26 }
27
28 pub fn cycle_free(&mut self) -> bool {
30 *self.cycle_free.get_or_insert_with(|| {
31 SymbolSource::generate_fresh()
32 .take(self.grammar.borrow().num_syms())
33 .all(|i| !self.unit_derivation[(i, i)])
34 })
35 }
36
37 pub fn classify(&self) -> impl Iterator<Item = (&CfgRule, bool)> + '_ {
39 self.grammar.borrow().rules().map(move |rule| {
40 (
41 rule,
42 rule.rhs.len() == 1 && self.unit_derivation[(rule.rhs[0], rule.lhs)],
43 )
44 })
45 }
46
47 pub fn cycle_participants(&self, get_cyclical: bool) -> impl Iterator<Item = &CfgRule> + '_ {
49 self.classify().filter_map(move |(rule, is_cyclical)| {
50 if is_cyclical ^ !get_cyclical {
51 Some(rule)
52 } else {
53 None
54 }
55 })
56 }
57}
58
59impl<G: BorrowMut<Cfg>> Cycles<G> {
60 pub fn remove_cycles(&mut self) {
63 if !self.cycle_free() {
64 self.grammar.borrow_mut().retain(|rule| {
65 !(rule.rhs.len() == 1 && self.unit_derivation[(rule.rhs[0], rule.lhs)])
66 });
67 }
68 }
69
70 pub fn rewrite_cycles(&mut self) {
73 let mut translation = BTreeMap::new();
74 let mut row = SymbolBitSet::from_elem(self.grammar.borrow(), false);
75 if !self.cycle_free() {
76 let unit_derivation = &self.unit_derivation;
77 self.grammar.borrow_mut().retain(|rule| {
78 if rule.rhs.len() == 1 && unit_derivation[(rule.rhs[0], rule.lhs)] {
80 if !translation.contains_key(&rule.lhs) {
82 for (lhs_derives, s) in unit_derivation
85 .iter_row(rule.lhs.usize())
86 .zip(SymbolSource::generate_fresh())
87 {
88 row.set(s, lhs_derives && unit_derivation[(s, rule.lhs)])
89 }
90 for sym in row.iter() {
91 translation.insert(sym, Some(rule.lhs));
92 }
93 translation.insert(rule.lhs, None);
94 }
95 false
96 } else {
97 true
98 }
99 });
100 let mut rewritten_rules = vec![];
103 self.grammar.borrow_mut().retain(|rule| {
104 let mut new_rule = rule.clone();
105 let mut changed = false;
106 if let Some(&Some(new_lhs)) = translation.get(&rule.lhs) {
107 new_rule.lhs = new_lhs;
108 changed = true;
109 }
110 let mut rhs = new_rule.rhs.to_vec();
111 for sym in &mut rhs {
112 if let Some(&Some(new_sym)) = translation.get(sym) {
113 *sym = new_sym;
114 changed = true;
115 }
116 }
117 if changed {
118 rewritten_rules.push(CfgRule {
119 lhs: new_rule.lhs,
120 rhs: rhs.into(),
121 history: new_rule.history,
122 });
123 }
124 !changed
125 });
126 for rule in rewritten_rules {
127 self.grammar.borrow_mut().add_rule(rule);
128 }
129 }
130 }
131}