use crate::collections::{Map, Set};
use crate::lr1::core::*;
use crate::lr1::lookahead::*;
mod test;
use super::ConflictIndex;
#[derive(Clone, Debug)]
pub struct ContextSet {
values: Vec<TokenSet>,
}
#[derive(Debug)]
pub struct OverlappingLookahead;
impl ContextSet {
pub fn new(num_conflicts: usize) -> Self {
ContextSet {
values: (0..num_conflicts).map(|_| TokenSet::new()).collect(),
}
}
pub fn union(set1: &ContextSet, set2: &ContextSet) -> Result<Self, OverlappingLookahead> {
let mut result = set1.clone();
for (i, t) in set2.values.iter().enumerate() {
result.insert(ConflictIndex::new(i), t)?;
}
Ok(result)
}
pub fn insert(
&mut self,
conflict: ConflictIndex,
set: &TokenSet,
) -> Result<bool, OverlappingLookahead> {
for (value, index) in self.values.iter().zip((0..).map(ConflictIndex::new)) {
if index != conflict && value.is_intersecting(&set) {
return Err(OverlappingLookahead);
}
}
Ok(self.values[conflict.index].union_with(&set))
}
pub fn apply<'grammar>(&self, state: &mut LR1State<'grammar>, actions: &Set<Action<'grammar>>) {
let lookaheads: Map<Action<'grammar>, &TokenSet> =
actions.iter().cloned().zip(&self.values).collect();
for &mut (ref mut lookahead, production) in &mut state.reductions {
let action = Action::Reduce(production);
*lookahead = lookaheads[&action].clone();
}
}
}