use super::{Lookahead, StateIdx};
use crate::input::{Node, ProdIdx};
#[derive(Clone, Debug)]
pub enum Error {
StatesOverflow,
CycleError(CycleError),
Conflict {
lalr_tables: super::Table,
state: StateIdx,
conflict: Conflict,
},
}
impl From<crate::lr::StatesOverflow> for Error {
fn from(_: crate::lr::StatesOverflow) -> Self {
Self::StatesOverflow
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CycleError {
pub node: Node,
pub path: Vec<ProdIdx>,
}
impl From<CycleError> for Error {
fn from(err: CycleError) -> Self {
Self::CycleError(err)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Conflict {
pub lookahead: Lookahead,
pub contributions: ConflictContributions,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConflictContributions {
pub has_shift: bool,
pub reduces: Vec<ProdIdx>,
}
impl ConflictContributions {
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
let mut len = self.reduces.len();
if self.has_shift {
len += 1;
}
len
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn conflict_contributions_len() {
let conflict_contributions = ConflictContributions {
has_shift: true,
reduces: vec![
ProdIdx {
lhs: Node(0),
index: 0,
},
ProdIdx {
lhs: Node(0),
index: 1,
},
],
};
assert_eq!(conflict_contributions.len(), 3);
let conflict_contributions = ConflictContributions {
has_shift: false,
reduces: vec![
ProdIdx {
lhs: Node(0),
index: 0,
},
ProdIdx {
lhs: Node(0),
index: 1,
},
],
};
assert_eq!(conflict_contributions.len(), 2);
}
}