/* * Copyright 2022 Arnaud Golfouse * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! For debugging: pretty-print a `Table`. use super::GrammarFormat; use ielr::{ input::{Node, Symbol}, output::{Lookahead, Table}, }; use std::{collections::HashMap, fmt::Display}; pub struct TableDisplay<'a> { table: &'a Table, grammar_format: &'a GrammarFormat, } impl<'a> TableDisplay<'a> { #[allow(dead_code)] pub fn new(table: &'a Table, grammar_format: &'a GrammarFormat) -> Self { Self { table, grammar_format, } } fn get_node(&self, node: Node) -> &str { &self.grammar_format.symbols[&Symbol::Node(node)] } fn get_symbol(&self, symbol: Symbol) -> &str { &self.grammar_format.symbols[&symbol] } fn get_lookahead(&self, lookahead: Lookahead) -> &str { match lookahead { Lookahead::Eof => "EOF", Lookahead::Token(token) => &self.grammar_format.symbols[&Symbol::Token(token)], } } } impl Display for TableDisplay<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let start_states: HashMap<_, _> = self .table .get_all_starts() .map(|(node, state)| (state.get() as usize, node)) .collect(); f.write_str("Table {\n")?; for (index, state) in self.table.states.iter().enumerate() { write!(f, " State({index}): ")?; if let Some(node) = start_states.get(&index) { write!(f, "[START({})] ", self.get_node(*node))?; } f.write_str("{\n items: [\n")?; for item in state.all_items() { write!(f, " {} →", self.get_node(item.production.lhs))?; let rhs = self .grammar_format .grammar .get_rhs(item.production) .unwrap_or_default(); for (idx, symbol) in rhs.iter().enumerate() { f.write_str(if idx == item.index as usize { "∙" } else { " " })?; f.write_str(self.get_symbol(*symbol))?; } if item.index as usize == rhs.len() { f.write_str("∙")?; } f.write_str(" { ")?; for (idx, lookahead) in item.get_all_lookaheads().enumerate() { if idx != 0 { f.write_str(", ")?; } f.write_str(self.get_lookahead(lookahead))?; } f.write_str(" },\n")?; } f.write_str(" ],\n")?; f.write_str(" transitions: {\n")?; for (symbol, to) in state.get_all_transitions() { writeln!( f, " {} ⇒ State({}),", self.get_symbol(symbol), to.get() )?; } f.write_str(" },\n")?; f.write_str(" },\n")?; } f.write_str("}") } }