From 4ea4c4fa871a7dec830b43197333b6f8899f6af5 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Wed, 7 Aug 2024 21:27:40 -0500 Subject: [PATCH] debug printing --- kabel/Cargo.toml | 4 +- kabel/src/debug.rs | 189 ++++++++++++++++++++++++++++++++++++++++++++ kabel/src/lexer.rs | 35 +++++++- kabel/src/lib.rs | 6 +- kabel/src/macros.rs | 19 +++++ 5 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 kabel/src/debug.rs diff --git a/kabel/Cargo.toml b/kabel/Cargo.toml index b9380fcfd6c7a36a6ef5fa7dd957d3715481811e..7217d6975ae83c38389fcca264c1cad5cc42cae4 100644 --- a/kabel/Cargo.toml +++ b/kabel/Cargo.toml @@ -7,4 +7,6 @@ edition = "2021" [features] timer = [] -debug = [] +debug = ["debug_lexer", "debug_parser"] +debug_lexer = [] +debug_parser = [] diff --git a/kabel/src/debug.rs b/kabel/src/debug.rs new file mode 100644 index 0000000000000000000000000000000000000000..7368424431abae2ebe21cc5427464237b34b7312 --- /dev/null +++ b/kabel/src/debug.rs @@ -0,0 +1,189 @@ +use crate::{lexer::Token, parser::AST, push_output}; + +pub fn debug_token_array(tokens: Vec) -> String { + let mut output = "".to_string(); + for token in tokens { + output += &token.token_type.to_string(); + output += "\n"; + } + output[..output.len()-1].to_string() +} +pub fn debug_ast(ast: AST, level: usize) -> String { + use crate::parser::ASTType::*; + use crate::parser::BinOp::*; + use crate::parser::UnOp::*; + use crate::parser::Lit::*; + let mut output = "".to_string(); + match ast.ast_type { + Program(asts) => { + output += &"| ".repeat(level); + output += "Program"; + for ast in asts { + output += "\n"; + output += &debug_ast(ast, level+1); + } + } + Function(name, args, block) => { + output += &"| ".repeat(level); + output += "Function "; + output += &(name.name + " "); + for arg in args { + output += &(arg.name + " "); + } + output += "\n"; + output += &"| ".repeat(level); + output += &debug_ast(*block, level+1); + } + Return(expr) => { + output += &"| ".repeat(level); + output += "Return"; + if let Some(expr) = *expr { + output += "\n"; + output += &debug_ast(expr, level+1); + } + } + Loop(block) => { + output += &"| ".repeat(level); + output += "Loop"; + output += "\n"; + output += &debug_ast(*block, level+1); + } + While(condition, block) => { + output += &"| ".repeat(level); + output += "While"; + output += "\n"; + output += &debug_ast(*condition, level+1); + output += "\n"; + output += &debug_ast(*block, level+1); + } + For(expr1, expr2, expr3, block) => { + output += &"| ".repeat(level); + output += "For"; + if let Some(expr1) = *expr1 { + output += "\n"; + output += &debug_ast(expr1, level+1); + } + if let Some(expr2) = *expr2 { + output += "\n"; + output += &debug_ast(expr2, level+1); + } + if let Some(expr3) = *expr3 { + output += "\n"; + output += &debug_ast(expr3, level+1); + } + output += "\n"; + output += &debug_ast(*block, level+1); + } + Break => { output += "Break\n"; } + Continue => { output += "Continue\n"; } + If(condition, block, else_expr) => { + output += &"| ".repeat(level); + output += "If\n"; + output += &debug_ast(*condition, level+1); + output += "\n"; + output += &debug_ast(*block, level+1); + if let Some(else_expr) = *else_expr { + output += "\n"; + output += &"| ".repeat(level); + output += "Else"; + output += "\n"; + output += &debug_ast(else_expr, level+1); + } + } + Block(asts) => { + output += &"| ".repeat(level); + output += "Block"; + for ast in asts { + output += "\n"; + output += &debug_ast(ast, level+1); + } + } + Decl(name, expr) => { + output += &"| ".repeat(level); + output += "Decl "; + output += &name.name; + output += "\n"; + output += &debug_ast(*expr, level+1); + } + Assign(name, expr) => { + output += &"| ".repeat(level); + output += "Assign "; + output += &name.name; + output += "\n"; + output += &debug_ast(*expr, level+1); + } + Ternary(condition, true_expr, false_expr) => { + output += &"| ".repeat(level); + output += "Ternary\n"; + output += &debug_ast(*condition, level+1); + output += "\n"; + output += &debug_ast(*true_expr, level+1); + output += "\n"; + output += &debug_ast(*false_expr, level+1); + } + Subscript(array, index) => { + output += &"| ".repeat(level); + output += "Subscript\n"; + output += &debug_ast(*array, level+1); + output += "\n"; + output += &debug_ast(*index, level+1); + } + Binary(left, oper, right) => { + output += &"| ".repeat(level); + output += "Binary "; + push_output!(oper, output, + Add, Sub, Mul, Div, Mod, BitAnd, BitXor, BitOr, + Eq, Ne, Gr, Ge, Ls, Le, Or, And); + output += "\n"; + output += &debug_ast(*left, level+1); + output += "\n"; + output += &debug_ast(*right, level+1); + } + Unary(oper, right) => { + output += &"| ".repeat(level); + output += "Unary "; + push_output!(oper, output, + Not, Neg); + output += "\n"; + output += &debug_ast(*right, level+1); + } + Lit(lit) => { + output += &"| ".repeat(level); + output += "Lit "; + match lit { + Ident(name) => { + output += &name; + } + Str(value) => { + output += &value; + } + Num(value) => { + output += &value.to_string(); + } + Array(value) => { + for value in value { + output += "\n"; + output += &debug_ast(value, level+1); + } + } + } + } + Call(name, args) => { + output += &"| ".repeat(level); + output += "Call "; + output += &name.name; + for arg in args { + output += "\n"; + output += &debug_ast(arg, level+1); + } + } + Member(left, right) => { + output += &"| ".repeat(level); + output += "Member\n"; + output += &debug_ast(*left, level+1); + output += "\n"; + output += &debug_ast(*right, level+1); + } + } + output +} diff --git a/kabel/src/lexer.rs b/kabel/src/lexer.rs index b04a304916f75cbfd7aa2e15139c75d16b0640e4..8266784bd86b2bc72504a544ef279850cc371638 100644 --- a/kabel/src/lexer.rs +++ b/kabel/src/lexer.rs @@ -1,8 +1,8 @@ -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Display}; use crate::{ error::{ErrorKind, KabelError}, - token, + token, token_display, }; pub struct Lexer { @@ -394,3 +394,34 @@ pub enum TokenType { Str(String), Num(f32), } + +impl Display for TokenType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use TokenType::*; + token_display!(*self, f, Function, Return, Loop, While, For, + Break, Continue, If, Else, Var, Star, StarEqual, + Slash, SlashEqual, Percent, PercentEqual, Plus, + PlusPlus, PlusEqual, Minus, MinusMinus, MinusEqual, + LeftParen, RightParen, LeftBrace, RightBrace, + LeftSquare, RightSquare, Equal, EqualEqual, + Bang, BangEqual, Greater, GreaterEqual, Less, + LessEqual, And, AndEqual, AndAnd, Or, OrEqual, OrOr, + Caret, CaretEqual, Period, Comma, Semicolon, Colon, Question); + match *self { + Ident(ref name) => { + f.write_str("Ident ")?; + f.write_str(name)?; + } + Str(ref value) => { + f.write_str("Str ")?; + f.write_str(value)?; + } + Num(ref value) => { + f.write_str("Num ")?; + f.write_str(&value.to_string())?; + } + _ => {} + } + Ok(()) + } +} diff --git a/kabel/src/lib.rs b/kabel/src/lib.rs index 008c26577b3a76f8fec964110ea0b1a5086141bb..8c8fe75e019f0451dc3cdb3d285b98a21b87448c 100644 --- a/kabel/src/lib.rs +++ b/kabel/src/lib.rs @@ -1,10 +1,12 @@ #[cfg(feature = "timer")] use std::time::Instant; +use debug::debug_token_array; use lexer::{Lexer, Token}; use parser::{Parser, AST}; use semantic_analysis::Analyzer; +pub mod debug; pub mod error; pub mod lexer; pub mod macros; @@ -50,7 +52,9 @@ pub fn compile(program: String) -> String { //println!("{}", error); } #[cfg(feature = "debug")] - println!("{:?}", lexer.output); + { + output += &debug_token_array(lexer.output.clone()); + } if lexer.errors.len() != 0 || lexer.output.len() == 0 { return output; } diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 2963126d495ec2165ed0193ae9e979c79c7ef3ee..7c066997f0576a0bc282caec2f8df404adddc996 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -12,6 +12,16 @@ macro_rules! token { }; } +#[macro_export] +macro_rules! token_display { + ( $match_to:expr, $f:expr, $( $name:tt),*) => { + match $match_to { + $( $name => { $f.write_str(stringify!($name))?; } ),* + _ => () + } + } +} + #[macro_export] macro_rules! lit { ($type:ident, $data:expr, $token:expr) => { @@ -53,6 +63,15 @@ macro_rules! name { }; } +#[macro_export] +macro_rules! push_output { + ( $match_to:expr, $output:expr, $( $name:tt),*) => { + match $match_to { + $( $name => { $output += stringify!($name); } ),* + } + } +} + #[macro_export] macro_rules! unexpected_token { ($self:expr, $message:expr, $token:expr) => {