1use std::collections::{BTreeMap, BTreeSet};
4
5use cfg_symbol::Symbol;
6
7use cfg_grammar::symbol::set::SymbolBitSet;
8use cfg_grammar::RuleContainer;
9
10use super::{PerSymbolSets, PredictSets};
11
12pub struct FollowSets {
14 map: PerSymbolSets,
16}
17
18impl FollowSets {
19 pub fn new<'a, G>(grammar: &'a G, start_sym: Symbol, first_sets: &PerSymbolSets) -> Self
22 where
23 G: RuleContainer,
24 {
25 let mut this = FollowSets {
26 map: BTreeMap::new(),
27 };
28
29 for rule in grammar.rules() {
30 let follow_set = this.map.entry(rule.lhs).or_insert_with(BTreeSet::new);
31 if rule.lhs == start_sym {
32 follow_set.insert(None);
33 }
34 }
35
36 let mut changed = true;
37 while changed {
38 changed = false;
39 let terminal_set = SymbolBitSet::terminal_set(grammar);
40 for rule in grammar.rules() {
41 let mut follow_set = this.map.get(&rule.lhs).unwrap().clone();
42
43 for &sym in rule.rhs.iter().rev() {
44 if terminal_set.has_sym(sym) {
45 follow_set.clear();
46 follow_set.insert(Some(sym));
47 } else {
48 let followed = this.map.get_mut(&sym).unwrap();
49 let prev_cardinality = followed.len();
50 followed.extend(follow_set.iter().cloned());
51 changed |= prev_cardinality != followed.len();
52
53 let first_set = first_sets.get(&sym).unwrap();
54 if !first_set.contains(&None) {
55 follow_set.clear();
56 }
57 follow_set.extend(first_set.iter().cloned());
58 }
59 }
60 }
61 }
62
63 this
64 }
65}
66
67impl PredictSets for FollowSets {
68 fn predict_sets(&self) -> &PerSymbolSets {
70 &self.map
71 }
72}