1
0

Expand formatter

This commit is contained in:
Jeff 2024-10-13 12:04:32 -04:00
parent 5d62d897f4
commit 3609fddaea
2 changed files with 162 additions and 53 deletions

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Display};
use colored::Colorize;
use serde::{Deserialize, Serialize};
use crate::{AnnotatedError, Formatter, Identifier, Instruction, Operation, Span, Type, Value};
use crate::{AnnotatedError, Identifier, Instruction, Operation, Span, Type, Value};
#[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Chunk {
@ -514,6 +514,7 @@ impl<'a> ChunkDisassembler<'a> {
};
let push_function_disassembly = |function_disassembly: &str, disassembly: &mut String| {
disassembly.push_str(function_disassembly);
disassembly.push('\n');
};
let mut disassembly = String::new();
let top_border = "".to_string() + &"".repeat(self.width - 2) + "";
@ -656,6 +657,7 @@ impl<'a> ChunkDisassembler<'a> {
);
}
disassembly.pop(); // Remove the last newline character
disassembly
}

View File

@ -1,91 +1,198 @@
use annotate_snippets::{renderer::Style, Level, Renderer, Snippet};
use colored::{Colorize, CustomColor};
use colored::{ColoredString, Colorize, CustomColor};
use crate::{lex, Token};
#[derive(Debug, Copy, Clone)]
#[derive(Debug)]
pub struct Formatter<'src> {
source: &'src str,
origin: Option<&'src str>,
footer: Option<&'src str>,
lines: Vec<(String, LineKind, usize)>,
next_line: String,
indent: usize,
}
impl<'src> Formatter<'src> {
pub fn new(source: &'src str) -> Self {
Self {
source,
origin: None,
footer: None,
lines: Vec::new(),
next_line: String::new(),
indent: 0,
}
}
pub fn origin(&mut self, origin: &'src str) -> &mut Self {
self.origin = Some(origin);
self
}
pub fn footer(&mut self, footer: &'src str) -> &mut Self {
self.source = footer;
self
}
pub fn format(&self) -> String {
pub fn format(&mut self) -> String {
let tokens = match lex(self.source) {
Ok(tokens) => tokens,
Err(error) => return format!("{}", error),
};
let mut block_depth = 0;
let mut formatted = String::new();
let line_break = |formatted: &mut String, block_depth: i32| {
formatted.push('\n');
for _ in 0..block_depth {
formatted.push_str(" ");
}
};
let mut line_kind = LineKind::Empty;
for (token, _) in tokens {
use Token::*;
match token {
Token::Boolean(boolean) => formatted.push_str(&boolean.red()),
Token::Byte(byte) => formatted.push_str(&byte.green()),
Token::Character(character) => formatted.push_str(
&character
.to_string()
.custom_color(CustomColor::new(225, 150, 150)),
),
Token::Float(float) => formatted.push_str(&float.yellow()),
Token::Identifier(identifier) => {
formatted.push_str(&identifier.blue());
formatted.push(' ');
}
Token::Integer(integer) => formatted.push_str(&integer.cyan()),
Token::String(string) => formatted.push_str(&string.magenta()),
Token::LeftCurlyBrace => {
block_depth += 1;
Boolean(boolean) => {
self.push_colored(boolean.red());
formatted.push_str(token.as_str());
line_break(&mut formatted, block_depth)
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
Token::RightCurlyBrace => {
block_depth -= 1;
Byte(byte) => {
self.push_colored(byte.green());
line_break(&mut formatted, block_depth);
formatted.push_str(token.as_str());
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
Token::Semicolon => {
formatted.push_str(token.as_str());
line_break(&mut formatted, block_depth);
Character(character) => {
self.push_colored(
character
.to_string()
.custom_color(CustomColor::new(225, 150, 150)),
);
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
Token::Eof => continue,
Float(float) => {
self.push_colored(float.yellow());
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
Identifier(identifier) => {
self.push_colored(identifier.blue());
self.next_line.push(' ');
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
Integer(integer) => {
self.push_colored(integer.cyan());
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
String(string) => {
self.push_colored(string.magenta());
if line_kind != LineKind::Assignment {
line_kind = LineKind::Expression;
}
}
LeftCurlyBrace => {
self.next_line.push_str(token.as_str());
self.commit_line(LineKind::OpenBlock);
self.indent += 1;
}
RightCurlyBrace => {
self.commit_line(LineKind::CloseBlock);
self.next_line.push_str(token.as_str());
self.indent -= 1;
}
Semicolon => {
if line_kind != LineKind::Assignment {
line_kind = LineKind::Statement;
}
self.next_line.push_str(token.as_str());
self.commit_line(line_kind);
}
Let => {
line_kind = LineKind::Assignment;
self.push_colored(token.as_str().bold());
self.next_line.push(' ');
}
Break | Loop | Return | While => {
line_kind = LineKind::Statement;
self.push_colored(token.as_str().bold());
self.next_line.push(' ');
}
Eof => continue,
token => {
formatted.push_str(token.as_str());
formatted.push(' ');
self.next_line.push_str(token.as_str());
self.next_line.push(' ');
}
}
}
formatted
let mut previous_index = 0;
let mut current_index = 1;
while current_index < self.lines.len() {
let (_, previous, _) = &self.lines[previous_index];
let (_, current, _) = &self.lines[current_index];
println!("{:?} {:?}", previous, current);
match (previous, current) {
(LineKind::Empty, _)
| (_, LineKind::Empty)
| (LineKind::OpenBlock, _)
| (_, LineKind::CloseBlock) => {}
(left, right) if left == right => {}
_ => {
self.lines
.insert(current_index, ("".to_string(), LineKind::Empty, 0));
}
}
previous_index += 1;
current_index += 1;
}
let formatted = String::with_capacity(
self.lines
.iter()
.fold(0, |total, (line, _, _)| total + line.len()),
);
self.lines
.iter()
.enumerate()
.fold(formatted, |acc, (index, (line, _, indent))| {
let left_pad = " ".repeat(*indent);
if index == 0 {
return format!("{:<3}| {}{}", index + 1, left_pad, line);
}
format!("{}\n{:<3}| {}{}", acc, index + 1, left_pad, line)
})
}
fn push_colored(&mut self, colored: ColoredString) {
self.next_line.push_str(&format!("{}", colored));
}
fn commit_line(&mut self, line_kind: LineKind) {
self.lines
.push((self.next_line.clone(), line_kind, self.indent));
self.next_line.clear();
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LineKind {
Assignment,
FunctionCall,
Statement,
Expression,
Empty,
OpenBlock,
CloseBlock,
}