#![allow(dead_code)]
use crate::logic::grammar::Segment;
use crate::logic::parse::arena::TypeId;
use crate::logic::typing::TypingRuntime;
use super::{ChildRef, NodeId, TypedParser};
use crate::logic::parse::arena::{ParseArena, Span};
use crate::logic::parse::State;
use crate::logic::parse::arena::Lexeme;
pub fn render_node_text<T: TypingRuntime>(
parser: &TypedParser<T>,
node_id: NodeId,
segments: &[Segment],
) -> String {
let Some(alts) = parser.arena().alts_for(node_id) else {
return String::new();
};
let Some(alt) = alts.first() else {
return String::new();
};
let mut parts = Vec::new();
for child in &alt.children {
match child {
ChildRef::Node(child_id) => parts.push(render_node_text(parser, *child_id, segments)),
ChildRef::Terminal(Lexeme {
matched: span,
complete,
..
}) => {
if *complete {
parts.push(render_span(*span, segments));
}
}
}
}
parts
.into_iter()
.filter(|part| !part.is_empty())
.collect::<Vec<_>>()
.join(" ")
}
pub fn pretty_node<T: TypingRuntime>(
parser: &TypedParser<T>,
node_id: NodeId,
segments: &[Segment],
) -> String {
let mut out = String::new();
render_pretty(parser.arena(), node_id, segments, 0, &mut out);
out
}
fn render_pretty(
arena: &ParseArena,
node_id: NodeId,
segments: &[Segment],
indent: usize,
out: &mut String,
) {
let Some(node) = arena.node(node_id) else {
return;
};
let pad = " ".repeat(indent);
out.push_str(&format!(
"{}node {:?} nt={:?} span=({},{}) status={:?} ty={}\n",
pad,
node_id,
node.nt,
node.span.start,
node.span.end,
node.status,
render_type_label(Some(node.ty))
));
out.push_str(&format!("{}bindings={:?}\n", pad, node.bindings));
if let Some(alts) = arena.alts_for(node_id) {
for (idx, alt) in alts.iter().enumerate() {
out.push_str(&format!("{}alt {} prod={:?}\n", pad, idx, alt.prod));
for child in &alt.children {
match child {
ChildRef::Node(child_id) => {
render_pretty(arena, *child_id, segments, indent + 1, out)
}
ChildRef::Terminal(Lexeme {
matched: span,
complete,
open,
}) => out.push_str(&format!(
"{} term {:?} complete={} open={} text='{}'\n",
pad,
span,
complete,
open,
render_span(*span, segments)
)),
}
}
}
}
}
fn render_type_label(type_id: Option<TypeId>) -> String {
match type_id {
Some(id) => format!("TypeId({})", id),
None => "None".to_string(),
}
}
fn render_span(span: Span, segments: &[Segment]) -> String {
(span.start as usize..span.end as usize)
.filter_map(|idx| segments.get(idx).map(|s| s.as_str().to_string()))
.collect::<Vec<_>>()
.join(" ")
}
pub fn pretty_prefix_state<T: TypingRuntime>(
parser: &TypedParser<T>,
state: &State,
segments: &[Segment],
) -> String {
let mut out = String::new();
out.push_str(&format!(
"State span=({}, {}) root={} frontier={}\n",
state.span.start,
state.span.end,
state.root,
state.frontier.as_ref().map_or(0, |f: &Vec<_>| f.len()),
));
out.push_str("root:\n");
let pretty = pretty_node(parser, state.root, segments);
for line in pretty.lines() {
out.push_str(" ");
out.push_str(line);
out.push('\n');
}
out
}