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 colored::Colorize;
|
||||||
use serde::{Deserialize, Serialize};
|
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)]
|
#[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
@ -514,6 +514,7 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
};
|
};
|
||||||
let push_function_disassembly = |function_disassembly: &str, disassembly: &mut String| {
|
let push_function_disassembly = |function_disassembly: &str, disassembly: &mut String| {
|
||||||
disassembly.push_str(function_disassembly);
|
disassembly.push_str(function_disassembly);
|
||||||
|
disassembly.push('\n');
|
||||||
};
|
};
|
||||||
let mut disassembly = String::new();
|
let mut disassembly = String::new();
|
||||||
let top_border = "┌".to_string() + &"─".repeat(self.width - 2) + "┐";
|
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
|
disassembly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,91 +1,198 @@
|
|||||||
use annotate_snippets::{renderer::Style, Level, Renderer, Snippet};
|
use colored::{ColoredString, Colorize, CustomColor};
|
||||||
use colored::{Colorize, CustomColor};
|
|
||||||
|
|
||||||
use crate::{lex, Token};
|
use crate::{lex, Token};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct Formatter<'src> {
|
pub struct Formatter<'src> {
|
||||||
source: &'src str,
|
source: &'src str,
|
||||||
origin: Option<&'src str>,
|
lines: Vec<(String, LineKind, usize)>,
|
||||||
footer: Option<&'src str>,
|
next_line: String,
|
||||||
|
indent: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Formatter<'src> {
|
impl<'src> Formatter<'src> {
|
||||||
pub fn new(source: &'src str) -> Self {
|
pub fn new(source: &'src str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source,
|
source,
|
||||||
origin: None,
|
lines: Vec::new(),
|
||||||
footer: None,
|
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 {
|
pub fn footer(&mut self, footer: &'src str) -> &mut Self {
|
||||||
self.source = footer;
|
self.source = footer;
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(&self) -> String {
|
pub fn format(&mut self) -> String {
|
||||||
let tokens = match lex(self.source) {
|
let tokens = match lex(self.source) {
|
||||||
Ok(tokens) => tokens,
|
Ok(tokens) => tokens,
|
||||||
Err(error) => return format!("{}", error),
|
Err(error) => return format!("{}", error),
|
||||||
};
|
};
|
||||||
let mut block_depth = 0;
|
let mut line_kind = LineKind::Empty;
|
||||||
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(" ");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (token, _) in tokens {
|
for (token, _) in tokens {
|
||||||
|
use Token::*;
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
Token::Boolean(boolean) => formatted.push_str(&boolean.red()),
|
Boolean(boolean) => {
|
||||||
Token::Byte(byte) => formatted.push_str(&byte.green()),
|
self.push_colored(boolean.red());
|
||||||
Token::Character(character) => formatted.push_str(
|
|
||||||
&character
|
if line_kind != LineKind::Assignment {
|
||||||
|
line_kind = LineKind::Expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Byte(byte) => {
|
||||||
|
self.push_colored(byte.green());
|
||||||
|
|
||||||
|
if line_kind != LineKind::Assignment {
|
||||||
|
line_kind = LineKind::Expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Character(character) => {
|
||||||
|
self.push_colored(
|
||||||
|
character
|
||||||
.to_string()
|
.to_string()
|
||||||
.custom_color(CustomColor::new(225, 150, 150)),
|
.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;
|
|
||||||
|
|
||||||
formatted.push_str(token.as_str());
|
if line_kind != LineKind::Assignment {
|
||||||
line_break(&mut formatted, block_depth)
|
line_kind = LineKind::Expression;
|
||||||
}
|
}
|
||||||
Token::RightCurlyBrace => {
|
}
|
||||||
block_depth -= 1;
|
Float(float) => {
|
||||||
|
self.push_colored(float.yellow());
|
||||||
|
|
||||||
line_break(&mut formatted, block_depth);
|
if line_kind != LineKind::Assignment {
|
||||||
formatted.push_str(token.as_str());
|
line_kind = LineKind::Expression;
|
||||||
}
|
}
|
||||||
Token::Semicolon => {
|
|
||||||
formatted.push_str(token.as_str());
|
|
||||||
line_break(&mut formatted, block_depth);
|
|
||||||
}
|
}
|
||||||
Token::Eof => continue,
|
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 => {
|
token => {
|
||||||
formatted.push_str(token.as_str());
|
self.next_line.push_str(token.as_str());
|
||||||
formatted.push(' ');
|
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