#![allow(dead_code)]
use std::fmt::{Write, Error as FmtError};
use std::io::Write as IOWrite;
use crate::protocol::input_source::{InputSource, InputSpan};
use crate::protocol::parser::Module;
use crate::protocol::tokens::{Token, TokenKind, TokenMarker};
pub(crate) struct TokenWriter {
buffer: String,
}
impl TokenWriter {
pub(crate) fn new() -> Self {
return Self{
buffer: String::with_capacity(4096),
}
}
pub(crate) fn write<W: IOWrite>(&mut self, w: &mut W, modules: &[Module]) {
self.buffer.clear();
for module in modules {
self.write_module_tokens(module);
}
w.write_all(self.buffer.as_bytes()).expect("write tokens");
}
fn write_module_tokens(&mut self, module: &Module) {
self.write_dashed_indent(0);
match &module.name {
Some(name) => writeln!(self.buffer, "Module: {}", name.1.as_str()).unwrap(),
None => self.buffer.push_str("Unnamed module\n"),
}
self.write_marker_array(&module.tokens.markers, 1).expect("write markers");
self.write_token_array(&module.source, &module.tokens.tokens, 1).expect("write tokens");
}
fn write_marker_array(&mut self, markers: &[TokenMarker], indent: u32) -> Result<(), FmtError> {
self.write_indent(indent);
writeln!(self.buffer, "Markers: [")?;
let marker_indent = indent + 1;
for marker in markers {
self.write_indent(marker_indent);
writeln!(self.buffer, "{:?}", marker)?;
}
self.write_indent(indent);
writeln!(self.buffer, "]")?;
return Ok(());
}
fn write_token_array(&mut self, source: &InputSource, tokens: &[Token], indent: u32) -> Result<(), FmtError> {
self.write_indent(indent);
writeln!(self.buffer, "Tokens: [")?;
let num_tokens = tokens.len();
let token_indent = indent + 1;
for token_index in 0..num_tokens {
// Skip uninteresting tokens
let token = &tokens[token_index];
if token.kind == TokenKind::SpanEnd {
continue;
}
self.write_indent(token_indent);
write!(self.buffer, "{:?} (index {})", token.kind, token_index)?;
if token.kind.has_span_end() {
let token_start = token.pos;
let token_end = tokens[token_index + 1].pos;
let section = source.section_at_span(InputSpan::from_positions(token_start, token_end));
writeln!(self.buffer, " text: {}", String::from_utf8_lossy(section))?;
} else {
self.buffer.push('\n');
}
}
self.write_indent(indent);
writeln!(self.buffer, "]")?;
return Ok(());
}
fn write_dashed_indent(&mut self, indent: u32) {
for _ in 0..indent * 2 {
self.buffer.push(' ');
}
self.buffer.push('-');
self.buffer.push(' ');
}
fn write_indent(&mut self, indent: u32) {
for _ in 0..(indent + 1)*2 {
self.buffer.push(' ');
}
}
}