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

205 lines
6.3 KiB
Rust
Raw Normal View History

use clap::builder;
2024-05-04 20:35:18 +00:00
use owo_colors::{unset_override, OwoColorize};
2024-04-24 09:07:38 +00:00
use rowan::{GreenNode, GreenNodeBuilder, GreenNodeData, GreenTokenData, Language, NodeOrToken};
use std::mem;
2024-05-04 20:35:18 +00:00
use crate::lst_parser::{
input::MEANINGLESS_TOKS,
syntax_kind::{Lang, SyntaxKind},
};
2024-04-24 09:07:38 +00:00
use super::{
error::SyntaxError,
events::{Event, NodeKind},
};
2024-04-24 09:07:38 +00:00
pub struct Output {
pub green_node: GreenNode,
pub errors: Vec<SyntaxError>,
}
2024-05-04 19:56:12 +00:00
2024-04-24 09:07:38 +00:00
impl std::fmt::Debug for Output {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2024-05-04 19:56:12 +00:00
let mut errs: Vec<&SyntaxError> = self.errors.iter().collect();
errs.reverse();
2024-05-04 20:35:18 +00:00
debug_print_green_node(NodeOrToken::Node(&self.green_node), f, 0, &mut errs, false)
2024-04-24 09:07:38 +00:00
}
}
const INDENT_STR: &str = " ";
2024-04-24 09:07:38 +00:00
fn debug_print_green_node(
node: NodeOrToken<&GreenNodeData, &GreenTokenData>,
2024-05-04 20:35:18 +00:00
f: &mut dyn std::fmt::Write,
2024-04-24 09:07:38 +00:00
lvl: i32,
2024-05-04 19:56:12 +00:00
errs: &mut Vec<&SyntaxError>,
2024-05-04 20:35:18 +00:00
colored: bool,
2024-04-24 09:07:38 +00:00
) -> std::fmt::Result {
for _ in 0..lvl {
f.write_str(INDENT_STR)?;
2024-04-24 09:07:38 +00:00
}
2024-05-04 20:35:18 +00:00
if !colored {
owo_colors::set_override(false);
} else {
owo_colors::set_override(true);
}
let r = match node {
2024-04-24 09:07:38 +00:00
NodeOrToken::Node(n) => {
2024-05-04 19:56:12 +00:00
let kind = Lang::kind_from_raw(node.kind());
if kind != SyntaxKind::PARSE_ERR {
2024-05-04 20:35:18 +00:00
writeln!(
f,
"{:?} {}",
Lang::kind_from_raw(node.kind()).bright_yellow().bold(),
"{".yellow()
)?;
2024-05-04 19:56:12 +00:00
} else {
let err = errs
.pop()
2024-05-04 20:35:18 +00:00
.expect("all error syntax nodes should correspond to an error")
.bright_red();
2024-05-04 19:56:12 +00:00
2024-05-04 20:35:18 +00:00
writeln!(
f,
"{:?}{} {err:?} {}",
kind.bright_red().bold(),
":".red(),
"{".bright_red().bold()
)?;
2024-05-04 19:56:12 +00:00
}
2024-04-24 09:07:38 +00:00
for c in n.children() {
2024-05-04 20:35:18 +00:00
debug_print_green_node(c, f, lvl + 1, errs, colored)?;
2024-04-24 09:07:38 +00:00
}
for _ in 0..lvl {
f.write_str(INDENT_STR)?;
2024-04-24 09:07:38 +00:00
}
2024-05-04 20:35:18 +00:00
if kind != SyntaxKind::PARSE_ERR {
write!(f, "{}", "}\n".yellow())
} else {
write!(f, "{}", "}\n".bright_red().bold())
}
2024-04-24 09:07:38 +00:00
}
NodeOrToken::Token(t) => {
2024-05-04 20:35:18 +00:00
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()
)
}
2024-04-24 09:07:38 +00:00
}
2024-05-04 20:35:18 +00:00
};
if !colored {
owo_colors::unset_override();
2024-04-24 09:07:38 +00:00
}
2024-05-04 20:35:18 +00:00
r
2024-04-24 09:07:38 +00:00
}
impl Output {
2024-05-04 20:35:18 +00:00
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
}
2024-04-24 09:07:38 +00:00
pub fn from_parser_output(
mut raw_toks: Vec<(SyntaxKind, &str)>,
mut events: Vec<Event>,
2024-04-24 09:07:38 +00:00
) -> Self {
let mut builder = GreenNodeBuilder::new();
let mut fw_parents = Vec::new();
let mut errors = Vec::new();
2024-04-24 09:07:38 +00:00
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() {
match kind {
NodeKind::Syntax(kind) if kind != SyntaxKind::TOMBSTONE => {
builder.start_node(kind.into())
}
NodeKind::Error(err) => {
errors.push(err);
builder.start_node(SyntaxKind::PARSE_ERR.into())
}
_ => {}
2024-04-24 09:07:38 +00:00
}
}
}
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);
}),
}
}
Self {
green_node: builder.finish(),
errors,
2024-04-24 09:07:38 +00:00
}
}
}