use super::Lookahead;
use crate::{
indices::{StateIdxRaw, SymbolIdx},
input::{Grammar, Node, ProdIdx, Symbol},
structures::{Map, Set},
};
use std::ops;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StateIdx(pub(crate) StateIdxRaw);
impl StateIdx {
pub const fn get(self) -> StateIdxRaw {
self.0
}
}
#[derive(Debug, Clone)]
pub struct State {
pub(crate) items: Vec<Item>,
pub(crate) core_items_len: usize,
pub(crate) action_table: InternalActionTable,
pub(crate) goto_table: Map<Node, StateIdx>,
pub accessing_symbol: Option<Symbol>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Item {
pub production: ProdIdx,
pub index: SymbolIdx,
pub(crate) lookaheads: Set<Lookahead>,
}
impl Item {
pub fn has_lookahead(&self, lookahead: Lookahead) -> bool {
self.lookaheads.contains(&lookahead)
}
pub fn get_all_lookaheads(&self) -> impl Iterator<Item = Lookahead> + '_ {
self.lookaheads.iter().copied()
}
pub fn current_symbol(&self, grammar: &Grammar) -> Option<Symbol> {
let rhs = grammar.get_rhs(self.production).unwrap_or_default();
rhs.get(self.index as usize).copied()
}
}
type InternalActionTable = Map<Lookahead, Action>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ActionTable<'a> {
internal: &'a InternalActionTable,
}
pub struct GotoTable<'a> {
internal: &'a Map<Node, StateIdx>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Action {
Shift(StateIdx),
Reduce(ProdIdx),
Accept(Node),
}
impl ActionTable<'_> {
pub fn get_action(self, lookahead: Lookahead) -> Option<Action> {
Some(*self.internal.get(&lookahead)?)
}
pub fn iter(&mut self) -> impl Iterator<Item = (Lookahead, Action)> + '_ {
self.internal
.iter()
.map(|(lookahead, action)| (*lookahead, *action))
}
}
impl GotoTable<'_> {
pub fn get_goto(self, node: Node) -> Option<StateIdx> {
self.internal.get(&node).copied()
}
pub fn iter(&mut self) -> impl Iterator<Item = (Node, StateIdx)> + '_ {
self.internal
.iter()
.map(|(node, to_state)| (*node, *to_state))
}
}
impl State {
pub fn action_table(&self) -> ActionTable {
ActionTable {
internal: &self.action_table,
}
}
pub fn goto_table(&self) -> GotoTable {
GotoTable {
internal: &self.goto_table,
}
}
pub fn transition(&self, symbol: Symbol) -> Option<StateIdx> {
match symbol {
Symbol::Token(t) => match self.action_table.get(&Lookahead::Token(t)) {
Some(Action::Shift(to_state)) => Some(*to_state),
_ => None,
},
Symbol::Node(n) => self.goto_table.get(&n).copied(),
}
}
pub fn get_all_transitions(&self) -> impl Iterator<Item = (Symbol, StateIdx)> + '_ {
self.action_table
.iter()
.filter_map(|(lookahead, action)| {
let token = match lookahead {
Lookahead::Eof => return None,
Lookahead::Token(token) => *token,
};
match action {
Action::Shift(to) => Some((Symbol::Token(token), *to)),
_ => None,
}
})
.chain(
self.goto_table
.iter()
.map(|(node, to)| (Symbol::Node(*node), *to)),
)
}
pub fn all_items(&self) -> &[Item] {
&self.items
}
pub fn core_items(&self) -> &[Item] {
&self.items[..self.core_items_len]
}
}
impl ops::Index<StateIdx> for [State] {
type Output = State;
fn index(&self, index: StateIdx) -> &Self::Output {
&self[index.0 as usize]
}
}
impl ops::Index<StateIdx> for Vec<State> {
type Output = State;
fn index(&self, index: StateIdx) -> &Self::Output {
&self[index.0 as usize]
}
}
impl ops::IndexMut<StateIdx> for Vec<State> {
fn index_mut(&mut self, index: StateIdx) -> &mut Self::Output {
&mut self[index.0 as usize]
}
}