~starkingdoms/starkingdoms

4ea4c4fa871a7dec830b43197333b6f8899f6af5 — ghostly_zsh 1 year, 4 months ago 19c233f
debug printing
5 files changed, 249 insertions(+), 4 deletions(-)

M kabel/Cargo.toml
A kabel/src/debug.rs
M kabel/src/lexer.rs
M kabel/src/lib.rs
M kabel/src/macros.rs
M kabel/Cargo.toml => kabel/Cargo.toml +3 -1
@@ 7,4 7,6 @@ edition = "2021"

[features]
timer = []
debug = []
debug = ["debug_lexer", "debug_parser"]
debug_lexer = []
debug_parser = []

A kabel/src/debug.rs => kabel/src/debug.rs +189 -0
@@ 0,0 1,189 @@
use crate::{lexer::Token, parser::AST, push_output};

pub fn debug_token_array(tokens: Vec<Token>) -> 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
}

M kabel/src/lexer.rs => kabel/src/lexer.rs +33 -2
@@ 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(())
    }
}

M kabel/src/lib.rs => kabel/src/lib.rs +5 -1
@@ 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;
    }

M kabel/src/macros.rs => kabel/src/macros.rs +19 -0
@@ 13,6 13,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) => {
        $crate::parser::AST {


@@ 54,6 64,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) => {
        $crate::error::KabelError::new(