diff --git a/src/main.rs b/src/main.rs index 9e9b216..70e44c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,15 +2,23 @@ use compiler::{backend::spirv_meta, meta_compile}; use error::print_error; use std::{env, fs, path::PathBuf}; -use parser::parse_string; +use parser::{parse_string, tokenize, Token}; pub mod compiler; mod error; pub mod parser; +#[derive(Debug, Default, PartialEq)] +enum Trace { + Tokens, + AST, + #[default] Normal +} + #[derive(Debug, Default)] struct CompilerArgs { input: Option, output: Option, + trace: Trace, print_help: bool, print_version: bool, } @@ -43,6 +51,17 @@ fn main() { return; } }; + if args.trace == Trace::Tokens { + let tokens = tokenize(&src); + for tok in tokens { + match tok.item { + Token::LeftParen => println!("{:>3}:{:<3} LeftParen",tok.location.line_start(), tok.location.col_start()), + Token::RightParen => println!("{:>3}:{:<3} RightParen",tok.location.line_start(), tok.location.col_start()), + Token::Symbol( val ) => println!("{:>3}:{:<3} Symbol `{}`",tok.location.line_start(), tok.location.col_start(), val) + } + } + return; + } let ast = match parse_string(&src) { Ok(i) => i, @@ -51,6 +70,11 @@ fn main() { return; } }; + + if args.trace == Trace::AST { + ast.pretty_print(None,None); + return; + } let module = match meta_compile(ast) { Ok(m) => m, @@ -111,6 +135,36 @@ fn parse_args() -> CompilerArgs { return parsed_args; } } + "trace" => { + if parsed_args.trace == Trace::Normal { + let Some(output) = args.next() else { + parsed_args.print_help = true; + eprintln!("trace needs a file"); + eprintln!(); + return parsed_args; + }; + match output.as_str() { + "ast" | "AST" | "Ast" => { + parsed_args.trace = Trace::AST; + } + "token" | "tokens" => { + parsed_args.trace = Trace::Tokens; + } + a => { + eprintln!("unknown trace value {a}"); + eprintln!(); + parsed_args.print_help = true; + return parsed_args; + } + } + + } else { + eprintln!("trace can be passed only once"); + eprintln!(); + parsed_args.print_help = true; + return parsed_args; + } + } a => { eprintln!("unknown arg --{a}"); eprintln!(); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 550f0ad..75774d0 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -155,6 +155,31 @@ impl Ast { Ast::Root(_) => &Location::All, } } + + pub fn pretty_print(&self, prefix: Option<&String>, body_prefix: Option<&String>) { + let empty_string_to_make_rust_happy = &String::from(""); + let prefix_ = prefix.unwrap_or(&empty_string_to_make_rust_happy); + let body_prefix_ = body_prefix.unwrap_or(&empty_string_to_make_rust_happy); + match self { + Ast::Symbol(Localised { item, location }) => { + println!("{} Symbol `{}` ({}:{})", prefix_, item, location.line_start(), location.col_start()); + }, + Ast::List(Localised { item, location }) => { + println!("{} List ({}:{})", prefix_, location.line_start(), location.col_start()); + for i in 0..item.len()-2 { + item[i].pretty_print(Some(&(body_prefix_.to_owned() + &String::from(" ├─ "))), Some(&(body_prefix_.to_owned() + &String::from(" │ ")))); + } + item[item.len()-1].pretty_print(Some(&(body_prefix_.to_owned() + &String::from(" ╰─ "))), Some(&(body_prefix_.to_owned() + &String::from(" ")))); + }, + Ast::Root( items ) => { + println!("{} Root", prefix_); + for i in 0..items.len()-2 { + items[i].pretty_print(Some(&(body_prefix_.to_owned() + &String::from(" ├─ "))), Some(&(body_prefix_.to_owned() + &String::from(" │ ")))); + } + items[items.len()-1].pretty_print(Some(&(body_prefix_.to_owned() + &String::from(" ╰─ "))), Some(&(body_prefix_.to_owned() + &String::from(" ")))); + }, + } + } } pub fn tokenize(input: &str) -> Vec> {