use crate::grammar::repr::*;
use crate::lr1::core::*;
use super::trace_graph::*;
use super::Tracer;
#[cfg(test)]
mod test;
impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
pub fn backtrace_shift(
mut self,
item_state: StateIndex,
item: LR0Item<'grammar>,
) -> TraceGraph<'grammar> {
let symbol_sets = item.symbol_sets();
let pred_states = self.state_graph.trace_back(item_state, symbol_sets.prefix);
self.trace_graph
.add_edge(item.production.nonterminal.clone(), item, symbol_sets);
for pred_state in pred_states {
self.trace_epsilon_edges(pred_state, &item.production.nonterminal);
}
self.trace_graph
}
fn trace_epsilon_edges(&mut self, item_state: StateIndex, nonterminal: &NonterminalString) {
if self.visited_set.insert((item_state, nonterminal.clone())) {
for pred_item in self.states[item_state.0].items.vec.iter() {
if pred_item.can_shift_nonterminal(nonterminal) {
if pred_item.index > 0 {
self.trace_graph.add_edge(
pred_item,
nonterminal.clone(),
pred_item.symbol_sets(),
);
} else {
let pred_nonterminal = &pred_item.production.nonterminal;
self.trace_graph.add_edge(
pred_nonterminal.clone(),
nonterminal.clone(),
pred_item.symbol_sets(),
);
self.trace_epsilon_edges(item_state, pred_nonterminal);
}
}
}
}
}
}