mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-01 17:51:48 -07:00
144 lines
3.0 KiB
Odin
144 lines
3.0 KiB
Odin
package odin_printer
|
|
|
|
import "core:odin/ast"
|
|
import "core:odin/tokenizer"
|
|
import "core:strings"
|
|
import "core:runtime"
|
|
import "core:fmt"
|
|
import "core:unicode/utf8"
|
|
import "core:mem"
|
|
|
|
Line :: struct {
|
|
format_tokens: [dynamic] Format_Token,
|
|
finalized: bool,
|
|
used: bool,
|
|
depth: int,
|
|
}
|
|
|
|
Format_Token :: struct {
|
|
kind: tokenizer.Token_Kind,
|
|
text: string,
|
|
spaces_before: int,
|
|
}
|
|
|
|
Printer :: struct {
|
|
string_builder: strings.Builder,
|
|
config: Config,
|
|
depth: int, //the identation depth
|
|
comments: [dynamic]^ast.Comment_Group,
|
|
allocator: mem.Allocator,
|
|
file: ^ast.File,
|
|
source_position: tokenizer.Pos,
|
|
lines: map [int]^Line,
|
|
skip_semicolon: bool,
|
|
current_line: ^Line,
|
|
current_line_index: int,
|
|
last_token: ^Format_Token,
|
|
}
|
|
|
|
Config :: struct {
|
|
spaces: int, //Spaces per indentation
|
|
newline_limit: int, //The limit of newlines between statements and declarations.
|
|
tabs: bool, //Enable or disable tabs
|
|
convert_do: bool, //Convert all do statements to brace blocks
|
|
semicolons: bool, //Enable semicolons
|
|
split_multiple_stmts: bool,
|
|
brace_style: Brace_Style,
|
|
align_assignments: bool,
|
|
align_style: Alignment_Style,
|
|
indent_cases: bool,
|
|
}
|
|
|
|
Brace_Style :: enum {
|
|
_1TBS,
|
|
Allman,
|
|
Stroustrup,
|
|
K_And_R,
|
|
}
|
|
|
|
Block_Type :: enum {
|
|
None,
|
|
If_Stmt,
|
|
Proc,
|
|
Generic,
|
|
Comp_Lit,
|
|
}
|
|
|
|
Alignment_Style :: enum {
|
|
Align_On_Colon_And_Equals,
|
|
Align_On_Type_And_Equals,
|
|
}
|
|
|
|
default_style := Config {
|
|
spaces = 4,
|
|
newline_limit = 2,
|
|
convert_do = false,
|
|
semicolons = true,
|
|
tabs = true,
|
|
brace_style = ._1TBS,
|
|
split_multiple_stmts = true,
|
|
align_assignments = true,
|
|
align_style = .Align_On_Type_And_Equals,
|
|
indent_cases = false,
|
|
};
|
|
|
|
make_printer :: proc(config: Config, allocator := context.allocator) -> Printer {
|
|
return {
|
|
config = config,
|
|
allocator = allocator,
|
|
};
|
|
}
|
|
|
|
print :: proc(p: ^Printer, file: ^ast.File) -> string {
|
|
|
|
for decl in file.decls {
|
|
visit_stmt(p, decl);
|
|
}
|
|
|
|
fix_lines(p);
|
|
|
|
builder := strings.make_builder(p.allocator);
|
|
|
|
last_line := 0;
|
|
|
|
for key, value in p.lines {
|
|
diff_line := min(key - last_line, p.config.newline_limit);
|
|
|
|
for i := 0; i < diff_line; i += 1 {
|
|
strings.write_byte(&builder, '\n');
|
|
}
|
|
|
|
for i := 0; i < value.depth * 4; i += 1 {
|
|
strings.write_byte(&builder, ' ');
|
|
}
|
|
|
|
for format_token in value.format_tokens {
|
|
|
|
for i := 0; i < format_token.spaces_before; i += 1 {
|
|
strings.write_byte(&builder, ' ');
|
|
}
|
|
|
|
strings.write_string(&builder, format_token.text);
|
|
}
|
|
|
|
last_line = key;
|
|
}
|
|
|
|
return strings.to_string(builder);
|
|
}
|
|
|
|
fix_lines :: proc(p: ^Printer) {
|
|
|
|
for key, value in p.lines {
|
|
|
|
if len(value.format_tokens) <= 0 {
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|