Expand formatter
This commit is contained in:
parent
5d62d897f4
commit
3609fddaea
@ -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
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user