diff --git a/src/main.rs b/src/main.rs index 2353c53..8431cfc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use utils::ProblemCap; use variable::Variables; mod parser; @@ -8,9 +9,19 @@ mod variable; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("void main() {int x}".to_string(), 0, &mut vars); + let out = trsp.transpile("void main() {x int x}".to_string(), 0, &mut vars); for p in trsp.problems { - println!("{:?}: {}", p.problem_type, p.problem_msg) + match p { + ProblemCap::Error(problem) => { + println!( + "\x1b[31;1mError\x1b[0;1m: {}\x1b[0m\n{}:{}: {:?}", + problem.problem_msg, + problem.state.line, + problem.state.column, + problem.problem_type, + ) + } + } } println!("{out}\n\n\n{:?}", vars); } diff --git a/src/parser.rs b/src/parser.rs index 55f6262..e479d12 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,18 +2,31 @@ use std::usize; use crate::{ transpiler::{State, Transpiler}, - utils::{Problem, ProblemType}, + utils::{Problem, ProblemCap, ProblemType}, variable::Variables, }; #[derive(Clone, Debug)] +#[allow(dead_code)] pub enum Token { Number(String, State), + Keyword(String, State), Identifier(String, State), Curly(String, State), Round(String, State), // Square(String), } + +pub fn extract_state(token: Token) -> State { + match token { + Token::Number(_, state) => state, + Token::Identifier(_, state) => state, + Token::Curly(_, state) => state, + Token::Round(_, state) => state, + Token::Keyword(_, state) => state, + } +} + pub enum Ast { Variable(String, String), Function(String, String, String, String), @@ -22,7 +35,10 @@ pub enum Ast { pub fn get_token(v: String, t: u32, state: State) -> Token { match t { 1 => Token::Number(v, state), - 2 => Token::Identifier(v, state), + 2 => match v.as_str() { + "enum" | "struct" | "namespace" => Token::Keyword(v, state), + _ => Token::Identifier(v, state), + }, 3 => Token::Round(v, state), 4 => Token::Curly(v, state), _ => Token::Number(String::from(""), state), @@ -123,13 +139,11 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { t = 4; } x => { - root.problems.push(Problem { - problem_msg: format!( - "Invalid character '{}' at {}:{}, LexingError", - x, root.state.line, root.state.column - ), + root.problems.push(ProblemCap::Error(Problem { + problem_msg: format!("Invalid character '{}'", x,), problem_type: ProblemType::SyntaxError, - }); + state: root.state.clone(), + })); } } if (t != token_type || tval == '\n') && token_type != 0 { @@ -166,31 +180,34 @@ pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec 0 { let mut drain: usize = 1; match tokens.as_slice() { - [Token::Identifier(var_type, state0), Token::Identifier(var_name, state1), Token::Round(round, state2), Token::Curly(curly, state3), ..] => + [Token::Identifier(var_type, state0), Token::Identifier(var_name, _state1), Token::Round(round, _state2), Token::Curly(curly, _state3), ..] => { ast.push(Ast::Function( - var_type.clone(), - var_name.clone(), + if var_type == "void" { + "()".to_string() + } else { + var_type.clone() + }, + vars.new_func(var_name.clone(), state0.clone(), "".to_string()), round.clone(), curly.clone(), )); - drain += 1; - vars.new_func(var_name.clone(), state1.clone(), "".to_string()); + drain += 3; } - [Token::Identifier(var_type, state0), Token::Identifier(var_name, state1), ..] => { - ast.push(Ast::Variable(var_type.clone(), var_name.clone())); + [Token::Identifier(var_type, _state0), Token::Identifier(var_name, state1), ..] => { + ast.push(Ast::Variable( + var_type.clone(), + vars.new_var(var_name.clone(), state1.clone(), "".to_string()), + )); drain += 1; - vars.new_var(var_name.clone(), state1.clone(), "".to_string()); } x => { if !pcon.contains(&(root.state.line, root.state.column)) { - root.problems.push(Problem { - problem_msg: format!( - "Invalid placement '{:?}' at {}:{}, ParserError", - x, root.state.line, root.state.column - ), + root.problems.push(ProblemCap::Error(Problem { + problem_msg: format!("Invalid placement"), problem_type: ProblemType::SyntaxError, - }); + state: extract_state(x[0].clone()), + })); pcon.push((root.state.line, root.state.column)); } } diff --git a/src/transpiler.rs b/src/transpiler.rs index 9165c0a..f30f1e8 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,6 +1,6 @@ use crate::{ parser::{self, Ast}, - utils::Problem, + utils::ProblemCap, variable::Variables, }; use serde::{Deserialize, Serialize}; @@ -16,7 +16,7 @@ pub struct Transpiler { pub matched_vars: Variables, pub peek: String, // pub libmgr: LibManager, - pub problems: Vec, + pub problems: Vec, pub state: State, } @@ -33,9 +33,12 @@ impl Default for Transpiler { } impl Transpiler { - pub fn transpile(&mut self, code: String, indent: u32, vars: &mut Variables) -> String { + pub fn transpile(&mut self, code: String, indent: usize, vars: &mut Variables) -> String { let ast = parser::parse(code, vars, self); let mut res = String::new(); + if indent > 0 { + res += " ".repeat(indent * 2).as_str(); + } for a in ast { match a { Ast::Variable(var_type, var_name) => { @@ -43,13 +46,22 @@ impl Transpiler { } Ast::Function(var_type, var_name, round, curly) => { res += format!( - "fn {}({}) -> {} {}{}{}", - var_name, round, var_type, "{", curly, "}" + "fn {}({}) -> {} {}\n{}{}\n", + var_name, + round, + var_type, + "{", + self.transpile(curly, indent + 1, &mut vars.clone()), + "}" ) .as_str(); } } } + if indent > 0 { + res += "\n"; + res += " ".repeat((indent - 1) * 2).as_str(); + } res } } diff --git a/src/utils.rs b/src/utils.rs index 9ffdc53..d5bed48 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use crate::transpiler::State; + #[derive(Clone, Debug, Serialize, Deserialize)] pub enum ProblemType { VariableNotFound, @@ -8,9 +10,15 @@ pub enum ProblemType { SyntaxError, } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum ProblemCap { + Error(Problem), +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Problem { //pub code: u32, pub problem_type: ProblemType, pub problem_msg: String, + pub state: State, } diff --git a/src/variable.rs b/src/variable.rs index 91abf9f..da95dc9 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::{ transpiler::{State, Transpiler}, - utils::{Problem, ProblemType}, + utils::{Problem, ProblemCap, ProblemType}, }; #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] @@ -49,7 +49,8 @@ impl Variables { )]), } } - pub fn new_var(&mut self, name: String, state: State, desc: String) { + pub fn new_var(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); self.vars.insert( name, Variable { @@ -59,12 +60,14 @@ impl Variables { params: Variables { vars: HashMap::new(), }, - rname: generate_varname(), + rname: rname.clone(), }, ); + rname } - pub fn new_namespace(&mut self, name: String, state: State, desc: String) { + pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); self.vars.insert( name, Variable { @@ -74,12 +77,14 @@ impl Variables { params: Variables { vars: HashMap::new(), }, - rname: generate_varname(), + rname: rname.clone(), }, ); + rname } - pub fn new_struct(&mut self, name: String, state: State, desc: String) { + pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); self.vars.insert( name, Variable { @@ -89,11 +94,13 @@ impl Variables { params: Variables { vars: HashMap::new(), }, - rname: generate_varname(), + rname: rname.clone(), }, ); + rname } - pub fn new_enum(&mut self, name: String, state: State, desc: String) { + pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); self.vars.insert( name, Variable { @@ -103,9 +110,10 @@ impl Variables { params: Variables { vars: HashMap::new(), }, - rname: generate_varname(), + rname: rname.clone(), }, ); + rname } // pub fn new_keyword(&mut self, name: String, state: State, desc: String) { @@ -123,7 +131,8 @@ impl Variables { // ); // } - pub fn new_func(&mut self, name: String, state: State, desc: String) { + pub fn new_func(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); self.vars.insert( name, Variable { @@ -133,9 +142,10 @@ impl Variables { params: Variables { vars: HashMap::new(), }, - rname: generate_varname(), + rname: rname.clone(), }, ); + rname } pub fn add(&mut self, vtype: VariableType, name: String, state: State, desc: String) { self.vars.insert( @@ -151,14 +161,15 @@ impl Variables { }, ); } - pub fn get_var(&mut self, name: String, root: &mut Transpiler) -> String { + pub fn get_var(&mut self, name: String, root: &mut Transpiler, state: State) -> String { if let Some(x) = self.get_mut(name.clone()) { return x.rname.clone(); } else { - root.problems.push(Problem { + root.problems.push(ProblemCap::Error(Problem { problem_type: ProblemType::VariableNotFound, problem_msg: format!("Variable '{}' doesn't exist", &name), - }); + state: state, + })); return name; } }