cfg_predict_sets/
first.rs1use std::collections::BTreeMap;
6
7use cfg_grammar::{Cfg, SymbolBitSet};
8use cfg_symbol::Symbol;
9
10use crate::sets::PerSymbolSetVal;
11
12use super::{PerSymbolSets, PredictSets};
13
14pub struct FirstSets {
16 pub(super) map: PerSymbolSets,
17 lookahead: PerSymbolSetVal,
18 changed: bool,
19 terminal_set: SymbolBitSet,
20}
21
22impl FirstSets {
31 pub fn new(grammar: &Cfg) -> Self {
39 let mut this = FirstSets {
40 map: BTreeMap::new(),
41 lookahead: PerSymbolSetVal::new(),
42 changed: true,
43 terminal_set: grammar.terminal_symbols(),
44 };
45
46 this.collect_from(grammar);
47 this
48 }
49
50 pub fn first_set_for_string(&self, string: &[Symbol]) -> PerSymbolSetVal {
52 let mut result = vec![];
53 for &sym in string {
54 if self.terminal_set[sym] {
55 result.push(sym);
56 break;
57 } else {
58 let first_set = self
59 .map
60 .get(&sym)
61 .expect("FIRST set not found in PerSymbolSets");
62 result.clone_from(&first_set.list);
63 if !result.is_empty() {
64 break;
65 }
66 }
67 }
68 PerSymbolSetVal {
69 has_none: result.is_empty(),
70 list: result,
71 }
72 }
73
74 fn collect_from(&mut self, grammar: &Cfg) {
75 while self.changed {
76 self.changed = false;
77 for rule in grammar.rules() {
78 let set_changed = self.process_rule(rule.lhs, &rule.rhs[..]);
79 self.changed |= set_changed;
80 }
81 }
82 }
83
84 fn process_rule(&mut self, lhs: Symbol, rhs: &[Symbol]) -> bool {
85 self.first_set_collect(rhs);
86 let first_set = self.map.entry(lhs).or_insert_with(PerSymbolSetVal::new);
87 let prev_cardinality = first_set.len();
88 first_set.list.extend(self.lookahead.list.iter().cloned());
89 first_set.list.sort_unstable();
90 first_set.list.dedup();
91 first_set.has_none |= self.lookahead.has_none;
92 self.lookahead.list.clear();
93 self.lookahead.has_none = false;
94 prev_cardinality != first_set.len()
95 }
96
97 fn first_set_collect(&mut self, rhs: &[Symbol]) {
99 for &sym in rhs {
100 let mut nullable = false;
101 if self.terminal_set[sym] {
102 self.lookahead.list.push(sym);
103 self.lookahead.list.sort_unstable();
104 self.lookahead.list.dedup();
105 } else {
106 match self.map.get(&sym) {
107 None => {
108 }
114 Some(&PerSymbolSetVal { has_none, ref list }) => {
115 self.lookahead.list.extend(list.iter().copied());
116 self.lookahead.list.sort_unstable();
117 self.lookahead.list.dedup();
118 if has_none {
119 nullable = true;
120 }
121 }
122 }
123 }
124 if !nullable {
125 return;
127 }
128 }
129 self.lookahead.has_none = true;
130 }
131}
132
133impl PredictSets for FirstSets {
134 fn predict_sets(&self) -> &PerSymbolSets {
136 &self.map
137 }
138}