iowo/crates/lang/src/lst_parser/output.rs

192 lines
5.9 KiB
Rust

use owo_colors::{unset_override, OwoColorize};
use rowan::{GreenNode, GreenNodeBuilder, GreenNodeData, GreenTokenData, Language, NodeOrToken};
use std::mem;
use crate::lst_parser::{
input::MEANINGLESS_TOKS,
syntax_kind::{Lang, SyntaxKind},
};
use super::{error::SyntaxError, events::Event};
pub struct Output {
pub green_node: GreenNode,
pub errors: Vec<SyntaxError>,
}
impl std::fmt::Debug for Output {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut errs: Vec<&SyntaxError> = self.errors.iter().collect();
errs.reverse();
debug_print_green_node(NodeOrToken::Node(&self.green_node), f, 0, &mut errs, false)
}
}
fn debug_print_green_node(
node: NodeOrToken<&GreenNodeData, &GreenTokenData>,
f: &mut dyn std::fmt::Write,
lvl: i32,
errs: &mut Vec<&SyntaxError>,
colored: bool,
) -> std::fmt::Result {
for _ in 0..lvl {
f.write_str(" ")?;
}
if !colored {
owo_colors::set_override(false);
} else {
owo_colors::set_override(true);
}
let r = match node {
NodeOrToken::Node(n) => {
let kind = Lang::kind_from_raw(node.kind());
if kind != SyntaxKind::PARSE_ERR {
writeln!(
f,
"{:?} {}",
Lang::kind_from_raw(node.kind()).bright_yellow().bold(),
"{".yellow()
)?;
} else {
let err = errs
.pop()
.expect("all error syntax nodes should correspond to an error")
.bright_red();
writeln!(
f,
"{:?}{} {err:?} {}",
kind.bright_red().bold(),
":".red(),
"{".bright_red().bold()
)?;
}
for c in n.children() {
debug_print_green_node(c, f, lvl + 1, errs, colored)?;
}
for _ in 0..lvl {
f.write_str(" ")?;
}
if kind != SyntaxKind::PARSE_ERR {
write!(f, "{}", "}\n".yellow())
} else {
write!(f, "{}", "}\n".bright_red().bold())
}
}
NodeOrToken::Token(t) => {
let tok = Lang::kind_from_raw(t.kind());
if MEANINGLESS_TOKS.contains(tok) {
writeln!(
f,
"{:?} {:?}{}",
Lang::kind_from_raw(t.kind()).white(),
t.text().white(),
";".white()
)
} else {
writeln!(
f,
"{:?} {:?}{}",
Lang::kind_from_raw(t.kind()).bright_cyan().bold(),
t.text().green(),
";".yellow()
)
}
}
};
if !colored {
owo_colors::unset_override();
}
r
}
impl Output {
pub fn debug_colored(&self) -> String {
let mut out = String::new();
let mut errs: Vec<&SyntaxError> = self.errors.iter().collect();
errs.reverse();
let _ = debug_print_green_node(
NodeOrToken::Node(&self.green_node),
&mut out,
0,
&mut errs,
true,
);
out
}
pub fn from_parser_output(
mut raw_toks: Vec<(SyntaxKind, &str)>,
(mut events, errs): (Vec<Event>, Vec<SyntaxError>),
) -> Self {
let mut builder = GreenNodeBuilder::new();
let mut fw_parents = Vec::new();
raw_toks.reverse();
for i in 0..events.len() {
match mem::replace(&mut events[i], Event::tombstone()) {
Event::Start {
kind,
forward_parent,
} => {
if kind == SyntaxKind::TOMBSTONE && forward_parent.is_none() {
continue;
}
fw_parents.push(kind);
let mut idx = i;
let mut fp = forward_parent;
while let Some(fwd) = fp {
idx += fwd as usize;
fp = match mem::replace(&mut events[idx], Event::tombstone()) {
Event::Start {
kind,
forward_parent,
} => {
fw_parents.push(kind);
forward_parent
}
_ => unreachable!(),
}
}
// remove whitespace bc it's ugly
while let Some((SyntaxKind::WHITESPACE | SyntaxKind::NEWLINE, _)) =
raw_toks.last()
{
match events.iter_mut().find(|ev| matches!(ev, Event::Eat { .. })) {
Some(Event::Eat { count }) => *count -= 1,
_ => unreachable!(),
}
let (tok, text): (SyntaxKind, &str) = raw_toks.pop().unwrap();
builder.token(tok.into(), text);
}
for kind in fw_parents.drain(..).rev() {
if kind != SyntaxKind::TOMBSTONE {
builder.start_node(kind.into());
}
}
}
Event::Finish => builder.finish_node(),
Event::Eat { count } => (0..count).for_each(|_| {
let (tok, text): (SyntaxKind, &str) = raw_toks.pop().unwrap();
builder.token(tok.into(), text);
}),
Event::Error => todo!(),
}
}
Self {
green_node: builder.finish(),
errors: errs,
}
}
}