use crate::grammar::repr::*;
use crate::lr1::core::*;
use super::Tracer;
use super::trace_graph::*;
#[cfg(test)]
mod test;
impl<'grammar> Tracer<'_, 'grammar> {
pub fn backtrace_reduce(
mut self,
item_state: StateIndex,
item: Lr0Item<'grammar>,
) -> TraceGraph<'grammar> {
self.trace_reduce_item(item_state, item);
self.trace_graph
}
fn trace_reduce_item(&mut self, item_state: StateIndex, item: Lr0Item<'grammar>) {
let nonterminal = &item.production.nonterminal;
self.trace_graph
.add_edge(nonterminal.clone(), item, item.symbol_sets());
let pred_states = self.state_graph.trace_back(item_state, item.prefix());
for pred_state in pred_states {
self.trace_reduce_from_state(pred_state, nonterminal);
}
}
fn trace_reduce_from_state(&mut self, item_state: StateIndex, nonterminal: &NonterminalString)
{
if !self.visited_set.insert((item_state, nonterminal.clone())) {
return;
}
for pred_item in self.states[item_state.0]
.items
.vec
.iter()
.filter(|i| i.can_shift_nonterminal(nonterminal))
{
let symbol_sets = pred_item.symbol_sets();
let first_suffix = self.first_sets.first0(symbol_sets.suffix);
let continue_tracing = first_suffix.contains_eof();
if !continue_tracing {
self.trace_graph
.add_edge(pred_item.to_lr0(), nonterminal.clone(), symbol_sets);
} else {
self.trace_graph.add_edge(
pred_item.production.nonterminal.clone(),
nonterminal.clone(),
symbol_sets,
);
self.trace_reduce_item(item_state, pred_item.to_lr0());
}
}
}
}