From 910b638458dfc91158bb52412a0a6c46d41535e3 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Tue, 25 Jun 2024 21:13:46 +0200 Subject: [PATCH 01/21] rewrive-rev01 --- README.md | 3 + src/lexer.rs | 3 +- src/main.rs | 357 ++++++++++++++++++++++++++++++++-------------- src/parser.rs | 22 +++ src/transpiler.rs | 31 ++++ src/variable.rs | 15 ++ 6 files changed, 319 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index 89fe6c2..d2fc3bc 100644 --- a/README.md +++ b/README.md @@ -7,5 +7,8 @@

Wyst is a programing language that has similar syntax to C and transpiles to Rust

+# Re Write +We are re-writing the parser and transpiler due to the messy code that is very hard to expand + # Alpha We are on pure alpha. if you would like to contribute please open a new issue. diff --git a/src/lexer.rs b/src/lexer.rs index 8f98af3..76df225 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -85,7 +85,8 @@ const SYNTAX: [Node; 17] = [ Node { token_type: TokenType::Keyword, token_regex: Lazy::new(|| { - Regex::new(r"^(pub|mut|try|catch|return|fn|let|use|cb|struct|impl|in|as)\b").unwrap() + Regex::new(r"^(pub|mut|try|catch|return|fn|let|use|cb|enum|struct|impl|in|as)\b") + .unwrap() }), }, Node { diff --git a/src/main.rs b/src/main.rs index 494d6d3..a7b7897 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,120 +1,255 @@ -mod compile; -mod dllmgr; -mod file_writer; -mod lexer; -mod lsp; -mod lspcom; -mod parser; -mod transpiler; -mod variable; -use clap::Parser; -use std::{fs, path::Path}; -use transpiler::Transpiler; -use variable::{Variable, VariableType, Variables}; - -use crate::lsp::run_lsp_server; - -// Arguments for Wyst (short and long version) -#[derive(Parser)] -struct Args { - //#[clap(short, long)] - //rust: Option, - #[clap(short, long)] - compile: Option, - - #[clap(short, long)] - dll: Option, - - #[clap(long)] - stdio: bool, +#[derive(Debug, PartialEq, Clone)] +enum Token { + Plus, + Minus, + Star, + Slash, + Equals, + Semicolon, + LParen, + RParen, + Identifier(String), + Number(i64), + EOF, } -fn main() { - let args = Args::parse(); - match args.stdio { - true => { - run_lsp_server(); - } - false => { - match args.compile { - Some(ref exe_name) => { - let file_content = fs::read_to_string("main.wt").expect("Error reading file"); - if Path::new("build").exists() { - fs::remove_dir_all("build").expect("err rm build"); - } - fs::create_dir("build").expect("error making build"); - let mut trsp = Transpiler::default(); - let mut vars = Variables::new(); - let mut transpiled_code = trsp.transpile(file_content, 0, &mut vars); - transpiled_code += "\nfn main() {"; - transpiled_code += "std::process::exit("; - transpiled_code += vars.get_var("main".to_string(), &mut trsp).as_str(); - transpiled_code += "())}"; - for problem in &trsp.problems { - println!("{:?}: {}", problem.problem_type, problem.problem_msg) - } - if trsp.problems.len() > 0 { - return; - } - trsp.writer.write(); +fn tokenize(input: &str) -> Vec { + let mut tokens = Vec::new(); + let chars: Vec = input.chars().collect(); + let mut i = 0; - compile::write_to_rust_file(&transpiled_code, "build/main.rs") - .expect("Error writing to temporary Rust file"); - std::env::set_current_dir("build").expect("setDir err: "); - compile::compile_to_executable(exe_name) - .expect("Error compiling to executable"); - std::env::set_current_dir("..").expect("setDir0 err: "); - fs::rename(Path::new("build").join(exe_name).as_path(), exe_name) - .expect("RenameErrBuld: "); - fs::remove_dir_all("build").expect("err rm build"); - } - None => {} + while i < chars.len() { + match chars[i] { + ' ' | '\t' | '\n' | '\r' => i += 1, + '+' => { + tokens.push(Token::Plus); + i += 1; } - match args.dll { - Some(ref dll_path) => { - let file_content = fs::read_to_string("lib.wt").expect("Error reading file"); - if Path::new("build").exists() { - fs::remove_dir_all("build").expect("err rm build"); - } - fs::create_dir("build").expect("error making build"); - let mut trsp = Transpiler::default(); - let mut vars = Variables::new(); - let transpiled_code = trsp.transpile(file_content, 0, &mut vars); - for problem in trsp.problems { - println!("{}", problem.problem_msg) - } - trsp.writer.write(); - let mut dll_main = String::from( - "mod wslib;use wslib::*;\nfn call_fn(fn_name: &str, params: Vec)->i32{match fn_name {", - ); - for (name, var) in vars.vars.clone() { - if var.vtype != VariableType::Func { - continue; - } - let mut dparams = String::new(); - println!("{:?}", var.params.vars); - for i in 0..var.params.vars.len() { - dparams += format!("params.get({}).expect(\"Err_prms\"),", i).as_str(); - } - dll_main += format!( - "\"{}\" => {}return {}({dparams});{}", - name, "{", var.rname, "}" - ) - .as_str(); - } - dll_main += "}}\nfn main(){}"; - //dll_main = "fn main(){}".to_string(); - compile::write_to_rust_file(&transpiled_code, "build/wslib.rs") - .expect("Error writing to temporary Rust file"); - compile::write_to_rust_file(&dll_main, "build/main.rs") - .expect("Error writing to main dll"); - std::env::set_current_dir("build").expect("setDir err: "); - compile::compile_to_executable("run").expect("Error compiling to executable"); - dllmgr::write_dll(vars, "run".to_string(), dll_path.to_string()); - // fs::remove_dir_all("build").expect("err rm build"); + '-' => { + tokens.push(Token::Minus); + i += 1; + } + '*' => { + tokens.push(Token::Star); + i += 1; + } + '/' => { + tokens.push(Token::Slash); + i += 1; + } + '=' => { + tokens.push(Token::Equals); + i += 1; + } + ';' => { + tokens.push(Token::Semicolon); + i += 1; + } + '(' => { + tokens.push(Token::LParen); + i += 1; + } + ')' => { + tokens.push(Token::RParen); + i += 1; + } + '0'..='9' => { + let mut num = 0; + while i < chars.len() && chars[i].is_digit(10) { + num = num * 10 + chars[i].to_digit(10).unwrap() as i64; + i += 1; } - None => {} + tokens.push(Token::Number(num)); + } + 'a'..='z' | 'A'..='Z' => { + let mut id = String::new(); + while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_') { + id.push(chars[i]); + i += 1; + } + match id.as_str() { + _ => tokens.push(Token::Identifier(id)), + } + } + _ => panic!("Unexpected character: {}", chars[i]), + } + } + + tokens.push(Token::EOF); + tokens +} + +#[derive(Debug)] +enum ASTNode { + Number(i64), + Identifier(String), + BinaryOp(Box, Token, Box), + Assignment(String, Box), + Print(Box), + Let(String, Box), + Sequence(Vec), +} + +struct Parser { + tokens: Vec, + current_token: Token, + pos: usize, +} + +impl Parser { + fn new(tokens: Vec) -> Self { + Self { + tokens: tokens.clone(), + current_token: tokens[0].clone(), + pos: 0, + } + } + + fn eat(&mut self, token: Token) { + if self.current_token == token { + self.pos += 1; + self.current_token = self.tokens[self.pos].clone(); + } else { + panic!("Unexpected token: {:?}", self.current_token); + } + } + + fn factor(&mut self) -> ASTNode { + match self.current_token.clone() { + Token::Number(value) => { + self.eat(Token::Number(value)); + ASTNode::Number(value) + } + Token::Identifier(name) => { + self.eat(Token::Identifier(name.clone())); + ASTNode::Identifier(name) + } + Token::LParen => { + self.eat(Token::LParen); + let expr = self.expression(); + self.eat(Token::RParen); + expr + } + _ => panic!("Unexpected token: {:?}", self.current_token), + } + } + + fn term(&mut self) -> ASTNode { + let mut node = self.factor(); + + while self.current_token == Token::Star || self.current_token == Token::Slash { + let token = self.current_token.clone(); + self.eat(token.clone()); + node = ASTNode::BinaryOp(Box::new(node), token, Box::new(self.factor())); + } + + node + } + + fn expression(&mut self) -> ASTNode { + let mut node = self.term(); + + while self.current_token == Token::Plus || self.current_token == Token::Minus { + let token = self.current_token.clone(); + self.eat(token.clone()); + node = ASTNode::BinaryOp(Box::new(node), token, Box::new(self.term())); + } + + node + } + + fn statement(&mut self) -> ASTNode { + match self.current_token.clone() { + Token::Identifier(name) => { + self.eat(Token::Identifier(name.clone())); + self.eat(Token::Equals); + let expr = self.expression(); + self.eat(Token::Semicolon); + ASTNode::Assignment(name, Box::new(expr)) + } + _ => panic!("Unexpected token: {:?}", self.current_token), + } + } + + fn parse(&mut self) -> ASTNode { + let mut statements = Vec::new(); + + while self.current_token != Token::EOF { + statements.push(self.statement()); + } + + ASTNode::Sequence(statements) + } +} + +use std::collections::HashMap; + +struct Interpreter { + symbol_table: HashMap, +} + +impl Interpreter { + fn new() -> Self { + Self { + symbol_table: HashMap::new(), + } + } + + fn evaluate(&mut self, node: &ASTNode) -> i64 { + match node { + ASTNode::Number(value) => *value, + ASTNode::Identifier(name) => *self.symbol_table.get(name).expect("Undefined variable"), + ASTNode::BinaryOp(left, token, right) => { + let left_val = self.evaluate(left); + let right_val = self.evaluate(right); + match token { + Token::Plus => left_val + right_val, + Token::Minus => left_val - right_val, + Token::Star => left_val * right_val, + Token::Slash => left_val / right_val, + _ => panic!("Unexpected binary operator"), + } + } + ASTNode::Assignment(name, expr) => { + let value = self.evaluate(expr); + self.symbol_table.insert(name.clone(), value); + value + } + ASTNode::Let(name, expr) => { + let value = self.evaluate(expr); + self.symbol_table.insert(name.clone(), value); + value + } + ASTNode::Print(expr) => { + let value = self.evaluate(expr); + println!("{}", value); + value + } + ASTNode::Sequence(statements) => { + for statement in statements { + self.evaluate(statement); + } + 0 } } } } + +fn main() { + let input = " + let x = 5; + let y = x + 3; + print y; + x = y * 2; + print x; + "; + let tokens = tokenize(input); + println!("Tokens: {:?}", tokens); + + let mut parser = Parser::new(tokens); + let ast = parser.parse(); + println!("AST: {:?}", ast); + + let mut interpreter = Interpreter::new(); + interpreter.evaluate(&ast); +} diff --git a/src/parser.rs b/src/parser.rs index 2ab67dc..6583f59 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -26,6 +26,7 @@ pub enum AstType { Json, Impl, StaticExecution, + EnumDeceleration, Other, } @@ -119,6 +120,27 @@ impl Parser { ast_res.tokens.push(self.tokens[index + 1].clone()); ast_res.ast_type = AstType::Ref; self.index += 1; + } else if self.tokens.len() - index > 2 + && self.tokens[index].value == "enum" + && self.tokens[index + 1].token_type == TokenType::Identifier + && self.tokens[index + 2].token_type == TokenType::Curly + { + ast_res.tokens.push(self.tokens[index + 1].clone()); + ast_res.tokens.push(self.tokens[index + 2].clone()); + ast_res.ast_type = AstType::EnumDeceleration; + self.index += 2; + let mut desc = String::new(); + if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment { + desc = self.tokens[index - 1].value.clone() + } + self.variables.new_enum( + self.tokens[index + 1].clone().value, + LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column, + }, + desc, + ); } else if self.tokens.len() - index > 2 && self.tokens[index].value == "struct" && self.tokens[index + 1].token_type == TokenType::Identifier diff --git a/src/transpiler.rs b/src/transpiler.rs index 190ae76..f794f88 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -149,6 +149,37 @@ impl Transpiler { ) ) .as_str(); + } else if ast.ast_type == AstType::StructDeceleration { + if self.auto_pub { + result += "pub "; + } + let mut vars: Variables = variables.clone(); + let round = self.transpile_round(ast.tokens[1].value.clone(), &mut vars); + result += format!( + "enum {} {} {}", + ast.tokens[0].value, + "{\n", + round.trim_end() + ) + .replace( + "\n", + ("\n".to_string() + " ".repeat(((indent + 1) as usize) * 2).as_str()) + .as_str(), + ) + .as_str(); + result += "\n}\n"; + let vvars = variables.clone(); + if let Some(v) = variables.get_mut(ast.tokens[0].value.clone()) { + for (name, var) in vars.iter_mut() { + if !(vvars.vars.contains_key(name)) { + v.params.new_var( + name.to_string(), + LexerState { line: 0, column: 0 }, + var.desc.clone(), + ); + } + } + } } else if ast.ast_type == AstType::StructDeceleration { if self.auto_pub { result += "pub "; diff --git a/src/variable.rs b/src/variable.rs index 127d4e4..e48a660 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -16,6 +16,7 @@ pub enum VariableType { Keyword, Struct, Namespace, + Enum, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -93,6 +94,20 @@ impl Variables { }, ); } + pub fn new_enum(&mut self, name: String, state: LexerState, desc: String) { + self.vars.insert( + name, + Variable { + vtype: VariableType::Enum, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: generate_varname(), + }, + ); + } // pub fn new_keyword(&mut self, name: String, state: LexerState, desc: String) { // self.vars.insert( From 3d694d4931098d4851d5b1bbf22e52d8298f7997 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Fri, 28 Jun 2024 14:57:47 +0200 Subject: [PATCH 02/21] rewrite 1 --- src/compile.rs | 57 --- src/dllmgr.rs | 76 ---- src/file_writer.rs | 197 ---------- src/lexer.rs | 440 ---------------------- src/lsp.rs | 116 ------ src/lspcom.rs | 115 ------ src/main.rs | 259 +------------ src/parser.rs | 437 ++++------------------ src/transpiler.rs | 915 ++------------------------------------------- src/variable.rs | 23 +- 10 files changed, 109 insertions(+), 2526 deletions(-) delete mode 100644 src/compile.rs delete mode 100644 src/dllmgr.rs delete mode 100644 src/file_writer.rs delete mode 100644 src/lexer.rs delete mode 100644 src/lsp.rs delete mode 100644 src/lspcom.rs diff --git a/src/compile.rs b/src/compile.rs deleted file mode 100644 index 032a5f1..0000000 --- a/src/compile.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::fs; -use std::io::{Error, ErrorKind}; -use std::path::Path; -use std::process::Command; - -pub fn write_to_rust_file(transpiled_code: &str, file_name: &str) -> Result<(), Error> { - // Determine the file extension based on the provided file_name - let mut output_file = String::from(file_name); - if let Some(extension) = Path::new(file_name).extension() { - if let Some(ext_str) = extension.to_str() { - // Replace the existing extension with ".rs" if it's not already ".rs" - if ext_str != "rs" { - output_file.push_str(".rs"); - } - } - } else { - // If no extension is provided, append ".rs" to the file_name - output_file.push_str(".rs"); - } - - // Write the transpiled_code to the determined output file - fs::write(&output_file, transpiled_code)?; - - Ok(()) -} - -pub fn compile_to_executable(output_exe: &str) -> Result<(), Error> { - let output = Command::new("rustc") - .arg("main.rs".to_string()) - .arg("-o") - .arg(output_exe) - .output()?; - - // Check if compilation was successful - if output.status.success() { - println!("Compilation successful!"); - } else { - if let Some(code) = output.status.code() { - eprintln!("Compilation failed with error code: {}", code); - } - if !output.stdout.is_empty() { - eprintln!( - "Compiler output:\n{}", - String::from_utf8_lossy(&output.stdout) - ); - } - if !output.stderr.is_empty() { - eprintln!( - "Compiler errors:\n{}", - String::from_utf8_lossy(&output.stderr) - ); - } - return Err(Error::new(ErrorKind::Other, "Compilation failed")); - } - - Ok(()) -} diff --git a/src/dllmgr.rs b/src/dllmgr.rs deleted file mode 100644 index c81f064..0000000 --- a/src/dllmgr.rs +++ /dev/null @@ -1,76 +0,0 @@ -use regex::Regex; -use std::fs; -use std::io::Write; -use std::{ - fs::File, - io::{BufReader, Read}, -}; -use zip::{write::SimpleFileOptions, ZipArchive, ZipWriter}; - -use crate::variable::Variables; - -pub fn read_dll(dll_path: String) -> Variables { - let mut vars = Variables::new(); - let dll_file = File::open(dll_path).expect("err_dll_read"); - let dll_reader = BufReader::new(dll_file); - let mut dll_zip = ZipArchive::new(dll_reader).expect("err_archive"); - for i in 0..dll_zip.len() { - let mut buf = Vec::new(); - let mut file = dll_zip.by_index(i).expect("err_dll_idx"); - let filename = file.name(); - if filename == "map.json" && file.is_file() { - file.read_to_end(&mut buf).expect("err_read_zip_file"); - println!( - "Filename: {}\nFileContents: {}", - file.name(), - String::from_utf8_lossy(&buf) - ); - } - } - vars -} - -pub fn write_dll(vars: Variables, exe_path: String, dll_path: String) { - let dll_file = File::create(&dll_path).expect("Err_DllCREATE"); - let mut dll = ZipWriter::new(dll_file); - dll.start_file("run", SimpleFileOptions::default()) - .expect("ERR_STARTFILE_RUN"); - let buf_vec = fs::read(exe_path).expect("ERR_READ_EXE"); - let buf_u8: &[u8] = buf_vec.as_slice(); - dll.write_all(buf_u8).expect("ERR_DLL_EXEWRITE"); - dll.start_file("map.json", SimpleFileOptions::default()) - .expect("ERR_STARTFILE_MAP"); - let json_data = serde_json::to_string(&vars.vars).expect("ERR_MAP_JSON"); - dll.write_all(json_data.as_bytes()) - .expect("ERR_DLL_JSONWRITE"); - println!("{:?}", serde_json::to_string(&vars.vars)); -} - -pub struct HeaderConfig { - pub file_path: String, - pub map_path: String, -} - -impl HeaderConfig { - // Function to parse the input string - pub fn new(input: String) -> Option { - let re = Regex::new(r#"FILE_PATH\s*=\s*"([^"]*)""#).expect("ERR_REGEX_HDR"); - let re1 = Regex::new(r#"MAP_PATH\s*=\s*"([^"]*)""#).expect("ERR_REGEX_HDR1"); - let mut fp: String = String::new(); - let mut mp: String = String::new(); - if let Some(caps) = re.captures(input.as_str()) { - fp = caps.get(1)?.as_str().to_string(); - } else { - return None; - } - if let Some(caps) = re1.captures(input.as_str()) { - mp = caps.get(1)?.as_str().to_string(); - } else { - return None; - } - return Some(HeaderConfig { - file_path: fp, - map_path: mp, - }); - } -} diff --git a/src/file_writer.rs b/src/file_writer.rs deleted file mode 100644 index 6559a5b..0000000 --- a/src/file_writer.rs +++ /dev/null @@ -1,197 +0,0 @@ -use std::{collections::HashMap, fs, path::Path}; - -use dirs::home_dir; - -use crate::{ - dllmgr::{read_dll, HeaderConfig}, - lspcom::{Problem, ProblemType}, - transpiler::Transpiler, - variable::{Variable, Variables}, -}; - -fn join_directories(dir1: &str, dir2: &str) -> String { - let mut main_seperator = '/'; - if cfg!(windows) { - main_seperator = '\\'; - } - let mut result = dir1.to_string(); - - if !result.ends_with(main_seperator) { - result.push(main_seperator); - } - - let dir2_trimmed = if dir2.starts_with(main_seperator) { - &dir2[1..] - } else { - dir2 - }; - - result.push_str(dir2_trimmed); - result -} - -#[derive(Clone, Debug)] -pub struct Module { - pub file_ws: String, - pub file_rs: String, - pub mod_rs: String, - pub _code: String, - pub code_rs: String, -} - -#[derive(Clone, Debug)] -pub struct FileWriter { - pub files: Vec, - pub mod_num: u32, - pub _projpath: String, -} - -impl FileWriter { - pub fn new(_projpath: String) -> FileWriter { - FileWriter { - files: Vec::new(), - mod_num: 0, - _projpath, - } - } - pub fn write(&mut self) { - for module in &self.files { - fs::write(&module.file_rs, &module.code_rs).expect("WriteErr: can't write to file"); - } - } - /*Checks if a path has already been imported*/ - pub fn check(&mut self, filepath: String) -> Option<&Module> { - for module in &self.files { - if filepath == module.file_ws { - return Some(module); - } - } - return None; - } - pub fn expand(&mut self, writer: FileWriter) { - for module in writer.files { - self.files.push(module); - } - } - pub fn add( - &mut self, - filepath: String, - variables: &mut Variables, - global: bool, - ) -> Result { - let mut filepath = filepath; - if global { - let homedir_ = home_dir().expect("Err_HOMEDIR_NOTFOUND"); - let homedir = homedir_.to_str().expect("ERR_HOMEDIR_STR"); - let gdir = join_directories(&homedir, &join_directories("wyst", "lib")); - let lpath = join_directories("lib", &filepath); - let gpath = join_directories(&gdir, &filepath); - if Path::new(&lpath).exists() { - filepath = lpath; - } else if Path::new(&gpath).exists() { - filepath = gpath; - } else { - return Err(Problem { - problem_type: ProblemType::FileNotFound, - problem_msg: format!("failed to import {}: Not found", filepath), - }); - } - } - if !Path::new(&filepath).exists() { - return Err(Problem { - problem_type: ProblemType::FileNotFound, - problem_msg: format!("failed to import {}: Not found", filepath), - }); - } - if let Some(module) = self.check(filepath.clone()) { - return Ok(module.mod_rs.clone()); - } - match filepath.rsplit_once('.').expect("Err_SPLIT").1 { - "wt" => { - let mut trsp = Transpiler { - writer: self.clone(), - ..Default::default() - }; - let mut vars = Variables::new(); - let code = fs::read_to_string(filepath.clone()).expect("failed to read"); - let code_rs = trsp.transpile(code.clone(), 0, &mut vars); - let module = Module { - file_ws: filepath, - mod_rs: format!("mod_{}", self.mod_num), - file_rs: format!("build/mod_{}.rs", self.mod_num), - _code: code, - code_rs, - }; - self.files.push(module.clone()); - self.expand(trsp.writer); - variables.expand(vars); - self.mod_num += 1; - Ok(module.mod_rs) - } - "h" => { - let hdr_code = fs::read_to_string(filepath.clone()).expect("failed to read"); - let mut parent = String::new(); - match Path::new(&filepath).parent() { - Some(p) => parent = format!("{}", p.display()), - None => {} - }; - match HeaderConfig::new(hdr_code) { - Some(hdrcnf) => { - let file_path = Path::new(&parent).join(hdrcnf.file_path.clone()); - let map_path = Path::new(&parent).join(hdrcnf.map_path.clone()); - match fs::read_to_string(file_path) { - Ok(code) => match fs::read_to_string(map_path) { - Ok(map_string) => { - let map: HashMap = - serde_json::from_str(&map_string) - .expect(format!("err_hdr.map: {}", filepath).as_str()); - let vars = Variables { vars: map }; - let module = Module { - file_ws: filepath, - mod_rs: format!("mod_{}", self.mod_num), - file_rs: format!("build/mod_{}.rs", self.mod_num), - _code: code.clone(), - code_rs: code, - }; - self.files.push(module.clone()); - variables.expand(vars); - Ok(module.mod_rs) - } - Err(_) => Err(Problem { - problem_type: ProblemType::FileNotFound, - problem_msg: format!( - "failed to import {}: Not found", - hdrcnf.map_path - ), - }), - }, - Err(_) => Err(Problem { - problem_type: ProblemType::FileNotFound, - problem_msg: format!( - "failed to import {}: Not found", - hdrcnf.file_path - ), - }), - } - } - None => Err(Problem { - problem_type: ProblemType::HeaderSyntaxError, - problem_msg: format!("failed to deserialize"), - }), - } - } - "dll" => { - read_dll(filepath.clone()); - return Ok("xyz".to_string()); - } - "rs" => Err(Problem { - problem_type: ProblemType::FileNotFound, - problem_msg: format!("failed to import {}: Not found", filepath), - }), - _ => Err(Problem { - problem_type: ProblemType::FileNotFound, - problem_msg: format!("failed to import {}: Not found", filepath), - }), - } - } -} diff --git a/src/lexer.rs b/src/lexer.rs deleted file mode 100644 index 76df225..0000000 --- a/src/lexer.rs +++ /dev/null @@ -1,440 +0,0 @@ -use once_cell::sync::Lazy; -use regex::Regex; -use serde::{Deserialize, Serialize}; -use std::fmt; -#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] -pub struct LexerState { - pub line: usize, - pub column: usize, -} - -// Define token types -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum TokenType { - Keyword, - Keyword1, - Keyword2, - Newline, - Whitespace, - Number, - Identifier, - Ptr, - Operator, - SecondOperator, - Semicolon, - Round, - Curly, - Square, - Angle, - Include, - String, - Comment, - StaticExecution, - // EOF, -} - -#[derive(Clone)] -pub struct Token { - pub token_type: TokenType, - pub value: String, - pub line: usize, - pub column: usize, -} - -impl fmt::Debug for Token { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(TokenType: {:?}, TokenValue: {}, Line: {}, Column {})", - self.token_type, - self.value.replace("\n", "\\n"), - self.line, - self.column - ) - } -} - -impl fmt::Display for Token { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "(\x1b[33mTokenType:\x1b[0m \x1b[35m{:?}\x1b[0m, \x1b[33mTokenValue:\x1b[0m \x1b[32m\"{}\"\x1b[0m, \x1b[33mLine:\x1b[0m \x1b[36m{}\x1b[0m, \x1b[33mColumn:\x1b[0m \x1b[36m{}\x1b[0m)", self.token_type, self.value.replace("\n", "\\n"), self.line, self.column) - } -} - -pub struct Node { - token_type: TokenType, - token_regex: Lazy, -} - -const SYNTAX: [Node; 17] = [ - Node { - token_type: TokenType::Semicolon, - token_regex: Lazy::new(|| Regex::new(r"^\;").unwrap()), - }, - Node { - token_type: TokenType::SecondOperator, - token_regex: Lazy::new(|| Regex::new(r"^,").unwrap()), - }, - Node { - token_type: TokenType::String, - token_regex: Lazy::new(|| Regex::new("^\"").unwrap()), - }, - Node { - token_type: TokenType::Whitespace, - token_regex: Lazy::new(|| Regex::new(r"^\s+").unwrap()), - }, - Node { - token_type: TokenType::Keyword, - token_regex: Lazy::new(|| { - Regex::new(r"^(pub|mut|try|catch|return|fn|let|use|cb|enum|struct|impl|in|as)\b") - .unwrap() - }), - }, - Node { - token_type: TokenType::Keyword1, - token_regex: Lazy::new(|| { - Regex::new(r"^(impl|namespace|if|for|while|else *if)\b").unwrap() - }), - }, - Node { - token_type: TokenType::Keyword2, - token_regex: Lazy::new(|| Regex::new(r"^(else)\b").unwrap()), - }, - Node { - token_type: TokenType::Identifier, - token_regex: Lazy::new(|| Regex::new(r"^[.:_a-zA-Z][a-zA-Z0-9_.:]*").unwrap()), - }, - Node { - token_type: TokenType::Number, - token_regex: Lazy::new(|| Regex::new(r"^\d+").unwrap()), - }, - Node { - token_type: TokenType::Ptr, - token_regex: Lazy::new(|| Regex::new(r"^->").unwrap()), - }, - Node { - token_type: TokenType::Operator, - token_regex: Lazy::new(|| Regex::new(r"^[\&\&|\-|\+|\*|\=|\!|\&|\:]").unwrap()), - }, - Node { - token_type: TokenType::Round, - token_regex: Lazy::new(|| Regex::new(r"^[\(|\)]").unwrap()), - }, - Node { - token_type: TokenType::Curly, - token_regex: Lazy::new(|| Regex::new(r"^[\{|\}]").unwrap()), - }, - Node { - token_type: TokenType::Square, - token_regex: Lazy::new(|| Regex::new(r"^[\[|\]]").unwrap()), - }, - Node { - token_type: TokenType::Include, - token_regex: Lazy::new(|| Regex::new(r"^#include *<(.*?)>").unwrap()), - }, - Node { - token_type: TokenType::Include, - token_regex: Lazy::new(|| Regex::new(r#"^#include *"(.*?)""#).unwrap()), - }, - Node { - token_type: TokenType::StaticExecution, - token_regex: Lazy::new(|| Regex::new(r"^#").unwrap()), - }, -]; - -fn get_first_char(value: &str) -> String { - value.chars().next().unwrap().to_string() -} - -pub fn lex( - mut code: &str, - use_whitespace: bool, - state: LexerState, -) -> Result, (LexerState, Vec)> { - let mut state = state; - let mut tokens: Vec = Vec::new(); - let mut brstr: String = String::new(); - let mut br_state: LexerState = LexerState { line: 0, column: 0 }; - let mut brtp: Vec = Vec::new(); - while !code.is_empty() { - let mut is_match = false; - let fch = get_first_char(code); - let brln = brtp.len(); - match fch.as_str() { - "/" => { - brstr += "/"; - code = code.strip_prefix(fch.as_str()).expect(""); - if brln == 0 { - if code.len() > 0 { - let sch = get_first_char(code); - if sch == "/" { - code = code.strip_prefix(sch.as_str()).expect(""); - brstr += &sch; - brtp.push(4); - if brln > 0 { - brstr += fch.as_str(); - } else { - br_state.line = state.line; - br_state.column = state.column; - } - } else if sch == "*" { - code = code.strip_prefix(sch.as_str()).expect(""); - brstr += &sch; - brtp.push(5); - if brln > 0 { - brstr += fch.as_str(); - } else { - br_state.line = state.line; - br_state.column = state.column; - } - } else if brln == 0 { - tokens.push(Token { - token_type: TokenType::Operator, - value: "/".to_string(), - column: state.column, - line: state.line, - }); - } - } else if brln == 0 { - tokens.push(Token { - token_type: TokenType::Operator, - value: "*".to_string(), - column: state.column, - line: state.line, - }); - } - } - } - "\"" => { - brstr += "\""; - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 && brtp[brln - 1] == 0 { - brtp.pop(); - tokens.push(Token { - token_type: TokenType::String, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } else if brln == 0 { - brtp.push(0); - br_state.line = state.line; - br_state.column = state.column; - } - } - "'" => { - brstr += "'"; - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 && brtp[brln - 1] == 1 { - brtp.pop(); - tokens.push(Token { - token_type: TokenType::String, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } else if brln == 0 { - brtp.push(1); - br_state.line = state.line; - br_state.column = state.column; - } - } - "(" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 { - brstr += fch.as_str(); - } else { - br_state.line = state.line; - br_state.column = state.column; - } - brtp.push(2); - } - ")" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 && brtp[brln - 1] == 2 { - brtp.pop(); - if brln == 1 { - tokens.push(Token { - token_type: TokenType::Round, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } else { - brstr += fch.as_str(); - } - } else { - brstr += fch.as_str(); - } - } - "{" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 { - brstr += fch.as_str(); - } else { - br_state.line = state.line; - br_state.column = state.column; - } - brtp.push(3); - } - "}" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 && brtp[brln - 1] == 3 { - brtp.pop(); - if brln == 1 { - tokens.push(Token { - token_type: TokenType::Curly, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } else { - brstr += fch.as_str(); - } - } else { - brstr += fch.as_str(); - } - } - "[" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 { - brstr += fch.as_str(); - } else { - br_state.line = state.line; - br_state.column = state.column; - } - brtp.push(3); - } - "]" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 && brtp[brln - 1] == 3 { - brtp.pop(); - if brln == 1 { - tokens.push(Token { - token_type: TokenType::Square, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } else { - brstr += fch.as_str(); - } - } else { - brstr += fch.as_str(); - } - } - "<" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 { - brstr += fch.as_str(); - } else { - br_state.line = state.line; - br_state.column = state.column; - } - brtp.push(6); - } - ">" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 && brtp[brln - 1] == 6 { - brtp.pop(); - if brln == 1 { - tokens.push(Token { - token_type: TokenType::Angle, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } else { - brstr += fch.as_str(); - } - } else { - brstr += fch.as_str(); - } - } - "\\" => { - brstr += "\\"; - code = code.strip_prefix(fch.as_str()).expect(""); - if code.len() > 0 { - let sch = get_first_char(code); - code = code.strip_prefix(sch.as_str()).expect(""); - brstr += &sch; - } - } - "\n" => { - code = code.strip_prefix(fch.as_str()).expect(""); - if brln > 0 { - brstr += "\n"; - } - if brln == 1 && brtp[0] == 4 { - brtp.pop(); - tokens.push(Token { - token_type: TokenType::Comment, - value: brstr.clone(), - column: br_state.column, - line: br_state.line, - }); - brstr = String::new(); - } - state.line += 1; - state.column = 0; - } - _ => { - if brln > 0 { - code = code.strip_prefix(fch.as_str()).expect(""); - brstr += fch.as_str(); - } else { - for s in &SYNTAX { - if let Some(caps) = s.token_regex.captures(code) { - is_match = true; - code = code.strip_prefix(&caps[0]).unwrap_or(code); - if (!use_whitespace && s.token_type != TokenType::Whitespace) - || use_whitespace - { - let cap = caps[0].to_string(); - match cap.as_str() { - "int" => { - tokens.push(Token { - token_type: s.token_type, - value: "i32".to_string(), - line: state.line, - column: state.column, - }); - } - "float" => { - tokens.push(Token { - token_type: s.token_type, - value: "f32".to_string(), - line: state.line, - column: state.column, - }); - } - _ => { - tokens.push(Token { - token_type: s.token_type, - value: cap, - line: state.line, - column: state.column, - }); - } - } - } - state.column += caps[0].len(); - } else { - continue; - }; - break; - } - if !is_match { - return Err((state, tokens)); - } - } - } - } - } - Ok(tokens) -} diff --git a/src/lsp.rs b/src/lsp.rs deleted file mode 100644 index af8dead..0000000 --- a/src/lsp.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::{ - lspcom::{get_completion, get_items, request_methods, LspServer, TextDocumentChangeParams}, - variable::Variables, -}; -use lsp_types::*; -use once_cell::sync::Lazy; -use regex::Regex; -use serde_json::{self, json, Value}; -use std::{ - collections::HashMap, - fs, - io::{stdin, stdout, Read, Write}, - path::Path, -}; - -#[derive(Debug)] -pub struct Server { - documents: HashMap, -} - -impl LspServer for Server { - fn initialize(&mut self) -> InitializeResult { - InitializeResult { - capabilities: ServerCapabilities { - completion_provider: Some(CompletionOptions { - trigger_characters: Some(vec![".".to_string()]), - ..Default::default() - }), - ..Default::default() - }, - ..Default::default() - } - } - fn completion(&mut self, params: CompletionParams) -> CompletionResponse { - let text = self - .documents - .get(params.text_document_position.text_document.uri.as_str()) - .expect("err_textdoc"); - let items: Variables = get_completion( - text.clone(), - params.text_document_position.position.line as usize + 1, - params.text_document_position.position.character as usize, - ); - CompletionResponse::Array(get_items(items, "".to_string())) - } - fn did_change(&mut self, params: TextDocumentChangeParams) { - self.documents.insert(params.uri, params.text); - } -} - -pub fn run_lsp_server() { - if Path::new("/home/leo/work/wyst/log.txt").exists() { - fs::remove_file("/home/leo/work/wyst/log.txt").unwrap(); - } - let clpattern = Lazy::new(|| Regex::new(r"^Content-Length: (\d+)").unwrap()); - let mut reader = stdin(); - let mut server = Server { - documents: HashMap::new(), - }; - loop { - let mut input = String::new(); - if reader.read_line(&mut input).is_err() { - continue; - } - let stdout = stdout(); - let mut handle = stdout.lock(); - - if let Some(caps) = clpattern.captures(&input) { - let content_len = caps[1].parse::().unwrap() + 2; - let mut buf = vec![0u8; content_len]; - if reader.read_exact(&mut buf).is_err() { - continue; - } - let json_string = String::from_utf8(buf).expect("Our bytes should be valid utf8"); - let client_json: Value = serde_json::from_str(&json_string).expect("err_json"); - let response = match client_json["method"].as_str().unwrap() { - request_methods::INITIALIZE => { - serde_json::to_string(&json!({ - "jsonrpc": "2.0", - "id": client_json["id"].as_u64().unwrap(), - "result": server.initialize() - })) - .unwrap() - } - request_methods::COMPLETION => serde_json::to_string(&json!({ - "jsonrpc": "2.0", - "id": client_json["id"].as_u64().unwrap(), - "result": server.completion(serde_json::from_value(serde_json::to_value(client_json["params"].as_object()).expect("err_pars2")).unwrap()) - })) - .unwrap(), - request_methods::DID_CHANGE =>{ - server.did_change(serde_json::from_value(serde_json::to_value(client_json["params"].as_object()).expect("err_pars2")).expect("err_pars3")); - "None".to_string()}, - request_methods::INITIALIZED => "None".to_string(), - request_methods::SHUTDOWN => { - return; - } - _ => { - continue; - } - }; - if response != "None" { - let header = format!( - "Content-Length: {}\r\n\r\n{}", - response.trim().len(), - response.trim() - ); - handle - .write_all(header.as_bytes()) - .expect("err_write_stdin"); - handle.flush().expect("err_flush_stdin"); - } - } else { - } - } -} diff --git a/src/lspcom.rs b/src/lspcom.rs deleted file mode 100644 index 1ac6a7c..0000000 --- a/src/lspcom.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::{ - transpiler::Transpiler, - variable::{VariableType, Variables}, -}; -use lsp_types::{ - CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, InitializeResult, -}; -use rand::{thread_rng, Rng}; -use serde::{Deserialize, Serialize}; - -pub fn place_at(input: String, in2: String, line_goal: usize, column_goal: usize) -> String { - let mut line: usize = 1; - let mut column: usize = 0; - let mut out = String::new(); - for c in input.chars() { - out += c.to_string().as_str(); - column += 1; - if c == '\n' { - line += 1; - column = 0; - } else if line == line_goal && column == column_goal { - out += in2.as_str(); - column += 1 - } - } - out -} - -pub fn get_completion(input: String, line: usize, column: usize) -> Variables { - let rand_id: u32 = thread_rng().gen(); - let rand_id: String = rand_id.to_string(); - let mut transpiler = Transpiler { - peek: rand_id.clone(), - ..Default::default() - }; - let mut vars = Variables::new(); - transpiler.transpile(place_at(input, rand_id, line, column), 0, &mut vars); - transpiler.matched_vars -} - -pub mod request_methods { - pub const INITIALIZE: &str = "initialize"; - pub const COMPLETION: &str = "textDocument/completion"; - pub const INITIALIZED: &str = "initialized"; - pub const SHUTDOWN: &str = "shutdown"; - pub const DID_CHANGE: &str = "textDocument/didChange"; -} - -pub trait LspServer { - fn did_change(&mut self, _params: TextDocumentChangeParams) {} - fn completion(&mut self, _params: CompletionParams) -> CompletionResponse { - CompletionResponse::Array(vec![]) - } - fn initialize(&mut self) -> InitializeResult { - InitializeResult::default() - } -} - -#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] -pub struct TextDocumentChangeParams { - pub uri: String, - pub text: String, -} - -pub fn get_items(mut items: Variables, lname: String) -> Vec { - let mut completion_items: Vec = Vec::new(); - for (name, var) in items.iter_mut() { - let mut item = CompletionItem::new_simple(lname.clone() + &name, var.desc.clone()); - if var.vtype != VariableType::Func { - completion_items.extend( - get_items(var.params.clone(), name.to_owned() + "::") - .iter() - .cloned(), - ) - } else { - // item.documentation = Some(Documentation::MarkupContent(MarkupContent { - // kind: MarkupKind::Markdown, - // value: "Markup".to_string(), - // })); - } - match var.vtype { - VariableType::Func => { - item.kind = Some(CompletionItemKind::FUNCTION); - } - VariableType::Var => { - item.kind = Some(CompletionItemKind::VARIABLE); - } - VariableType::Keyword => { - item.kind = Some(CompletionItemKind::KEYWORD); - } - VariableType::Struct => { - item.kind = Some(CompletionItemKind::STRUCT); - } - VariableType::Namespace => { - item.kind = Some(CompletionItemKind::MODULE); - } - } - completion_items.push(item); - } - completion_items -} - -#[derive(Clone, Debug)] -pub enum ProblemType { - VariableNotFound, - FileNotFound, - HeaderSyntaxError, -} - -#[derive(Clone, Debug)] -pub struct Problem { - //pub code: u32, - pub problem_type: ProblemType, - pub problem_msg: String, -} diff --git a/src/main.rs b/src/main.rs index a7b7897..f525f77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,255 +1,12 @@ -#[derive(Debug, PartialEq, Clone)] -enum Token { - Plus, - Minus, - Star, - Slash, - Equals, - Semicolon, - LParen, - RParen, - Identifier(String), - Number(i64), - EOF, -} +use variable::Variables; -fn tokenize(input: &str) -> Vec { - let mut tokens = Vec::new(); - let chars: Vec = input.chars().collect(); - let mut i = 0; - - while i < chars.len() { - match chars[i] { - ' ' | '\t' | '\n' | '\r' => i += 1, - '+' => { - tokens.push(Token::Plus); - i += 1; - } - '-' => { - tokens.push(Token::Minus); - i += 1; - } - '*' => { - tokens.push(Token::Star); - i += 1; - } - '/' => { - tokens.push(Token::Slash); - i += 1; - } - '=' => { - tokens.push(Token::Equals); - i += 1; - } - ';' => { - tokens.push(Token::Semicolon); - i += 1; - } - '(' => { - tokens.push(Token::LParen); - i += 1; - } - ')' => { - tokens.push(Token::RParen); - i += 1; - } - '0'..='9' => { - let mut num = 0; - while i < chars.len() && chars[i].is_digit(10) { - num = num * 10 + chars[i].to_digit(10).unwrap() as i64; - i += 1; - } - tokens.push(Token::Number(num)); - } - 'a'..='z' | 'A'..='Z' => { - let mut id = String::new(); - while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_') { - id.push(chars[i]); - i += 1; - } - match id.as_str() { - _ => tokens.push(Token::Identifier(id)), - } - } - _ => panic!("Unexpected character: {}", chars[i]), - } - } - - tokens.push(Token::EOF); - tokens -} - -#[derive(Debug)] -enum ASTNode { - Number(i64), - Identifier(String), - BinaryOp(Box, Token, Box), - Assignment(String, Box), - Print(Box), - Let(String, Box), - Sequence(Vec), -} - -struct Parser { - tokens: Vec, - current_token: Token, - pos: usize, -} - -impl Parser { - fn new(tokens: Vec) -> Self { - Self { - tokens: tokens.clone(), - current_token: tokens[0].clone(), - pos: 0, - } - } - - fn eat(&mut self, token: Token) { - if self.current_token == token { - self.pos += 1; - self.current_token = self.tokens[self.pos].clone(); - } else { - panic!("Unexpected token: {:?}", self.current_token); - } - } - - fn factor(&mut self) -> ASTNode { - match self.current_token.clone() { - Token::Number(value) => { - self.eat(Token::Number(value)); - ASTNode::Number(value) - } - Token::Identifier(name) => { - self.eat(Token::Identifier(name.clone())); - ASTNode::Identifier(name) - } - Token::LParen => { - self.eat(Token::LParen); - let expr = self.expression(); - self.eat(Token::RParen); - expr - } - _ => panic!("Unexpected token: {:?}", self.current_token), - } - } - - fn term(&mut self) -> ASTNode { - let mut node = self.factor(); - - while self.current_token == Token::Star || self.current_token == Token::Slash { - let token = self.current_token.clone(); - self.eat(token.clone()); - node = ASTNode::BinaryOp(Box::new(node), token, Box::new(self.factor())); - } - - node - } - - fn expression(&mut self) -> ASTNode { - let mut node = self.term(); - - while self.current_token == Token::Plus || self.current_token == Token::Minus { - let token = self.current_token.clone(); - self.eat(token.clone()); - node = ASTNode::BinaryOp(Box::new(node), token, Box::new(self.term())); - } - - node - } - - fn statement(&mut self) -> ASTNode { - match self.current_token.clone() { - Token::Identifier(name) => { - self.eat(Token::Identifier(name.clone())); - self.eat(Token::Equals); - let expr = self.expression(); - self.eat(Token::Semicolon); - ASTNode::Assignment(name, Box::new(expr)) - } - _ => panic!("Unexpected token: {:?}", self.current_token), - } - } - - fn parse(&mut self) -> ASTNode { - let mut statements = Vec::new(); - - while self.current_token != Token::EOF { - statements.push(self.statement()); - } - - ASTNode::Sequence(statements) - } -} - -use std::collections::HashMap; - -struct Interpreter { - symbol_table: HashMap, -} - -impl Interpreter { - fn new() -> Self { - Self { - symbol_table: HashMap::new(), - } - } - - fn evaluate(&mut self, node: &ASTNode) -> i64 { - match node { - ASTNode::Number(value) => *value, - ASTNode::Identifier(name) => *self.symbol_table.get(name).expect("Undefined variable"), - ASTNode::BinaryOp(left, token, right) => { - let left_val = self.evaluate(left); - let right_val = self.evaluate(right); - match token { - Token::Plus => left_val + right_val, - Token::Minus => left_val - right_val, - Token::Star => left_val * right_val, - Token::Slash => left_val / right_val, - _ => panic!("Unexpected binary operator"), - } - } - ASTNode::Assignment(name, expr) => { - let value = self.evaluate(expr); - self.symbol_table.insert(name.clone(), value); - value - } - ASTNode::Let(name, expr) => { - let value = self.evaluate(expr); - self.symbol_table.insert(name.clone(), value); - value - } - ASTNode::Print(expr) => { - let value = self.evaluate(expr); - println!("{}", value); - value - } - ASTNode::Sequence(statements) => { - for statement in statements { - self.evaluate(statement); - } - 0 - } - } - } -} +mod parser; +mod transpiler; +mod utils; +mod variable; fn main() { - let input = " - let x = 5; - let y = x + 3; - print y; - x = y * 2; - print x; - "; - let tokens = tokenize(input); - println!("Tokens: {:?}", tokens); - - let mut parser = Parser::new(tokens); - let ast = parser.parse(); - println!("AST: {:?}", ast); - - let mut interpreter = Interpreter::new(); - interpreter.evaluate(&ast); + let mut vars = Variables::new(); + let out = transpiler::Transpiler::default().transpile(r#"int x"#.to_string(), 0, &mut vars); + println!("{out}"); } diff --git a/src/parser.rs b/src/parser.rs index 6583f59..e5ecb21 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,387 +1,80 @@ -use crate::{ - lexer::{LexerState, Token, TokenType}, - variable::Variables, -}; -use once_cell::sync::Lazy; -use regex::Regex; -use std::fmt; +use crate::{transpiler::State, variable::Variables}; -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum AstType { - Ref, - FunctionDeceleration, - StructDeceleration, - StructCall, - StructVar, - VoidFunctionDeceleration, - Namespace, - VariableDeceleration, - PointerDeceleration, - MutVariableDeceleration, - State3, - State2, - Include, - IncludeLocal, - CodeBlock, - Json, - Impl, - StaticExecution, - EnumDeceleration, - Other, +#[derive(Clone, Debug)] +pub enum Token { + Number(String), + Identifier(String), + // Curly(String), + // Round(String), + // Square(String), +} +pub enum Ast { + Variable(String, String), } -pub fn is_decl(ast: &Ast) -> bool { - ast.ast_type == AstType::FunctionDeceleration - || ast.ast_type == AstType::VoidFunctionDeceleration - || ast.ast_type == AstType::Namespace - || ast.ast_type == AstType::VariableDeceleration - || ast.ast_type == AstType::PointerDeceleration - || ast.ast_type == AstType::MutVariableDeceleration - || ast.ast_type == AstType::StructDeceleration -} - -pub struct Ast { - pub tokens: Vec, - pub ast_type: AstType, -} - -impl fmt::Display for Ast { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "\x1b[36m{:?}:\x1b[0m [\n", self.ast_type)?; - for (i, token) in self.tokens.iter().enumerate() { - if i < self.tokens.len() - 1 { - write!(f, " {},\n", token)?; - } else { - write!(f, " {}\n", token)?; - } - } - write!(f, "]") +pub fn get_token(v: String, t: u32) -> Token { + match t { + 1 => Token::Number(v), + 2 => Token::Identifier(v), + _ => Token::Number(String::from("")), } } -impl fmt::Debug for Ast { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}: [\n", self.ast_type)?; - for (i, token) in self.tokens.iter().enumerate() { - if i < self.tokens.len() - 1 { - write!(f, " {:?},\n", token)?; - } else { - write!(f, " {:?}\n", token)?; +pub fn tokenize(code: String) -> Vec { + let mut code = code; + let mut tokens: Vec = Vec::new(); + let mut token_value: String = String::new(); + let mut token_type: u32 = 0; + while !code.is_empty() { + if let Some(c) = code.chars().next() { + code.remove(0); + let mut tval: char = c; + let mut t: u32 = 0; + match c { + '0'..='9' => { + if token_type == 2 { + t = 2; + } else { + t = 1; + } + } + 'a'..='z' | 'A'..='Z' => { + t = 2; + } + '\t' | ' ' => tval = ' ', + _ => {} + } + if t != token_type && token_type != 0 || tval == ' ' { + tokens.push(get_token(token_value.clone(), token_type)); + token_type = 0; + token_value = String::new(); + } + if tval != ' ' { + token_type = t; + token_value += tval.to_string().as_str(); } } - write!(f, "]") } + if token_type != 0 { + tokens.push(get_token(token_value.clone(), token_type)); + } + tokens } -pub struct Parser { - pub tokens: Vec, - pub index: u32, - pub include_regex: Lazy, - pub include_regex_local: Lazy, - pub variables: Variables, - pub json: bool, -} - -impl Parser { - pub fn new(tokens: Vec, variables: Variables) -> Parser { - Parser { - tokens: tokens, - index: 0, - include_regex: Lazy::new(|| Regex::new(r"^(#include *)<(.*?)>").unwrap()), - include_regex_local: Lazy::new(|| Regex::new(r#"^(#include *)"(.*?)""#).unwrap()), - variables: variables, - json: false, - } - } - pub fn parse(&mut self) -> Vec { - let mut full_ast: Vec = Vec::new(); - while self.tokens.len() > self.index as usize { - let mut ast_res: Ast = Ast { - tokens: vec![], - ast_type: AstType::Other, - }; - let index = self.index as usize; - if index == self.tokens.len() { - panic!("Reached the end of tokens") +pub fn parse(code: String, vars: &mut Variables) -> Vec { + let mut ast: Vec = Vec::new(); + let mut tokens = tokenize(code); + while tokens.len() > 0 { + let mut drain: usize = 0; + match tokens.as_slice() { + [Token::Identifier(var_type), Token::Identifier(var_name), ..] => { + ast.push(Ast::Variable(var_type.clone(), var_name.clone())); + drain += 2; + // vars.new_var(var_name, State {}, desc) } - let token = &self.tokens[index]; - if self.json - && self.tokens.len() - (self.index as usize) > 2 - && self.tokens[index + 1].value == ":" - { - ast_res.ast_type = AstType::Json; - ast_res.tokens.push(self.tokens[index].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - self.index += 2; - } else if self.tokens.len() - index > 1 - && self.tokens[index].value == "&" - && self.tokens[index + 1].token_type == TokenType::Identifier - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.ast_type = AstType::Ref; - self.index += 1; - } else if self.tokens.len() - index > 2 - && self.tokens[index].value == "enum" - && self.tokens[index + 1].token_type == TokenType::Identifier - && self.tokens[index + 2].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::EnumDeceleration; - self.index += 2; - let mut desc = String::new(); - if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_enum( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 2 - && self.tokens[index].value == "struct" - && self.tokens[index + 1].token_type == TokenType::Identifier - && self.tokens[index + 2].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::StructDeceleration; - self.index += 2; - let mut desc = String::new(); - if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_struct( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 2 - && self.tokens[index].value == "namespace" - && self.tokens[index + 1].token_type == TokenType::Identifier - && self.tokens[index + 2].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::Namespace; - self.index += 2; - let mut desc = String::new(); - if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_namespace( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 2 - && self.tokens[index].value == "impl" - && self.tokens[index + 1].token_type == TokenType::Identifier - && self.tokens[index + 2].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::Impl; - self.index += 2; - } else if self.tokens.len() - index > 2 - && self.tokens[index].token_type == TokenType::Keyword1 - && self.tokens[index + 1].token_type == TokenType::Round - && self.tokens[index + 2].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index].clone()); - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::State3; - self.index += 2; - } else if self.tokens.len() - index > 1 - && self.tokens[index].token_type == TokenType::Keyword2 - && self.tokens[index + 1].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index].clone()); - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.ast_type = AstType::State2; - self.index += 1; - } else { - match token.token_type { - TokenType::Identifier => { - ast_res.tokens.push(self.tokens[index].clone()); - if self.tokens.len() - index > 3 - && self.tokens[index + 1].token_type == TokenType::Identifier - && self.tokens[index + 2].token_type == TokenType::Round - && self.tokens[index + 3].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.tokens.push(self.tokens[index + 3].clone()); - if token.value == "void" { - ast_res.ast_type = AstType::VoidFunctionDeceleration; - } else { - ast_res.ast_type = AstType::FunctionDeceleration; - } - self.index += 3; - let mut desc = String::new(); - if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment - { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_func( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 1 - && self.tokens[index + 1].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.ast_type = AstType::StructCall; - self.index += 1; - } else if self.tokens.len() - index > 2 - && self.tokens[index + 1].token_type == TokenType::Identifier - && self.tokens[index + 2].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::StructVar; - self.index += 2; - let mut desc = String::new(); - if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment - { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_var( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 1 { - if self.tokens[index + 1].token_type == TokenType::Identifier { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.ast_type = AstType::VariableDeceleration; - self.index += 1; - let mut desc = String::new(); - if index > 0 - && self.tokens[index - 1].token_type == TokenType::Comment - { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_var( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 2 - && self.tokens[index + 2].token_type == TokenType::Identifier - && self.tokens[index + 1].token_type == TokenType::Angle - { - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.tokens[0].value += "<"; - ast_res.tokens[0].value += self.tokens[index + 1].value.as_str(); - ast_res.tokens[0].value += ">"; - ast_res.ast_type = AstType::VariableDeceleration; - self.index += 2; - let mut desc = String::new(); - if index > 0 - && self.tokens[index - 1].token_type == TokenType::Comment - { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_var( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } else if self.tokens.len() - index > 2 - && self.tokens[index + 1].value == "*" - && self.tokens[index + 2].token_type == TokenType::Identifier - { - ast_res.tokens.push(self.tokens[index + 2].clone()); - ast_res.ast_type = AstType::PointerDeceleration; - self.index += 2; - let mut desc = String::new(); - if index > 0 - && self.tokens[index - 1].token_type == TokenType::Comment - { - desc = self.tokens[index - 1].value.clone() - } - self.variables.new_var( - self.tokens[index + 1].clone().value, - LexerState { - line: self.tokens[index + 1].clone().line, - column: self.tokens[index + 1].clone().column, - }, - desc, - ); - } - } - } - TokenType::Include => { - if let Some(caps) = self.include_regex.captures(&token.value) { - ast_res.tokens.push(Token { - token_type: TokenType::String, - value: caps[2].to_owned().to_string(), - line: 0, - column: 0, - }); - ast_res.ast_type = AstType::Include; - } else if let Some(caps) = self.include_regex_local.captures(&token.value) { - ast_res.tokens.push(Token { - token_type: TokenType::String, - value: caps[2].to_owned().to_string(), - line: 0, - column: 0, - }); - ast_res.ast_type = AstType::IncludeLocal; - } else { - ast_res.tokens.push(token.clone()); - ast_res.ast_type = AstType::Include; - } - } - TokenType::Keyword => { - if token.value == "cb" - && self.tokens[index + 1].token_type == TokenType::Curly - { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.ast_type = AstType::CodeBlock; - self.index += 1; - } else { - ast_res.tokens.push(token.clone()); - } - } - TokenType::StaticExecution => { - if self.tokens[index + 1].token_type == TokenType::Square { - ast_res.tokens.push(self.tokens[index + 1].clone()); - ast_res.ast_type = AstType::StaticExecution; - } - } - _ => { - ast_res.tokens.push(token.clone()); - } - } - } - self.index += 1; - full_ast.push(ast_res); + _ => {} } - full_ast + tokens.drain(0..drain); } + ast } diff --git a/src/transpiler.rs b/src/transpiler.rs index f794f88..56ae1b0 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,911 +1,46 @@ use crate::{ - file_writer::FileWriter, - lexer::{lex, LexerState, TokenType}, - lspcom::{Problem, ProblemType}, - parser::{is_decl, Ast, AstType, Parser}, - variable::{VariableType, Variables}, + parser::{self, Ast}, + utils::Problem, + variable::Variables, }; +use serde::{Deserialize, Serialize}; -use std::{fs, path::Path}; +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct State { + pub line: u32, + pub column: u32, +} -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Transpiler { - pub state: LexerState, - pub auto_mut: bool, - pub auto_macro: bool, - pub auto_pub: bool, - pub macros: Vec, - pub modnum: u32, - pub peek: String, pub matched_vars: Variables, + pub peek: String, + // pub libmgr: LibManager, pub problems: Vec, - pub writer: FileWriter, } impl Default for Transpiler { - fn default() -> Transpiler { - let transpiler = Transpiler { - writer: FileWriter::new(".".to_string()), - state: LexerState { line: 1, column: 0 }, - auto_mut: true, - auto_macro: true, - auto_pub: false, - macros: vec![String::from("println")], - modnum: 0, - peek: String::new(), + fn default() -> Self { + Transpiler { matched_vars: Variables::new(), + peek: String::new(), + // libmgr: LibManager::new(".".to_string()), problems: Vec::new(), - }; - transpiler + } } } impl Transpiler { - pub fn transpile(&mut self, input: String, indent: u32, variables: &mut Variables) -> String { - let mut result = String::new(); - if indent == 0 { - // result += "type int = i32;\n"; - } else { - result += " ".repeat((indent as usize) * 2).as_str(); - } - let lexer_out = lex(input.as_str(), false, self.state); - - match lexer_out { - Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone(), variables.clone()); - let mut last_ast = Ast { - ast_type: AstType::Other, - tokens: vec![], - }; - let f_ast = full_ast.parse(); - //variables.expand(full_ast.variables.clone()); - *variables = full_ast.variables.clone(); - //let mut variables = full_ast.variables.clone(); - for ast in f_ast { - let mut ast = ast; - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone().iter_mut() { - if (ctoken.line > var.state.line && var.vtype == VariableType::Var) - || var.vtype != VariableType::Var - { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } else { - for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { - if ast.tokens[i].token_type == TokenType::Identifier { - if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} - let x = variables.get_var(ast.tokens[i].value.clone(), self); - ast.tokens[i].value = x; - } - } - } - if last_ast.tokens.len() > 0 { - let mut fl = 0; - for t in &last_ast.tokens { - fl += t.value.len() - } - if ast.tokens[ast.tokens.len() - 1].column - > last_ast.tokens[last_ast.tokens.len() - 1].column + fl - { - result += " " - .repeat( - ast.tokens[ast.tokens.len() - 1].column - - (last_ast.tokens[last_ast.tokens.len() - 1].column + fl), - ) - .as_str(); - } - } - last_ast = Ast { - ast_type: ast.ast_type.clone(), - tokens: ast.tokens.clone(), - }; - - if ast.ast_type == AstType::FunctionDeceleration { - if self.auto_pub { - result += "pub "; - } - let mut vars: Variables = variables.clone(); - let round = self.transpile_round(ast.tokens[2].value.clone(), &mut vars); - result += format!( - "fn {}({}) -> {} {}", - ast.tokens[1].value, - round, - ast.tokens[0].value, - self.transpile( - ast.tokens[3].value.clone(), - indent + 1, - &mut (vars.clone()) - ) - ) - .as_str(); - } else if ast.ast_type == AstType::VoidFunctionDeceleration { - if self.auto_pub { - result += "pub "; - } - let mut vars: Variables = variables.clone(); - let round = self.transpile_round(ast.tokens[2].value.clone(), &mut vars); - result += format!( - "fn {}({}) {}", - ast.tokens[1].value, - round, - self.transpile( - ast.tokens[3].value.clone(), - indent + 1, - &mut (vars.clone()) - ) - ) - .as_str(); - } else if ast.ast_type == AstType::StructDeceleration { - if self.auto_pub { - result += "pub "; - } - let mut vars: Variables = variables.clone(); - let round = self.transpile_round(ast.tokens[1].value.clone(), &mut vars); - result += format!( - "enum {} {} {}", - ast.tokens[0].value, - "{\n", - round.trim_end() - ) - .replace( - "\n", - ("\n".to_string() + " ".repeat(((indent + 1) as usize) * 2).as_str()) - .as_str(), - ) - .as_str(); - result += "\n}\n"; - let vvars = variables.clone(); - if let Some(v) = variables.get_mut(ast.tokens[0].value.clone()) { - for (name, var) in vars.iter_mut() { - if !(vvars.vars.contains_key(name)) { - v.params.new_var( - name.to_string(), - LexerState { line: 0, column: 0 }, - var.desc.clone(), - ); - } - } - } - } else if ast.ast_type == AstType::StructDeceleration { - if self.auto_pub { - result += "pub "; - } - let mut vars: Variables = variables.clone(); - let round = self.transpile_round(ast.tokens[1].value.clone(), &mut vars); - result += format!( - "struct {} {} {}", - ast.tokens[0].value, - "{\n", - round.trim_end() - ) - .replace( - "\n", - ("\n".to_string() + " ".repeat(((indent + 1) as usize) * 2).as_str()) - .as_str(), - ) - .as_str(); - result += "\n}\n"; - let vvars = variables.clone(); - if let Some(v) = variables.get_mut(ast.tokens[0].value.clone()) { - for (name, var) in vars.iter_mut() { - if !(vvars.vars.contains_key(name)) { - v.params.new_var( - name.to_string(), - LexerState { line: 0, column: 0 }, - var.desc.clone(), - ); - } - } - } - } else if ast.ast_type == AstType::VariableDeceleration { - if self.clone().auto_mut { - result += - format!("let mut {}: {}", ast.tokens[1].value, ast.tokens[0].value) - .as_str(); - } else { - result += - format!("let {}: {}", ast.tokens[1].value, ast.tokens[0].value) - .as_str(); - } - } else if ast.ast_type == AstType::MutVariableDeceleration { - result += - format!("let mut {}: {}", ast.tokens[1].value, ast.tokens[0].value) - .as_str(); - } else if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Round - { - result += format!( - "({})", - self.transpile_round( - ast.tokens[0].value.clone(), - &mut variables.clone() - ) - ) - .as_str(); - } else if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Comment - { - result += ast.tokens[0].value.clone().as_str(); - result += " ".repeat((indent as usize) * 2).as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square - { - result += format!( - "[{}]", - self.transpile_square( - ast.tokens[0].value.clone(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column - }, - variables.clone() - ) - ) - .as_str(); - } else if ast.ast_type == AstType::CodeBlock { - result += "{"; - result += ast.tokens[0].value.as_str(); - result += "}"; - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Curly - { - result += self - .transpile_json( - ast.tokens[0].value.as_str().to_string(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column, - }, - variables.clone(), - ) - .as_str(); - // } - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Ptr { - result += "."; - } else if ast.ast_type == AstType::StructCall { - result += ast.tokens[0].value.as_str(); - result += " {"; - result += ast.tokens[1].value.as_str(); - result += "}"; - } else if ast.ast_type == AstType::StructVar { - result += format!( - "let mut {}: {} = {} {}{}{}", - ast.tokens[1].value.as_str(), - ast.tokens[0].value.as_str(), - ast.tokens[0].value.as_str(), - "{", - ast.tokens[2].value.as_str(), - "}" - ) - .as_str(); - } else if ast.ast_type == AstType::Include { - match self - .writer - .add(ast.tokens[0].value.clone(), variables, true) - { - Ok(modname) => { - result += "mod "; - result += modname.as_str(); - result += ";\n"; - result += "use "; - result += modname.as_str(); - result += "::*;\n"; - } - Err(ptype) => { - self.problems.push(ptype); - } - } - } else if ast.ast_type == AstType::IncludeLocal { - match self - .writer - .add(ast.tokens[0].value.clone(), variables, false) - { - Ok(modname) => { - result += "mod "; - result += modname.as_str(); - result += ";\n"; - result += "use "; - result += modname.as_str(); - result += "::*;\n"; - } - Err(ptype) => { - self.problems.push(ptype); - } - } - } else if ast.ast_type == AstType::State3 { - result += format!( - "{} {} {}", - ast.tokens[0].value.clone(), - self.transpile_round( - ast.tokens[1].value.clone(), - &mut variables.clone() - ), - self.transpile( - ast.tokens[2].value.clone(), - indent + 1, - &mut variables.clone() - ), - ) - .as_str(); - } else if ast.ast_type == AstType::State2 { - result += format!( - "{} {}", - ast.tokens[0].value.clone(), - self.transpile( - ast.tokens[1].value.clone(), - indent + 1, - &mut variables.clone() - ), - ) - .as_str(); - } else if ast.ast_type == AstType::Namespace { - result += format!( - "mod {} {}{}{}", - &ast.tokens[0].value.clone(), - "{", - self.transpile(ast.tokens[1].value.clone(), 0, &mut variables.clone()), - "}" - ) - .as_str(); - } else if ast.ast_type == AstType::Impl { - result += format!( - "impl {} {}{}{}", - &ast.tokens[0].value.clone(), - "{", - self.transpile(ast.tokens[1].value.clone(), 0, &mut variables.clone()), - "}" - ) - .as_str(); - } else if ast.ast_type == AstType::PointerDeceleration { - if self.auto_mut { - result += format!( - "let mut {}: &mut {}", - ast.tokens[1].value, ast.tokens[0].value - ) - .as_str(); - } else { - result += format!( - "let {}: &mut {}", - ast.tokens[1].value, ast.tokens[0].value - ) - .as_str(); - } - } else if ast.ast_type == AstType::StaticExecution { - result += r#"use serde::Deserialize; -use serde_json::Value; -#[derive(Deserialize, Debug)] -struct Request(i32, String, Vec<(bool, Value)>); -#[derive(Deserialize, Debug)] -struct Response(i32, Vec<(bool, Value)>); -"#; - } else if ast.ast_type == AstType::Ref { - result += "&mut "; - result += ast.tokens[0].value.as_str(); - } - // flp - else { - if ast.tokens[0].token_type == TokenType::Newline { - result += (ast.tokens[0].value.as_str().to_owned() - + (" ".repeat((indent as usize) * 2).as_str())) - .as_str(); - } else if ast.tokens[0].token_type == TokenType::Semicolon { - result += ";\n"; - result += " ".repeat((indent as usize) * 2).as_str(); - } else { - result += ast.tokens[0].value.as_str(); - if self.auto_macro - && self - .macros - .contains(&ast.tokens[0].value.as_str().to_string()) - { - result += "!"; - } - } - } - } - result = result.trim_end().to_string(); - if indent > 0 { - result += "\n"; - result += " ".repeat((indent as usize - 1) * 2).as_str(); - return "{\n".to_owned() + result.as_str() + "}"; - } else { - return result; + pub fn transpile(&mut self, code: String, indent: u32, vars: &mut Variables) -> String { + let ast = parser::parse(code, vars); + let mut res = String::new(); + for a in ast { + match a { + Ast::Variable(var_type, var_name) => { + res += format!("let mut {}: {}", var_name, var_type).as_str(); } } - Err((state, _tokens)) => { - panic!("Invalid syntax at code.ws:{}:{}", state.line, state.column); - } - } - } - pub fn transpile_mod(&mut self, ast: Ast, s: &str) -> String { - let modfile = ast.tokens[0].value.as_str(); - let modname = format!( - "mod_{}", - // clean_incl(modfile.split(".").collect::>()[0]), - self.clone().modnum - ); - let file_content = fs::read_to_string(s.to_string() + modfile).expect("Error reading file"); - let transpiled_code = self.transpile(file_content, 0, &mut Variables::new()); - fs::write( - ("build/".to_string() + modname.as_str()) + ".rs", - transpiled_code, - ) - .expect("Error writing file"); - modname - } - pub fn transpile_round(&mut self, input: String, variables: &mut Variables) -> String { - let mut result = String::new(); - let lexer_out = lex(input.as_str(), false, self.state); - match lexer_out { - Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone(), variables.clone()); - let mut last_ast = Ast { - ast_type: AstType::Other, - tokens: vec![], - }; - let fast = full_ast.parse(); - *variables = full_ast.variables.clone(); - for ast in fast { - let mut ast = ast; - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone().iter_mut() { - if (ctoken.line > var.state.line && var.vtype == VariableType::Var) - || var.vtype != VariableType::Var - { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } else { - for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { - if ast.tokens[i].token_type == TokenType::Identifier { - if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} - let x = variables.get_var(ast.tokens[i].value.clone(), self); - ast.tokens[i].value = x; - } - } - } - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone().iter_mut() { - if ctoken.line > var.state.line || var.vtype != VariableType::Var { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } - if last_ast.tokens.len() > 0 { - let mut fl = 0; - for t in &last_ast.tokens { - fl += t.value.len() - } - if ast.tokens[ast.tokens.len() - 1].column - > last_ast.tokens[last_ast.tokens.len() - 1].column + fl - { - result += " " - .repeat( - ast.tokens[ast.tokens.len() - 1].column - - (last_ast.tokens[last_ast.tokens.len() - 1].column + fl), - ) - .as_str(); - } - } - last_ast = Ast { - ast_type: ast.ast_type.clone(), - tokens: ast.tokens.clone(), - }; - if ast.ast_type == AstType::VariableDeceleration { - result += - format!("{}: {}", ast.tokens[1].value, ast.tokens[0].value).as_str(); - } else if ast.ast_type == AstType::MutVariableDeceleration { - result += format!("mut {}: {}", ast.tokens[1].value, ast.tokens[0].value) - .as_str(); - } else if ast.ast_type == AstType::PointerDeceleration { - result += format!("{}: &mut {}", ast.tokens[1].value, ast.tokens[0].value) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Round - { - result += format!( - "({})", - self.transpile_round( - ast.tokens[0].value.clone(), - &mut variables.clone() - ) - ) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square - { - result += format!( - "[{}]", - self.transpile_square( - ast.tokens[0].value.clone(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column - }, - variables.clone() - ) - ) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Ptr { - result += "."; - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Curly - { - result += self - .transpile_json( - ast.tokens[0].value.as_str().to_string(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column, - }, - variables.clone(), - ) - .as_str(); - } else if ast.ast_type == AstType::StructCall { - result += ast.tokens[0].value.as_str(); - result += " {"; - result += ast.tokens[1].value.as_str(); - result += "}"; - } else if ast.ast_type == AstType::Ref { - result += "&mut "; - result += ast.tokens[0].value.as_str(); - } - // flp - else { - result += ast.tokens[0].value.as_str(); - } - } - - result = result.trim_end().to_string(); - result - } - Err((state, _tokens)) => { - panic!("Invalid syntax at code.ws:{}:{}", state.line, state.column); - } - } - } - - pub fn transpile_square( - &mut self, - input: String, - state: LexerState, - variables: Variables, - ) -> String { - let mut result = String::new(); - let lexer_out = lex(input.as_str(), false, state); - match lexer_out { - Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone(), variables.clone()); - let mut last_ast = Ast { - ast_type: AstType::Other, - tokens: vec![], - }; - let fast = full_ast.parse(); - let mut variables = full_ast.variables.clone(); - for ast in fast { - let mut ast = ast; - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone().iter_mut() { - if (ctoken.line > var.state.line && var.vtype == VariableType::Var) - || var.vtype != VariableType::Var - { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } else { - for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { - if ast.tokens[i].token_type == TokenType::Identifier { - if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} - let x = variables.get_var(ast.tokens[i].value.clone(), self); - ast.tokens[i].value = x; - } - } - } - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.iter_mut() { - if ctoken.line > var.state.line || var.vtype != VariableType::Var { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } - if last_ast.tokens.len() > 0 { - let mut fl = 0; - for t in &last_ast.tokens { - fl += t.value.len() - } - if ast.tokens[ast.tokens.len() - 1].column - > last_ast.tokens[last_ast.tokens.len() - 1].column + fl - { - result += " " - .repeat( - ast.tokens[ast.tokens.len() - 1].column - - (last_ast.tokens[last_ast.tokens.len() - 1].column + fl), - ) - .as_str(); - } - } - last_ast = Ast { - ast_type: ast.ast_type.clone(), - tokens: ast.tokens.clone(), - }; - - if ast.ast_type == AstType::VariableDeceleration { - result += - format!("{}: {}", ast.tokens[1].value, ast.tokens[0].value).as_str(); - } else if ast.ast_type == AstType::MutVariableDeceleration { - result += format!("mut {}: {}", ast.tokens[1].value, ast.tokens[0].value) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Round - { - result += format!( - "({})", - self.transpile_round( - ast.tokens[0].value.clone(), - &mut variables.clone() - ) - ) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square - { - result += format!( - "[{}]", - self.transpile_square( - ast.tokens[0].value.clone(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column - }, - variables.clone() - ) - ) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Ptr { - result += "."; - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Curly - { - result += self - .transpile_json( - ast.tokens[0].value.as_str().to_string(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column, - }, - variables.clone(), - ) - .as_str(); - } else if ast.ast_type == AstType::StructCall { - result += ast.tokens[0].value.as_str(); - result += " {"; - result += ast.tokens[1].value.as_str(); - result += "}"; - } else if ast.ast_type == AstType::Ref { - result += "&mut "; - result += ast.tokens[0].value.as_str(); - } - // flp - else { - result += ast.tokens[0].value.as_str(); - } - } - - result = result.trim_end().to_string(); - result - } - Err((state, _tokens)) => { - panic!("Invalid syntax at code.ws:{}:{}", state.line, state.column); - } - } - } - - pub fn transpile_json( - &mut self, - input: String, - state: LexerState, - variables: Variables, - ) -> String { - let mut result = String::new(); - let lexer_out = lex(input.as_str(), false, state); - match lexer_out { - Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone(), variables.clone()); - full_ast.json = true; - result += "HashMap::from(["; - let mut last_ast = Ast { - ast_type: AstType::Other, - tokens: vec![], - }; - let fast = full_ast.parse(); - let mut variables = full_ast.variables.clone(); - for ast in fast { - let mut ast = ast; - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.clone().iter_mut() { - if (ctoken.line > var.state.line && var.vtype == VariableType::Var) - || var.vtype != VariableType::Var - { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } else { - for i in (if is_decl(&ast) { 1 } else { 0 })..ast.tokens.len() { - if ast.tokens[i].token_type == TokenType::Identifier { - if ast.tokens[i].value.contains(&self.peek) && self.peek != "" {} - let x = variables.get_var(ast.tokens[i].value.clone(), self); - ast.tokens[i].value = x; - } - } - } - if ast.ast_type == AstType::Other - && ast.tokens[0].token_type == TokenType::Identifier - && ast.tokens[0].value.contains(&self.peek) - && self.peek != "" - { - let ctoken = &ast.tokens[0]; - // let pname = ctoken.value.split(&self.peek).next().unwrap(); - for (name, var) in variables.iter_mut() { - if ctoken.line > var.state.line || var.vtype != VariableType::Var { - self.matched_vars.add( - var.vtype.clone(), - name.to_string(), - var.state, - var.desc.clone(), - ); - } - } - self.peek = String::new(); - continue; - } - if last_ast.tokens.len() > 0 { - let mut fl = 0; - for t in &last_ast.tokens { - fl += t.value.len() - } - if ast.tokens[ast.tokens.len() - 1].column - > last_ast.tokens[last_ast.tokens.len() - 1].column + fl - { - result += " " - .repeat( - ast.tokens[ast.tokens.len() - 1].column - - (last_ast.tokens[last_ast.tokens.len() - 1].column + fl), - ) - .as_str(); - } - } - last_ast = Ast { - ast_type: ast.ast_type.clone(), - tokens: ast.tokens.clone(), - }; - - if ast.ast_type == AstType::Json { - result += "("; - result += ast.tokens[0].value.as_str(); - result += ","; - result += ast.tokens[1].value.as_str(); - result += ")"; - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Round - { - result += format!( - "({})", - self.transpile_round( - ast.tokens[0].value.clone(), - &mut variables.clone() - ) - ) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square - { - result += format!( - "[{}]", - self.transpile_square( - ast.tokens[0].value.clone(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column - }, - variables.clone() - ) - ) - .as_str(); - } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Curly - { - result += self - .transpile_json( - ast.tokens[0].value.as_str().to_string(), - LexerState { - line: ast.tokens[0].line, - column: ast.tokens[0].column, - }, - variables.clone(), - ) - .as_str(); - } else if ast.ast_type == AstType::Ref { - result += "&mut "; - result += ast.tokens[0].value.as_str(); - } else { - result += ast.tokens[0].value.as_str(); - } - } - result += "])"; - result = result.trim_end().to_string(); - result - } - Err((state, _tokens)) => { - panic!("Invalid syntax at code.ws:{}:{}", state.line, state.column); - } } + res } } diff --git a/src/variable.rs b/src/variable.rs index e48a660..91abf9f 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -4,9 +4,8 @@ use rand::Rng; use serde::{Deserialize, Serialize}; use crate::{ - lexer::LexerState, - lspcom::{Problem, ProblemType}, - transpiler::Transpiler, + transpiler::{State, Transpiler}, + utils::{Problem, ProblemType}, }; #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] @@ -23,7 +22,7 @@ pub enum VariableType { pub struct Variable { pub vtype: VariableType, pub desc: String, - pub state: LexerState, + pub state: State, pub params: Variables, pub rname: String, } @@ -41,7 +40,7 @@ impl Variables { Variable { vtype: VariableType::Keyword, desc: "".to_string(), - state: LexerState { line: 0, column: 0 }, + state: State { line: 0, column: 0 }, params: Variables { vars: HashMap::new(), }, @@ -50,7 +49,7 @@ impl Variables { )]), } } - pub fn new_var(&mut self, name: String, state: LexerState, desc: String) { + pub fn new_var(&mut self, name: String, state: State, desc: String) { self.vars.insert( name, Variable { @@ -65,7 +64,7 @@ impl Variables { ); } - pub fn new_namespace(&mut self, name: String, state: LexerState, desc: String) { + pub fn new_namespace(&mut self, name: String, state: State, desc: String) { self.vars.insert( name, Variable { @@ -80,7 +79,7 @@ impl Variables { ); } - pub fn new_struct(&mut self, name: String, state: LexerState, desc: String) { + pub fn new_struct(&mut self, name: String, state: State, desc: String) { self.vars.insert( name, Variable { @@ -94,7 +93,7 @@ impl Variables { }, ); } - pub fn new_enum(&mut self, name: String, state: LexerState, desc: String) { + pub fn new_enum(&mut self, name: String, state: State, desc: String) { self.vars.insert( name, Variable { @@ -109,7 +108,7 @@ impl Variables { ); } - // pub fn new_keyword(&mut self, name: String, state: LexerState, desc: String) { + // pub fn new_keyword(&mut self, name: String, state: State, desc: String) { // self.vars.insert( // name, // Variable { @@ -124,7 +123,7 @@ impl Variables { // ); // } - pub fn new_func(&mut self, name: String, state: LexerState, desc: String) { + pub fn new_func(&mut self, name: String, state: State, desc: String) { self.vars.insert( name, Variable { @@ -138,7 +137,7 @@ impl Variables { }, ); } - pub fn add(&mut self, vtype: VariableType, name: String, state: LexerState, desc: String) { + pub fn add(&mut self, vtype: VariableType, name: String, state: State, desc: String) { self.vars.insert( name, Variable { From 8cbe87d59c886bffb4868175d4ad546a10acb86d Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Fri, 28 Jun 2024 14:57:55 +0200 Subject: [PATCH 03/21] rewrite 1 --- src/utils.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/utils.rs diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..e82d417 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum ProblemType { + VariableNotFound, + FileNotFound, + HeaderSyntaxError, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Problem { + //pub code: u32, + pub problem_type: ProblemType, + pub problem_msg: String, +} From beff172ff4386625e123f66626bbda262407aada Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Sat, 29 Jun 2024 19:48:11 +0200 Subject: [PATCH 04/21] better error checking --- src/main.rs | 8 +++-- src/parser.rs | 79 +++++++++++++++++++++++++++++++++++------------ src/transpiler.rs | 4 ++- src/utils.rs | 1 + 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/main.rs b/src/main.rs index f525f77..5e2a96d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,10 @@ mod variable; fn main() { let mut vars = Variables::new(); - let out = transpiler::Transpiler::default().transpile(r#"int x"#.to_string(), 0, &mut vars); - println!("{out}"); + let mut trsp = transpiler::Transpiler::default(); + let out = trsp.transpile("int 12 x".to_string(), 0, &mut vars); + for p in trsp.problems { + println!("{:?}: {}", p.problem_type, p.problem_msg) + } + println!("{out}\n\n\n{:?}", vars); } diff --git a/src/parser.rs b/src/parser.rs index e5ecb21..1b53d59 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,9 +1,15 @@ -use crate::{transpiler::State, variable::Variables}; +use std::usize; + +use crate::{ + transpiler::{State, Transpiler}, + utils::{Problem, ProblemType}, + variable::Variables, +}; #[derive(Clone, Debug)] pub enum Token { - Number(String), - Identifier(String), + Number(String, State), + Identifier(String, State), // Curly(String), // Round(String), // Square(String), @@ -12,24 +18,26 @@ pub enum Ast { Variable(String, String), } -pub fn get_token(v: String, t: u32) -> Token { +pub fn get_token(v: String, t: u32, state: State) -> Token { match t { - 1 => Token::Number(v), - 2 => Token::Identifier(v), - _ => Token::Number(String::from("")), + 1 => Token::Number(v, state), + 2 => Token::Identifier(v, state), + _ => Token::Number(String::from(""), state), } } -pub fn tokenize(code: String) -> Vec { +pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { let mut code = code; let mut tokens: Vec = Vec::new(); let mut token_value: String = String::new(); let mut token_type: u32 = 0; + //let mut state = State { line: } while !code.is_empty() { if let Some(c) = code.chars().next() { code.remove(0); let mut tval: char = c; let mut t: u32 = 0; + root.state.column += 1; match c { '0'..='9' => { if token_type == 2 { @@ -42,37 +50,70 @@ pub fn tokenize(code: String) -> Vec { t = 2; } '\t' | ' ' => tval = ' ', - _ => {} + '\n' | '\r' => { + tval = '\n'; + root.state.line += 1; + root.state.column = 0; + } + x => { + root.problems.push(Problem { + problem_msg: format!( + "Invalid character '{}' at {}:{}, LexingError", + x, root.state.line, root.state.column + ), + problem_type: ProblemType::SyntaxError, + }); + } } if t != token_type && token_type != 0 || tval == ' ' { - tokens.push(get_token(token_value.clone(), token_type)); + tokens.push(get_token( + token_value.clone(), + token_type, + root.state.clone(), + )); token_type = 0; token_value = String::new(); } - if tval != ' ' { + if tval != ' ' && tval != '\n' { token_type = t; token_value += tval.to_string().as_str(); } } } if token_type != 0 { - tokens.push(get_token(token_value.clone(), token_type)); + tokens.push(get_token( + token_value.clone(), + token_type, + root.state.clone(), + )); } tokens } -pub fn parse(code: String, vars: &mut Variables) -> Vec { +pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec { let mut ast: Vec = Vec::new(); - let mut tokens = tokenize(code); + let mut tokens = tokenize(code, root); + let mut pcon: Vec<(u32, u32)> = Vec::new(); while tokens.len() > 0 { - let mut drain: usize = 0; + let mut drain: usize = 1; match tokens.as_slice() { - [Token::Identifier(var_type), Token::Identifier(var_name), ..] => { + [Token::Identifier(var_type, state0), Token::Identifier(var_name, state1), ..] => { ast.push(Ast::Variable(var_type.clone(), var_name.clone())); - drain += 2; - // vars.new_var(var_name, State {}, desc) + 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 + ), + problem_type: ProblemType::SyntaxError, + }); + pcon.push((root.state.line, root.state.column)); + } } - _ => {} } tokens.drain(0..drain); } diff --git a/src/transpiler.rs b/src/transpiler.rs index 56ae1b0..4963679 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -17,6 +17,7 @@ pub struct Transpiler { pub peek: String, // pub libmgr: LibManager, pub problems: Vec, + pub state: State, } impl Default for Transpiler { @@ -26,13 +27,14 @@ impl Default for Transpiler { peek: String::new(), // libmgr: LibManager::new(".".to_string()), problems: Vec::new(), + state: State { line: 1, column: 0 }, } } } impl Transpiler { pub fn transpile(&mut self, code: String, indent: u32, vars: &mut Variables) -> String { - let ast = parser::parse(code, vars); + let ast = parser::parse(code, vars, self); let mut res = String::new(); for a in ast { match a { diff --git a/src/utils.rs b/src/utils.rs index e82d417..9ffdc53 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,6 +5,7 @@ pub enum ProblemType { VariableNotFound, FileNotFound, HeaderSyntaxError, + SyntaxError, } #[derive(Clone, Debug, Serialize, Deserialize)] From e9237eaf9afb2c77b715dbf3001071e86d510d81 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Mon, 1 Jul 2024 18:05:34 +0200 Subject: [PATCH 05/21] round brackets --- src/main.rs | 2 +- src/parser.rs | 118 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5e2a96d..1fc786e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod variable; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("int 12 x".to_string(), 0, &mut vars); + let out = trsp.transpile("(xyz)".to_string(), 0, &mut vars); for p in trsp.problems { println!("{:?}: {}", p.problem_type, p.problem_msg) } diff --git a/src/parser.rs b/src/parser.rs index 1b53d59..b68fb92 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -10,8 +10,8 @@ use crate::{ pub enum Token { Number(String, State), Identifier(String, State), - // Curly(String), - // Round(String), + Curly(String, State), + Round(String, State), // Square(String), } pub enum Ast { @@ -22,6 +22,7 @@ pub fn get_token(v: String, t: u32, state: State) -> Token { match t { 1 => Token::Number(v, state), 2 => Token::Identifier(v, state), + 3 => Token::Round(v, state), _ => Token::Number(String::from(""), state), } } @@ -31,52 +32,89 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { let mut tokens: Vec = Vec::new(); let mut token_value: String = String::new(); let mut token_type: u32 = 0; - //let mut state = State { line: } + let mut stoken: (u8, u8) = (0, 0); + let mut token_state = State { line: 0, column: 0 }; while !code.is_empty() { if let Some(c) = code.chars().next() { code.remove(0); - let mut tval: char = c; - let mut t: u32 = 0; + let mut tval = c; + let mut t: u32 = token_type; root.state.column += 1; - match c { - '0'..='9' => { - if token_type == 2 { + if stoken.1 > 0 { + match c { + ')' => { + if stoken.0 == 1 { + stoken.1 -= 1; + if stoken.1 == 0 { + stoken.0 = 0; + tokens.push(get_token( + token_value.clone(), + token_type, + token_state.clone(), + )); + token_type = 0; + token_value = String::new(); + } else { + token_value += c.to_string().as_str(); + } + } + } + '(' => { + if stoken.0 == 1 { + stoken.1 += 1; + token_value += c.to_string().as_str(); + } + } + _ => token_value += c.to_string().as_str(), + } + } else { + match c { + '0'..='9' => { + if token_type == 2 { + t = 2; + } else { + t = 1; + } + } + 'a'..='z' | 'A'..='Z' => { t = 2; - } else { - t = 1; + } + '\t' | ' ' => tval = '\n', + '\n' | '\r' => { + tval = '\n'; + root.state.line += 1; + root.state.column = 0; + } + '(' => { + stoken.0 = 1; + stoken.1 += 1; + tval = ' '; + t = 3; + } + x => { + root.problems.push(Problem { + problem_msg: format!( + "Invalid character '{}' at {}:{}, LexingError", + x, root.state.line, root.state.column + ), + problem_type: ProblemType::SyntaxError, + }); } } - 'a'..='z' | 'A'..='Z' => { - t = 2; + if t != token_type && token_type != 0 { + tokens.push(get_token( + token_value.clone(), + token_type, + token_state.clone(), + )); + token_type = 0; + token_value = String::new(); } - '\t' | ' ' => tval = ' ', - '\n' | '\r' => { - tval = '\n'; - root.state.line += 1; - root.state.column = 0; + if tval != '\n' { + token_state = root.state.clone(); + token_type = t; + token_value += tval.to_string().as_str().trim(); } - x => { - root.problems.push(Problem { - problem_msg: format!( - "Invalid character '{}' at {}:{}, LexingError", - x, root.state.line, root.state.column - ), - problem_type: ProblemType::SyntaxError, - }); - } - } - if t != token_type && token_type != 0 || tval == ' ' { - tokens.push(get_token( - token_value.clone(), - token_type, - root.state.clone(), - )); - token_type = 0; - token_value = String::new(); - } - if tval != ' ' && tval != '\n' { - token_type = t; - token_value += tval.to_string().as_str(); } } } @@ -93,6 +131,8 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec { let mut ast: Vec = Vec::new(); let mut tokens = tokenize(code, root); + println!("{:?}", tokens); + panic!("xd"); let mut pcon: Vec<(u32, u32)> = Vec::new(); while tokens.len() > 0 { let mut drain: usize = 1; From d5616821364e71047216524ec8087957b79157c1 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Mon, 1 Jul 2024 18:07:48 +0200 Subject: [PATCH 06/21] round brackets --- src/parser.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index b68fb92..c39b790 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -44,7 +44,7 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { match c { ')' => { if stoken.0 == 1 { - stoken.1 -= 1; + stoken.1 += 1; if stoken.1 == 0 { stoken.0 = 0; tokens.push(get_token( @@ -61,7 +61,30 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { } '(' => { if stoken.0 == 1 { + stoken.1 -= 1; + token_value += c.to_string().as_str(); + } + } + '{' => { + if stoken.0 == 2 { stoken.1 += 1; + if stoken.1 == 0 { + stoken.0 = 0; + tokens.push(get_token( + token_value.clone(), + token_type, + token_state.clone(), + )); + token_type = 0; + token_value = String::new(); + } else { + token_value += c.to_string().as_str(); + } + } + } + '}' => { + if stoken.0 == 2 { + stoken.1 -= 1; token_value += c.to_string().as_str(); } } @@ -131,8 +154,6 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec { let mut ast: Vec = Vec::new(); let mut tokens = tokenize(code, root); - println!("{:?}", tokens); - panic!("xd"); let mut pcon: Vec<(u32, u32)> = Vec::new(); while tokens.len() > 0 { let mut drain: usize = 1; From 001636c79985eba4d26e37ee1cf809c66f310b58 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Mon, 1 Jul 2024 18:12:06 +0200 Subject: [PATCH 07/21] curly --- src/main.rs | 2 +- src/parser.rs | 37 ++++++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1fc786e..027ea12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod variable; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("(xyz)".to_string(), 0, &mut vars); + let out = trsp.transpile("{xyz}".to_string(), 0, &mut vars); for p in trsp.problems { println!("{:?}: {}", p.problem_type, p.problem_msg) } diff --git a/src/parser.rs b/src/parser.rs index c39b790..65ae99a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -23,6 +23,7 @@ pub fn get_token(v: String, t: u32, state: State) -> Token { 1 => Token::Number(v, state), 2 => Token::Identifier(v, state), 3 => Token::Round(v, state), + 4 => Token::Curly(v, state), _ => Token::Number(String::from(""), state), } } @@ -42,9 +43,15 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { root.state.column += 1; if stoken.1 > 0 { match c { - ')' => { + '(' => { if stoken.0 == 1 { stoken.1 += 1; + token_value += c.to_string().as_str(); + } + } + ')' => { + if stoken.0 == 1 { + stoken.1 -= 1; if stoken.1 == 0 { stoken.0 = 0; tokens.push(get_token( @@ -59,15 +66,15 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { } } } - '(' => { - if stoken.0 == 1 { - stoken.1 -= 1; - token_value += c.to_string().as_str(); - } - } '{' => { - if stoken.0 == 2 { + if stoken.0 == 1 { stoken.1 += 1; + token_value += c.to_string().as_str(); + } + } + '}' => { + if stoken.0 == 1 { + stoken.1 -= 1; if stoken.1 == 0 { stoken.0 = 0; tokens.push(get_token( @@ -82,12 +89,6 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { } } } - '}' => { - if stoken.0 == 2 { - stoken.1 -= 1; - token_value += c.to_string().as_str(); - } - } _ => token_value += c.to_string().as_str(), } } else { @@ -110,10 +111,16 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { } '(' => { stoken.0 = 1; - stoken.1 += 1; + stoken.1 = 1; tval = ' '; t = 3; } + '{' => { + stoken.0 = 2; + stoken.1 = 1; + tval = ' '; + t = 4; + } x => { root.problems.push(Problem { problem_msg: format!( From 41c6b99e26736090d236c7ce82e269db0fbcb626 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Mon, 1 Jul 2024 18:24:02 +0200 Subject: [PATCH 08/21] functions --- src/main.rs | 2 +- src/parser.rs | 14 +++++++++++++- src/transpiler.rs | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 027ea12..2353c53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod variable; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("{xyz}".to_string(), 0, &mut vars); + let out = trsp.transpile("void main() {int x}".to_string(), 0, &mut vars); for p in trsp.problems { println!("{:?}: {}", p.problem_type, p.problem_msg) } diff --git a/src/parser.rs b/src/parser.rs index 65ae99a..55f6262 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -16,6 +16,7 @@ pub enum Token { } pub enum Ast { Variable(String, String), + Function(String, String, String, String), } pub fn get_token(v: String, t: u32, state: State) -> Token { @@ -131,7 +132,7 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { }); } } - if t != token_type && token_type != 0 { + if (t != token_type || tval == '\n') && token_type != 0 { tokens.push(get_token( token_value.clone(), token_type, @@ -165,6 +166,17 @@ 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), ..] => + { + ast.push(Ast::Function( + var_type.clone(), + var_name.clone(), + round.clone(), + curly.clone(), + )); + drain += 1; + vars.new_func(var_name.clone(), state1.clone(), "".to_string()); + } [Token::Identifier(var_type, state0), Token::Identifier(var_name, state1), ..] => { ast.push(Ast::Variable(var_type.clone(), var_name.clone())); drain += 1; diff --git a/src/transpiler.rs b/src/transpiler.rs index 4963679..9165c0a 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -41,6 +41,13 @@ impl Transpiler { Ast::Variable(var_type, var_name) => { res += format!("let mut {}: {}", var_name, var_type).as_str(); } + Ast::Function(var_type, var_name, round, curly) => { + res += format!( + "fn {}({}) -> {} {}{}{}", + var_name, round, var_type, "{", curly, "}" + ) + .as_str(); + } } } res From 3cb1ab90fd69b9c8e7645ebf1b08d8e29616b4d0 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Tue, 2 Jul 2024 15:06:11 +0200 Subject: [PATCH 09/21] better errors and defs --- src/main.rs | 15 ++++++++++-- src/parser.rs | 61 ++++++++++++++++++++++++++++++----------------- src/transpiler.rs | 22 +++++++++++++---- src/utils.rs | 8 +++++++ src/variable.rs | 39 +++++++++++++++++++----------- 5 files changed, 102 insertions(+), 43 deletions(-) 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; } } From 9b755b1821a0727d568f1eb48c502fe982f21bde Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Wed, 3 Jul 2024 12:07:05 +0200 Subject: [PATCH 10/21] better state system --- src/main.rs | 2 +- src/parser.rs | 78 +++++++++++++++++++++++++++++------------------ src/transpiler.rs | 12 +++++++- src/variable.rs | 14 --------- 4 files changed, 61 insertions(+), 45 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8431cfc..8cf7575 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ mod variable; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("void main() {x int x}".to_string(), 0, &mut vars); + let out = trsp.transpile("struct Test {}".to_string(), 0, &mut vars); for p in trsp.problems { match p { ProblemCap::Error(problem) => { diff --git a/src/parser.rs b/src/parser.rs index e479d12..e1d2644 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -10,33 +10,34 @@ use crate::{ #[allow(dead_code)] pub enum Token { Number(String, State), - Keyword(String, State), + DKeyword(String, State), Identifier(String, State), Curly(String, State), Round(String, State), // Square(String), } -pub fn extract_state(token: Token) -> State { +pub fn extract_values(token: Token) -> (String, State) { match token { - Token::Number(_, state) => state, - Token::Identifier(_, state) => state, - Token::Curly(_, state) => state, - Token::Round(_, state) => state, - Token::Keyword(_, state) => state, + Token::Number(x, state) => (x, state), + Token::Identifier(x, state) => (x, state), + Token::Curly(x, state) => (x, state), + Token::Round(x, state) => (x, state), + Token::DKeyword(x, state) => (x, state), } } pub enum Ast { Variable(String, String), Function(String, String, String, String), + Struct(String, String), } pub fn get_token(v: String, t: u32, state: State) -> Token { match t { 1 => Token::Number(v, state), 2 => match v.as_str() { - "enum" | "struct" | "namespace" => Token::Keyword(v, state), + "enum" | "struct" | "namespace" => Token::DKeyword(v, state), _ => Token::Identifier(v, state), }, 3 => Token::Round(v, state), @@ -45,7 +46,7 @@ pub fn get_token(v: String, t: u32, state: State) -> Token { } } -pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { +pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec { let mut code = code; let mut tokens: Vec = Vec::new(); let mut token_value: String = String::new(); @@ -56,8 +57,9 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { if let Some(c) = code.chars().next() { code.remove(0); let mut tval = c; - let mut t: u32 = token_type; - root.state.column += 1; + let mut t: u32 = 0; + let mut ignore = false; + state.column += 1; if stoken.1 > 0 { match c { '(' => { @@ -120,11 +122,13 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { 'a'..='z' | 'A'..='Z' => { t = 2; } - '\t' | ' ' => tval = '\n', + '\t' | ' ' => { + ignore = true; + } '\n' | '\r' => { - tval = '\n'; - root.state.line += 1; - root.state.column = 0; + ignore = true; + state.line += 1; + state.column = 0; } '(' => { stoken.0 = 1; @@ -142,11 +146,12 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { root.problems.push(ProblemCap::Error(Problem { problem_msg: format!("Invalid character '{}'", x,), problem_type: ProblemType::SyntaxError, - state: root.state.clone(), + state: state.clone(), })); + ignore = true; } } - if (t != token_type || tval == '\n') && token_type != 0 { + if token_type != t && token_type != 0 { tokens.push(get_token( token_value.clone(), token_type, @@ -155,27 +160,30 @@ pub fn tokenize(code: String, root: &mut Transpiler) -> Vec { token_type = 0; token_value = String::new(); } - if tval != '\n' { - token_state = root.state.clone(); + if token_type != t { + token_state = state.clone(); token_type = t; - token_value += tval.to_string().as_str().trim(); + token_value += tval.to_string().as_str(); + } else if !ignore { + token_value += tval.to_string().as_str(); } } } } if token_type != 0 { - tokens.push(get_token( - token_value.clone(), - token_type, - root.state.clone(), - )); + tokens.push(get_token(token_value.clone(), token_type, state.clone())); } tokens } -pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec { +pub fn parse( + code: String, + vars: &mut Variables, + state: &mut State, + root: &mut Transpiler, +) -> Vec { let mut ast: Vec = Vec::new(); - let mut tokens = tokenize(code, root); + let mut tokens = tokenize(code, state, root); let mut pcon: Vec<(u32, u32)> = Vec::new(); while tokens.len() > 0 { let mut drain: usize = 1; @@ -201,12 +209,24 @@ pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec + { + match keyword.as_str() { + "struct" => ast.push(Ast::Struct( + vars.new_struct(name.clone(), state.clone(), String::from("")), + curly.clone(), + )), + _ => {} + } + drain += 2; + } x => { - if !pcon.contains(&(root.state.line, root.state.column)) { + let estate = extract_values(x[0].clone()).1; + if !pcon.contains(&(estate.line, estate.column)) { root.problems.push(ProblemCap::Error(Problem { problem_msg: format!("Invalid placement"), problem_type: ProblemType::SyntaxError, - state: extract_state(x[0].clone()), + state: estate, })); pcon.push((root.state.line, root.state.column)); } diff --git a/src/transpiler.rs b/src/transpiler.rs index f30f1e8..bdce0f4 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -34,7 +34,7 @@ impl Default for Transpiler { impl Transpiler { pub fn transpile(&mut self, code: String, indent: usize, vars: &mut Variables) -> String { - let ast = parser::parse(code, vars, self); + let ast = parser::parse(code, vars, &mut self.state.clone(), self); let mut res = String::new(); if indent > 0 { res += " ".repeat(indent * 2).as_str(); @@ -56,6 +56,16 @@ impl Transpiler { ) .as_str(); } + Ast::Struct(name, curly) => { + res += format!( + "struct {} {}\n{}{}\n", + name, + "{", + self.transpile(curly, indent + 1, &mut vars.clone()), + "}" + ) + .as_str() + } } } if indent > 0 { diff --git a/src/variable.rs b/src/variable.rs index da95dc9..75c1bfb 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -147,20 +147,6 @@ impl Variables { ); rname } - pub fn add(&mut self, vtype: VariableType, name: String, state: State, desc: String) { - self.vars.insert( - name, - Variable { - vtype, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: generate_varname(), - }, - ); - } 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(); From e3ebe9d8d337e95d0f99b618b63fccb74e4338df Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Wed, 3 Jul 2024 17:17:25 +0200 Subject: [PATCH 11/21] better variable manager --- src/main.rs | 11 +-- src/parser.rs | 60 ++++++++++++--- src/transpiler.rs | 40 ++++++++-- src/utils.rs | 188 ++++++++++++++++++++++++++++++++++++++++++++- src/variable.rs | 191 ---------------------------------------------- 5 files changed, 273 insertions(+), 217 deletions(-) delete mode 100644 src/variable.rs diff --git a/src/main.rs b/src/main.rs index 8cf7575..0e17b5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,16 @@ -use utils::ProblemCap; -use variable::Variables; +use utils::{ProblemCap, Variables}; mod parser; mod transpiler; mod utils; -mod variable; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("struct Test {}".to_string(), 0, &mut vars); + trsp.inject.inject = true; + trsp.inject.state.line = 2; + trsp.inject.state.column = 2; + let out = trsp.transpile("int x\nx".to_string(), 0, &mut vars); for p in trsp.problems { match p { ProblemCap::Error(problem) => { @@ -23,5 +24,5 @@ fn main() { } } } - println!("{out}\n\n\n{:?}", vars); + println!("{out}\n\n\n"); } diff --git a/src/parser.rs b/src/parser.rs index e1d2644..d9261fb 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,8 +2,7 @@ use std::usize; use crate::{ transpiler::{State, Transpiler}, - utils::{Problem, ProblemCap, ProblemType}, - variable::Variables, + utils::{Problem, ProblemCap, ProblemType, Variables}, }; #[derive(Clone, Debug)] @@ -27,10 +26,34 @@ pub fn extract_values(token: Token) -> (String, State) { } } +pub fn extract_ast(ast: Ast) -> Vec { + let mut vstr: Vec = Vec::new(); + match ast { + Ast::Struct(a, _) => { + vstr.push(a); + } + Ast::Single(a) => match a { + Token::Identifier(b, _) => vstr.push(b), + _ => {} + }, + Ast::Variable(a, b) => { + vstr.push(a); + vstr.push(b); + } + Ast::Function(a, b, _, _) => { + vstr.push(a); + vstr.push(b); + } + } + vstr +} + +#[derive(Clone, Debug)] pub enum Ast { Variable(String, String), Function(String, String, String, String), Struct(String, String), + Single(Token), } pub fn get_token(v: String, t: u32, state: State) -> Token { @@ -48,6 +71,7 @@ pub fn get_token(v: String, t: u32, state: State) -> Token { pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec { let mut code = code; + code += " "; let mut tokens: Vec = Vec::new(); let mut token_value: String = String::new(); let mut token_type: u32 = 0; @@ -60,6 +84,12 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec 0 { match c { '(' => { @@ -184,9 +214,14 @@ pub fn parse( ) -> Vec { let mut ast: Vec = Vec::new(); let mut tokens = tokenize(code, state, root); - let mut pcon: Vec<(u32, u32)> = Vec::new(); while tokens.len() > 0 { let mut drain: usize = 1; + let vals = extract_values(tokens[0].clone()); + if vals.0.contains("list_vx") { + ast.push(Ast::Single(Token::Identifier(vals.0, vals.1))); + tokens.drain(0..1); + continue; + } match tokens.as_slice() { [Token::Identifier(var_type, state0), Token::Identifier(var_name, _state1), Token::Round(round, _state2), Token::Curly(curly, _state3), ..] => { @@ -221,15 +256,16 @@ pub fn parse( drain += 2; } x => { - let estate = extract_values(x[0].clone()).1; - if !pcon.contains(&(estate.line, estate.column)) { - root.problems.push(ProblemCap::Error(Problem { - problem_msg: format!("Invalid placement"), - problem_type: ProblemType::SyntaxError, - state: estate, - })); - pcon.push((root.state.line, root.state.column)); - } + ast.push(Ast::Single(x[0].clone())); + //let estate = extract_values(x[0].clone()).1; + //if !pcon.contains(&(estate.line, estate.column)) { + // root.problems.push(ProblemCap::Error(Problem { + // problem_msg: format!("Invalid placement"), + // problem_type: ProblemType::SyntaxError, + // state: estate, + // })); + // pcon.push((root.state.line, root.state.column)); + //} } } tokens.drain(0..drain); diff --git a/src/transpiler.rs b/src/transpiler.rs index bdce0f4..390c0bd 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,7 +1,6 @@ use crate::{ - parser::{self, Ast}, - utils::ProblemCap, - variable::Variables, + parser::{self, extract_ast, Ast}, + utils::{ProblemCap, VariableType, Variables}, }; use serde::{Deserialize, Serialize}; @@ -14,18 +13,30 @@ pub struct State { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Transpiler { pub matched_vars: Variables, - pub peek: String, - // pub libmgr: LibManager, pub problems: Vec, pub state: State, + pub inject: Inject, +} +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Inject { + pub state: State, + pub inject: bool, +} + +impl Default for Inject { + fn default() -> Self { + Inject { + inject: false, + state: State { line: 0, column: 0 }, + } + } } impl Default for Transpiler { fn default() -> Self { Transpiler { matched_vars: Variables::new(), - peek: String::new(), - // libmgr: LibManager::new(".".to_string()), + inject: Inject::default(), problems: Vec::new(), state: State { line: 1, column: 0 }, } @@ -40,6 +51,20 @@ impl Transpiler { res += " ".repeat(indent * 2).as_str(); } for a in ast { + let astval = extract_ast(a.clone()); + if self.inject.inject { + for val in astval { + if val.contains("list_vx") { + for (name, var) in vars.clone().iter_mut() { + if self.inject.state.line > var.state.line + || var.vtype != VariableType::Var + { + self.matched_vars.vars.insert(name.clone(), var.clone()); + } + } + } + } + } match a { Ast::Variable(var_type, var_name) => { res += format!("let mut {}: {}", var_name, var_type).as_str(); @@ -66,6 +91,7 @@ impl Transpiler { ) .as_str() } + Ast::Single(_) => {} } } if indent > 0 { diff --git a/src/utils.rs b/src/utils.rs index d5bed48..28526f6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,8 @@ -use serde::{Deserialize, Serialize}; - use crate::transpiler::State; +use crate::transpiler::Transpiler; +use rand::Rng; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum ProblemType { @@ -22,3 +24,185 @@ pub struct Problem { pub problem_msg: String, pub state: State, } + +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] +pub enum VariableType { + Var, + Func, + Keyword, + Struct, + Namespace, + Enum, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Variable { + pub vtype: VariableType, + pub desc: String, + pub state: State, + pub params: Variables, + pub rname: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Variables { + pub vars: HashMap, +} + +impl Variables { + pub fn new() -> Variables { + Variables { + vars: HashMap::from([( + "void".to_string(), + Variable { + vtype: VariableType::Keyword, + desc: "".to_string(), + state: State { line: 0, column: 0 }, + params: Variables { + vars: HashMap::new(), + }, + rname: "".to_string(), + }, + )]), + } + } + pub fn new_var(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); + self.vars.insert( + name, + Variable { + vtype: VariableType::Var, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: rname.clone(), + }, + ); + rname + } + + pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); + self.vars.insert( + name, + Variable { + vtype: VariableType::Namespace, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: rname.clone(), + }, + ); + rname + } + + pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); + self.vars.insert( + name, + Variable { + vtype: VariableType::Struct, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: rname.clone(), + }, + ); + rname + } + pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); + self.vars.insert( + name, + Variable { + vtype: VariableType::Enum, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: rname.clone(), + }, + ); + rname + } + + // pub fn new_keyword(&mut self, name: String, state: State, desc: String) { + // self.vars.insert( + // name, + // Variable { + // vtype: VariableType::Keyword, + // desc, + // state, + // params: Variables { + // vars: HashMap::new(), + // }, + // rname: generate_varname(), + // }, + // ); + // } + + pub fn new_func(&mut self, name: String, state: State, desc: String) -> String { + let rname = generate_varname(); + self.vars.insert( + name, + Variable { + vtype: VariableType::Func, + desc, + state, + params: Variables { + vars: HashMap::new(), + }, + rname: rname.clone(), + }, + ); + rname + } + 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(ProblemCap::Error(Problem { + problem_type: ProblemType::VariableNotFound, + problem_msg: format!("Variable '{}' doesn't exist", &name), + state: state, + })); + return name; + } + } + pub fn iter_mut( + &mut self, + ) -> std::collections::hash_map::IterMut<'_, std::string::String, Variable> { + self.vars.iter_mut() + } + pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> { + self.vars.get_mut(&name) + } + pub fn expand(&mut self, vars: Variables) { + for (x, y) in vars.vars { + self.vars.insert(x, y); + } + } +} + +pub fn generate_varname() -> String { + let mut rng = rand::thread_rng(); + let charset: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; + let mut result = String::with_capacity(19); + result.push('_'); + result.push('0'); + result.push('x'); + for _ in 0..14 { + let random_char = charset[rng.gen_range(0..charset.len())] as char; + result.push(random_char); + } + result +} diff --git a/src/variable.rs b/src/variable.rs deleted file mode 100644 index 75c1bfb..0000000 --- a/src/variable.rs +++ /dev/null @@ -1,191 +0,0 @@ -use std::collections::HashMap; - -use rand::Rng; -use serde::{Deserialize, Serialize}; - -use crate::{ - transpiler::{State, Transpiler}, - utils::{Problem, ProblemCap, ProblemType}, -}; - -#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] -pub enum VariableType { - Var, - Func, - Keyword, - Struct, - Namespace, - Enum, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Variable { - pub vtype: VariableType, - pub desc: String, - pub state: State, - pub params: Variables, - pub rname: String, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Variables { - pub vars: HashMap, -} - -impl Variables { - pub fn new() -> Variables { - Variables { - vars: HashMap::from([( - "void".to_string(), - Variable { - vtype: VariableType::Keyword, - desc: "".to_string(), - state: State { line: 0, column: 0 }, - params: Variables { - vars: HashMap::new(), - }, - rname: "".to_string(), - }, - )]), - } - } - pub fn new_var(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Var, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - - pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Namespace, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - - pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Struct, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Enum, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - - // pub fn new_keyword(&mut self, name: String, state: State, desc: String) { - // self.vars.insert( - // name, - // Variable { - // vtype: VariableType::Keyword, - // desc, - // state, - // params: Variables { - // vars: HashMap::new(), - // }, - // rname: generate_varname(), - // }, - // ); - // } - - pub fn new_func(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Func, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - 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(ProblemCap::Error(Problem { - problem_type: ProblemType::VariableNotFound, - problem_msg: format!("Variable '{}' doesn't exist", &name), - state: state, - })); - return name; - } - } - pub fn iter_mut( - &mut self, - ) -> std::collections::hash_map::IterMut<'_, std::string::String, Variable> { - self.vars.iter_mut() - } - pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> { - self.vars.get_mut(&name) - } - pub fn expand(&mut self, vars: Variables) { - for (x, y) in vars.vars { - self.vars.insert(x, y); - } - } -} - -pub fn generate_varname() -> String { - let mut rng = rand::thread_rng(); - let charset: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789"; - let mut result = String::with_capacity(19); - result.push('_'); - result.push('0'); - result.push('x'); - for _ in 0..14 { - let random_char = charset[rng.gen_range(0..charset.len())] as char; - result.push(random_char); - } - result -} From 0137beff70772549c8edda79f0e92c60cc333929 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Sat, 6 Jul 2024 13:43:49 +0200 Subject: [PATCH 12/21] rust code --- src/main.rs | 5 +---- src/parser.rs | 14 ++++++++++++++ src/transpiler.rs | 5 +++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0e17b5d..43e92bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,10 +7,7 @@ mod utils; fn main() { let mut vars = Variables::new(); let mut trsp = transpiler::Transpiler::default(); - trsp.inject.inject = true; - trsp.inject.state.line = 2; - trsp.inject.state.column = 2; - let out = trsp.transpile("int x\nx".to_string(), 0, &mut vars); + let out = trsp.transpile("rust{let mut x;}".to_string(), 0, &mut vars); for p in trsp.problems { match p { ProblemCap::Error(problem) => { diff --git a/src/parser.rs b/src/parser.rs index d9261fb..af3b487 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -9,6 +9,8 @@ use crate::{ #[allow(dead_code)] pub enum Token { Number(String, State), + Keyword(String, State), + SKeyword(String, State), DKeyword(String, State), Identifier(String, State), Curly(String, State), @@ -23,6 +25,8 @@ pub fn extract_values(token: Token) -> (String, State) { Token::Curly(x, state) => (x, state), Token::Round(x, state) => (x, state), Token::DKeyword(x, state) => (x, state), + Token::SKeyword(x, state) => (x, state), + Token::Keyword(x, state) => (x, state), } } @@ -44,6 +48,7 @@ pub fn extract_ast(ast: Ast) -> Vec { vstr.push(a); vstr.push(b); } + _ => {} } vstr } @@ -53,6 +58,7 @@ pub enum Ast { Variable(String, String), Function(String, String, String, String), Struct(String, String), + Rust(String), Single(Token), } @@ -61,6 +67,7 @@ pub fn get_token(v: String, t: u32, state: State) -> Token { 1 => Token::Number(v, state), 2 => match v.as_str() { "enum" | "struct" | "namespace" => Token::DKeyword(v, state), + "rust" => Token::SKeyword(v, state), _ => Token::Identifier(v, state), }, 3 => Token::Round(v, state), @@ -255,6 +262,13 @@ pub fn parse( } drain += 2; } + [Token::SKeyword(keyword, _), Token::Curly(curly, _), ..] => { + match keyword.as_str() { + "rust" => ast.push(Ast::Rust(curly.clone())), + _ => {} + } + drain += 1; + } x => { ast.push(Ast::Single(x[0].clone())); //let estate = extract_values(x[0].clone()).1; diff --git a/src/transpiler.rs b/src/transpiler.rs index 390c0bd..92ddbd4 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -91,6 +91,11 @@ impl Transpiler { ) .as_str() } + Ast::Rust(rs) => { + res += "{"; + res += rs.as_str(); + res += "}"; + } Ast::Single(_) => {} } } From 58af9cdd958edd548410eae736f512e8ba608367 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Tue, 9 Jul 2024 12:29:36 +0200 Subject: [PATCH 13/21] error codes and compiler --- Cargo.toml | 2 +- src/compiler.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 47 ++++++++++++++++++------------ src/parser.rs | 26 ++++++++++------- src/transpiler.rs | 23 ++++++++++++--- src/utils.rs | 28 ++++++++++++++++-- 6 files changed, 163 insertions(+), 37 deletions(-) create mode 100644 src/compiler.rs diff --git a/Cargo.toml b/Cargo.toml index feb4029..1b301ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] regex = "1.10.4" once_cell = "1.19.0" -clap = { version = "4.0", features = ["derive"] } +clap = "3.0" rand = "0.8.5" serde_json = "1.0" serde = "1.0.203" diff --git a/src/compiler.rs b/src/compiler.rs new file mode 100644 index 0000000..27714b7 --- /dev/null +++ b/src/compiler.rs @@ -0,0 +1,74 @@ +use std::{fs, path::Path, process::Command}; + +use crate::{ + transpiler::{State, Transpiler}, + utils::{Problem, ProblemCap, ProblemType, Variables}, +}; + +pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 { + let mut ecode: u8 = 0; + let mut trsp = Transpiler { + ..Default::default() + }; + let mut vars = Variables::new(); + if let Ok(file_contents) = fs::read_to_string(input_file) { + let mut output_code = trsp.transpile(file_contents, 0, &mut vars); + if is_main { + output_code += "fn main() {"; + output_code += vars + .get_var( + "main".to_string(), + &mut trsp, + State { + line: 0, + column: 0, + file: None, + }, + ) + .as_str(); + output_code += "();}"; + } + if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {} + } else { + trsp.problems.push(ProblemCap::Error(Problem { + problem_msg: "File not found".to_string(), + problem_type: ProblemType::FileNotFound, + state: State { + line: 0, + column: 0, + file: None, + }, + })) + } + for p in trsp.problems { + match p { + ProblemCap::Error(problem) => { + ecode = 1; + if problem.state.file == None { + println!( + "\x1b[31;1m{:?}\x1b[0;1m: {}", + problem.problem_type, problem.problem_msg, + ) + } else { + println!( + "\x1b[31;1mError\x1b[0;1m: {}\x1b[0m\n{}:{}: {:?}", + problem.problem_msg, + problem.state.line, + problem.state.column, + problem.problem_type, + ) + } + } + } + } + ecode +} + +pub fn compile_rust(exe_file: String) { + Command::new("rustc") + .arg(Path::new("build").join("main.rs")) + .arg("-o") + .arg(exe_file) + .output() + .expect("Error compiling rust: "); +} diff --git a/src/main.rs b/src/main.rs index 43e92bf..3b30eda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,36 @@ -use utils::{ProblemCap, Variables}; +use std::{fs, process}; +mod compiler; mod parser; mod transpiler; mod utils; +use clap::{App, Arg}; +use compiler::{compile_rust, transpile}; fn main() { - let mut vars = Variables::new(); - let mut trsp = transpiler::Transpiler::default(); - let out = trsp.transpile("rust{let mut x;}".to_string(), 0, &mut vars); - for p in trsp.problems { - 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"); + let matches = App::new("Wyst") + .version("0.51") + .author("Leo dev") + .about("The wyst compiler") + .arg( + Arg::with_name("file") + .required(true) + .help("Sets the input file to use"), + ) + .arg( + Arg::with_name("output") + .short('o') + .long("output") + .takes_value(true) + .help("Specifies the output executable file name"), + ) + .get_matches(); + + let file = matches.value_of("file").unwrap().to_string(); + let output = matches.value_of("output").unwrap_or("out").to_string(); + if let Ok(_) = fs::create_dir("build") {} + let ecode = transpile(file, "main.rs".to_string(), true); + compile_rust(output); + fs::remove_dir_all("build").expect("Error removing build"); + process::exit(ecode as i32); } diff --git a/src/parser.rs b/src/parser.rs index af3b487..5bc2238 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,15 +18,15 @@ pub enum Token { // Square(String), } -pub fn extract_values(token: Token) -> (String, State) { +pub fn extract_values(token: Token) -> (u8, String, State) { match token { - Token::Number(x, state) => (x, state), - Token::Identifier(x, state) => (x, state), - Token::Curly(x, state) => (x, state), - Token::Round(x, state) => (x, state), - Token::DKeyword(x, state) => (x, state), - Token::SKeyword(x, state) => (x, state), - Token::Keyword(x, state) => (x, state), + Token::Number(x, state) => (0, x, state), + Token::Identifier(x, state) => (1, x, state), + Token::Curly(x, state) => (2, x, state), + Token::Round(x, state) => (3, x, state), + Token::DKeyword(x, state) => (4, x, state), + Token::SKeyword(x, state) => (5, x, state), + Token::Keyword(x, state) => (6, x, state), } } @@ -83,7 +83,11 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec 0 { let mut drain: usize = 1; let vals = extract_values(tokens[0].clone()); - if vals.0.contains("list_vx") { - ast.push(Ast::Single(Token::Identifier(vals.0, vals.1))); + if vals.1.contains("list_vx") { + ast.push(Ast::Single(Token::Identifier(vals.1, vals.2))); tokens.drain(0..1); continue; } diff --git a/src/transpiler.rs b/src/transpiler.rs index 92ddbd4..c970ae8 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,5 +1,5 @@ use crate::{ - parser::{self, extract_ast, Ast}, + parser::{self, extract_ast, extract_values, Ast}, utils::{ProblemCap, VariableType, Variables}, }; use serde::{Deserialize, Serialize}; @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; pub struct State { pub line: u32, pub column: u32, + pub file: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -27,7 +28,11 @@ impl Default for Inject { fn default() -> Self { Inject { inject: false, - state: State { line: 0, column: 0 }, + state: State { + line: 0, + column: 0, + file: None, + }, } } } @@ -38,7 +43,11 @@ impl Default for Transpiler { matched_vars: Variables::new(), inject: Inject::default(), problems: Vec::new(), - state: State { line: 1, column: 0 }, + state: State { + line: 1, + column: 0, + file: None, + }, } } } @@ -96,7 +105,13 @@ impl Transpiler { res += rs.as_str(); res += "}"; } - Ast::Single(_) => {} + Ast::Single(x) => { + let vals = extract_values(x); + if vals.0 == 1 { + println!("{:?}", vals); + res += vars.get_var(vals.1, self, vals.2).as_str(); + } + } } } if indent > 0 { diff --git a/src/utils.rs b/src/utils.rs index 28526f6..626dfbe 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,7 +19,6 @@ pub enum ProblemCap { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Problem { - //pub code: u32, pub problem_type: ProblemType, pub problem_msg: String, pub state: State, @@ -57,7 +56,11 @@ impl Variables { Variable { vtype: VariableType::Keyword, desc: "".to_string(), - state: State { line: 0, column: 0 }, + state: State { + line: 0, + column: 0, + file: None, + }, params: Variables { vars: HashMap::new(), }, @@ -182,7 +185,26 @@ impl Variables { self.vars.iter_mut() } pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> { - self.vars.get_mut(&name) + if !name.contains("::") { + return self.vars.get_mut(&name); + } + if let Some((x, _)) = name.split_once("::") { + println!("{x}"); + if let Some(v) = self.vars.get_mut(x) { + println!("{:?}", v); + let mut var = v; + for a in name.split("::") { + if let Some(b) = var.params.vars.get_mut(a) { + var = b; + } else { + return None; + } + } + return Some(var); + } + return None; + } + None } pub fn expand(&mut self, vars: Variables) { for (x, y) in vars.vars { From f4759f01c81eb001355bb0d6d8b423f962f3977e Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Thu, 11 Jul 2024 14:15:31 +0200 Subject: [PATCH 14/21] new compiler --- src/main.rs | 34 ++++++++++---- src/parser.rs | 117 +++++++++++++++++++++++++++++++++++++--------- src/transpiler.rs | 11 +++-- src/utils.rs | 48 +++++++++++++------ 4 files changed, 163 insertions(+), 47 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3b30eda..0fe5c31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,15 +22,33 @@ fn main() { .short('o') .long("output") .takes_value(true) - .help("Specifies the output executable file name"), + .help("Specifies the output binary file name"), + ) + .arg( + Arg::with_name("build") + .short('b') + .long("build") + .help("Puts the rust files in the build directory"), + ) + .arg( + Arg::with_name("stdio") + .short('s') + .long("stdio") + .help("LSP Mode"), ) .get_matches(); - let file = matches.value_of("file").unwrap().to_string(); - let output = matches.value_of("output").unwrap_or("out").to_string(); - if let Ok(_) = fs::create_dir("build") {} - let ecode = transpile(file, "main.rs".to_string(), true); - compile_rust(output); - fs::remove_dir_all("build").expect("Error removing build"); - process::exit(ecode as i32); + if matches.is_present("stdio") { + println!("stdio mode!"); + } else { + let file = matches.value_of("file").unwrap().to_string(); + let output = matches.value_of("output").unwrap_or("out").to_string(); + if let Ok(_) = fs::create_dir("build") {} + let ecode = transpile(file, "main.rs".to_string(), true); + compile_rust(output); + if !matches.is_present("build") { + fs::remove_dir_all("build").expect("Error removing build"); + } + process::exit(ecode as i32); + } } diff --git a/src/parser.rs b/src/parser.rs index 5bc2238..4c57304 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,10 +1,33 @@ use std::usize; +use once_cell::sync::Lazy; +use regex::Regex; + use crate::{ transpiler::{State, Transpiler}, utils::{Problem, ProblemCap, ProblemType, Variables}, }; +pub struct Node { + pub regex_pattern: Lazy, + pub token: u32, +} + +const NODES: [Node; 3] = [ + Node { + token: 1, + regex_pattern: Lazy::new(|| Regex::new(r"^(0(x|X)\d+|\d+)").unwrap()), + }, + Node { + token: 2, + regex_pattern: Lazy::new(|| Regex::new(r"^[.:_a-zA-Z][a-zA-Z0-9_.:]*").unwrap()), + }, + Node { + token: 5, + regex_pattern: Lazy::new(|| Regex::new(r"^(\;|\!|\=)").unwrap()), + }, +]; + #[derive(Clone, Debug)] #[allow(dead_code)] pub enum Token { @@ -15,6 +38,8 @@ pub enum Token { Identifier(String, State), Curly(String, State), Round(String, State), + Operator(String, State), + String(String, State), // Square(String), } @@ -27,6 +52,8 @@ pub fn extract_values(token: Token) -> (u8, String, State) { Token::DKeyword(x, state) => (4, x, state), Token::SKeyword(x, state) => (5, x, state), Token::Keyword(x, state) => (6, x, state), + Token::Operator(x, state) => (7, x, state), + Token::String(x, state) => (8, x, state), } } @@ -72,10 +99,30 @@ pub fn get_token(v: String, t: u32, state: State) -> Token { }, 3 => Token::Round(v, state), 4 => Token::Curly(v, state), + 5 => Token::Operator(v, state), + 6 => Token::String(v, state), _ => Token::Number(String::from(""), state), } } +pub fn tokenzie_regex(code: String, state: &mut State) -> (u32, String) { + let mut token = (0, String::new()); + if !code.is_empty() { + for node in &NODES { + if let Some(caps) = node.regex_pattern.captures(&code) { + token.0 = node.token; + token.1 = caps[0].to_string(); + state.column += token.1.len() as u32; + if token.1.contains("\n") { + state.column = 0; + state.line += token.1.chars().filter(|c| *c == '\n').count() as u32; + } + } + } + } + token +} + pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec { let mut code = code; code += " "; @@ -91,7 +138,8 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec Vec { - if stoken.0 == 1 { + if stoken.0 == 2 { stoken.1 += 1; token_value += c.to_string().as_str(); } } '}' => { - if stoken.0 == 1 { + if stoken.0 == 2 { stoken.1 -= 1; if stoken.1 == 0 { stoken.0 = 0; @@ -149,20 +197,35 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec { + token_value += c.to_string().as_str(); + if stoken.0 == 3 { + stoken.1 -= 1; + if stoken.1 == 0 { + stoken.0 = 0; + tokens.push(get_token( + token_value.clone(), + token_type, + token_state.clone(), + )); + token_type = 0; + token_value = String::new(); + } + } + } + '\\' => { + token_value += c.to_string().as_str(); + token_value += code + .chars() + .next() + .expect("Error expected a char for \\") + .to_string() + .as_str(); + } _ => token_value += c.to_string().as_str(), } } else { match c { - '0'..='9' => { - if token_type == 2 { - t = 2; - } else { - t = 1; - } - } - 'a'..='z' | 'A'..='Z' => { - t = 2; - } '\t' | ' ' => { ignore = true; } @@ -174,23 +237,35 @@ pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec { stoken.0 = 1; stoken.1 = 1; - tval = ' '; + tval = " "; t = 3; } '{' => { stoken.0 = 2; stoken.1 = 1; - tval = ' '; + tval = " "; t = 4; } - x => { - root.problems.push(ProblemCap::Error(Problem { - problem_msg: format!("Invalid character '{}'", x,), - problem_type: ProblemType::SyntaxError, - state: state.clone(), - })); + '"' => { + stoken.0 = 3; + stoken.1 = 1; + t = 6; ignore = true; } + x => { + ignore = true; + let vals = tokenzie_regex(format!("{}{}", c, code.clone()), state); + if vals.0 != 0 { + tokens.push(get_token(vals.1.clone(), vals.0, state.clone())); + code.drain(0..vals.1.len() - 1); + } else { + root.problems.push(ProblemCap::Error(Problem { + problem_msg: format!("Invalid syntax '{}'", x,), + problem_type: ProblemType::SyntaxError, + state: state.clone(), + })); + } + } } if token_type != t && token_type != 0 { tokens.push(get_token( diff --git a/src/transpiler.rs b/src/transpiler.rs index c970ae8..953c79c 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -106,10 +106,15 @@ impl Transpiler { res += "}"; } Ast::Single(x) => { + println!("{:?}", x); let vals = extract_values(x); - if vals.0 == 1 { - println!("{:?}", vals); - res += vars.get_var(vals.1, self, vals.2).as_str(); + match vals.0 { + 2 => res += vars.get_var(vals.1, self, vals.2).as_str(), + 3 => res += format!("({})", vals.1).as_str(), + 8 => res += vals.1.as_str(), + _ => { + res += vals.1.as_str(); + } } } } diff --git a/src/utils.rs b/src/utils.rs index 626dfbe..ad41986 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -51,22 +51,40 @@ pub struct Variables { impl Variables { pub fn new() -> Variables { Variables { - vars: HashMap::from([( - "void".to_string(), - Variable { - vtype: VariableType::Keyword, - desc: "".to_string(), - state: State { - line: 0, - column: 0, - file: None, + vars: HashMap::from([ + ( + "void".to_string(), + Variable { + vtype: VariableType::Keyword, + desc: "".to_string(), + state: State { + line: 0, + column: 0, + file: None, + }, + params: Variables { + vars: HashMap::new(), + }, + rname: "".to_string(), }, - params: Variables { - vars: HashMap::new(), + ), + ( + "println".to_string(), + Variable { + vtype: VariableType::Keyword, + desc: "".to_string(), + state: State { + line: 0, + column: 0, + file: None, + }, + params: Variables { + vars: HashMap::new(), + }, + rname: "println".to_string(), }, - rname: "".to_string(), - }, - )]), + ), + ]), } } pub fn new_var(&mut self, name: String, state: State, desc: String) -> String { @@ -173,7 +191,7 @@ impl Variables { } else { root.problems.push(ProblemCap::Error(Problem { problem_type: ProblemType::VariableNotFound, - problem_msg: format!("Variable '{}' doesn't exist", &name), + problem_msg: format!("'{}' doesn't exist", &name), state: state, })); return name; From 573ba1f7454bf8b72720b27a2b1616ae4240bc84 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Thu, 11 Jul 2024 14:20:00 +0200 Subject: [PATCH 15/21] rd --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index d2fc3bc..72248c2 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,19 @@

Wyst is a programing language that has similar syntax to C and transpiles to Rust

+<<<<<<< HEAD # Re Write We are re-writing the parser and transpiler due to the messy code that is very hard to expand +======= +```c +#include + +int main() { + printf("Hello, World!"); + return 0; +} +``` +>>>>>>> 30ed01f (Update README.md) # Alpha We are on pure alpha. if you would like to contribute please open a new issue. From 84c69df2767a9a774c3b8cb42094f44ffbd15d1a Mon Sep 17 00:00:00 2001 From: Leo dev Date: Thu, 11 Jul 2024 17:47:26 +0200 Subject: [PATCH 16/21] using pest --- Cargo.toml | 6 +- src/parser.rs | 375 ++-------------------------------------------- src/transpiler.rs | 133 ++++++++-------- src/wyst.pest | 58 +++++++ 4 files changed, 143 insertions(+), 429 deletions(-) create mode 100644 src/wyst.pest diff --git a/Cargo.toml b/Cargo.toml index 1b301ff..51411da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -regex = "1.10.4" -once_cell = "1.19.0" -clap = "3.0" rand = "0.8.5" serde_json = "1.0" serde = "1.0.203" @@ -16,3 +13,6 @@ serde_derive = "1.0.203" lsp-types = "0.97.0" zip = "2.1.3" dirs = "5.0.1" +pest = "2" +pest_derive = "2" +clap = "3" \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index 4c57304..d161d4a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,367 +1,22 @@ -use std::usize; +use pest::Parser; +use pest_derive::Parser; -use once_cell::sync::Lazy; -use regex::Regex; +#[derive(Parser)] +#[grammar = "wyst.pest"] +pub struct WystParser; -use crate::{ - transpiler::{State, Transpiler}, - utils::{Problem, ProblemCap, ProblemType, Variables}, -}; - -pub struct Node { - pub regex_pattern: Lazy, - pub token: u32, -} - -const NODES: [Node; 3] = [ - Node { - token: 1, - regex_pattern: Lazy::new(|| Regex::new(r"^(0(x|X)\d+|\d+)").unwrap()), - }, - Node { - token: 2, - regex_pattern: Lazy::new(|| Regex::new(r"^[.:_a-zA-Z][a-zA-Z0-9_.:]*").unwrap()), - }, - Node { - token: 5, - regex_pattern: Lazy::new(|| Regex::new(r"^(\;|\!|\=)").unwrap()), - }, -]; - -#[derive(Clone, Debug)] -#[allow(dead_code)] -pub enum Token { - Number(String, State), - Keyword(String, State), - SKeyword(String, State), - DKeyword(String, State), - Identifier(String, State), - Curly(String, State), - Round(String, State), - Operator(String, State), - String(String, State), - // Square(String), -} - -pub fn extract_values(token: Token) -> (u8, String, State) { - match token { - Token::Number(x, state) => (0, x, state), - Token::Identifier(x, state) => (1, x, state), - Token::Curly(x, state) => (2, x, state), - Token::Round(x, state) => (3, x, state), - Token::DKeyword(x, state) => (4, x, state), - Token::SKeyword(x, state) => (5, x, state), - Token::Keyword(x, state) => (6, x, state), - Token::Operator(x, state) => (7, x, state), - Token::String(x, state) => (8, x, state), - } -} - -pub fn extract_ast(ast: Ast) -> Vec { - let mut vstr: Vec = Vec::new(); - match ast { - Ast::Struct(a, _) => { - vstr.push(a); - } - Ast::Single(a) => match a { - Token::Identifier(b, _) => vstr.push(b), - _ => {} - }, - Ast::Variable(a, b) => { - vstr.push(a); - vstr.push(b); - } - Ast::Function(a, b, _, _) => { - vstr.push(a); - vstr.push(b); - } - _ => {} - } - vstr -} - -#[derive(Clone, Debug)] -pub enum Ast { - Variable(String, String), - Function(String, String, String, String), - Struct(String, String), - Rust(String), - Single(Token), -} - -pub fn get_token(v: String, t: u32, state: State) -> Token { - match t { - 1 => Token::Number(v, state), - 2 => match v.as_str() { - "enum" | "struct" | "namespace" => Token::DKeyword(v, state), - "rust" => Token::SKeyword(v, state), - _ => Token::Identifier(v, state), - }, - 3 => Token::Round(v, state), - 4 => Token::Curly(v, state), - 5 => Token::Operator(v, state), - 6 => Token::String(v, state), - _ => Token::Number(String::from(""), state), - } -} - -pub fn tokenzie_regex(code: String, state: &mut State) -> (u32, String) { - let mut token = (0, String::new()); - if !code.is_empty() { - for node in &NODES { - if let Some(caps) = node.regex_pattern.captures(&code) { - token.0 = node.token; - token.1 = caps[0].to_string(); - state.column += token.1.len() as u32; - if token.1.contains("\n") { - state.column = 0; - state.line += token.1.chars().filter(|c| *c == '\n').count() as u32; +pub fn parse(input: String, rule: Rule) { + match WystParser::parse(rule, &input) { + Ok(parsed) => { + for pair in parsed { + for inner in pair.into_inner() { + println!("{:?}", inner.into_inner()) } } + // println!("{:#?}", parsed); + } + Err(e) => { + println!("Ok: {}", e); } } - token -} - -pub fn tokenize(code: String, state: &mut State, root: &mut Transpiler) -> Vec { - let mut code = code; - code += " "; - let mut tokens: Vec = Vec::new(); - let mut token_value: String = String::new(); - let mut token_type: u32 = 0; - let mut stoken: (u8, u8) = (0, 0); - let mut token_state = State { - line: 0, - column: 0, - file: None, - }; - while !code.is_empty() { - if let Some(c) = code.chars().next() { - code.remove(0); - let tc = c.to_string(); - let mut tval = tc.as_str(); - let mut t: u32 = 0; - let mut ignore = false; - state.column += 1; - if root.inject.inject - && root.inject.state.line == state.line - && root.inject.state.column == state.column - { - token_value += "list_vx"; - } - if stoken.1 > 0 { - match c { - '(' => { - if stoken.0 == 1 { - stoken.1 += 1; - token_value += c.to_string().as_str(); - } - } - ')' => { - if stoken.0 == 1 { - stoken.1 -= 1; - if stoken.1 == 0 { - stoken.0 = 0; - tokens.push(get_token( - token_value.clone(), - token_type, - token_state.clone(), - )); - token_type = 0; - token_value = String::new(); - } else { - token_value += c.to_string().as_str(); - } - } - } - '{' => { - if stoken.0 == 2 { - stoken.1 += 1; - token_value += c.to_string().as_str(); - } - } - '}' => { - if stoken.0 == 2 { - stoken.1 -= 1; - if stoken.1 == 0 { - stoken.0 = 0; - tokens.push(get_token( - token_value.clone(), - token_type, - token_state.clone(), - )); - token_type = 0; - token_value = String::new(); - } else { - token_value += c.to_string().as_str(); - } - } - } - '"' => { - token_value += c.to_string().as_str(); - if stoken.0 == 3 { - stoken.1 -= 1; - if stoken.1 == 0 { - stoken.0 = 0; - tokens.push(get_token( - token_value.clone(), - token_type, - token_state.clone(), - )); - token_type = 0; - token_value = String::new(); - } - } - } - '\\' => { - token_value += c.to_string().as_str(); - token_value += code - .chars() - .next() - .expect("Error expected a char for \\") - .to_string() - .as_str(); - } - _ => token_value += c.to_string().as_str(), - } - } else { - match c { - '\t' | ' ' => { - ignore = true; - } - '\n' | '\r' => { - ignore = true; - state.line += 1; - state.column = 0; - } - '(' => { - stoken.0 = 1; - stoken.1 = 1; - tval = " "; - t = 3; - } - '{' => { - stoken.0 = 2; - stoken.1 = 1; - tval = " "; - t = 4; - } - '"' => { - stoken.0 = 3; - stoken.1 = 1; - t = 6; - ignore = true; - } - x => { - ignore = true; - let vals = tokenzie_regex(format!("{}{}", c, code.clone()), state); - if vals.0 != 0 { - tokens.push(get_token(vals.1.clone(), vals.0, state.clone())); - code.drain(0..vals.1.len() - 1); - } else { - root.problems.push(ProblemCap::Error(Problem { - problem_msg: format!("Invalid syntax '{}'", x,), - problem_type: ProblemType::SyntaxError, - state: state.clone(), - })); - } - } - } - if token_type != t && token_type != 0 { - tokens.push(get_token( - token_value.clone(), - token_type, - token_state.clone(), - )); - token_type = 0; - token_value = String::new(); - } - if token_type != t { - token_state = state.clone(); - token_type = t; - token_value += tval.to_string().as_str(); - } else if !ignore { - token_value += tval.to_string().as_str(); - } - } - } - } - if token_type != 0 { - tokens.push(get_token(token_value.clone(), token_type, state.clone())); - } - tokens -} - -pub fn parse( - code: String, - vars: &mut Variables, - state: &mut State, - root: &mut Transpiler, -) -> Vec { - let mut ast: Vec = Vec::new(); - let mut tokens = tokenize(code, state, root); - while tokens.len() > 0 { - let mut drain: usize = 1; - let vals = extract_values(tokens[0].clone()); - if vals.1.contains("list_vx") { - ast.push(Ast::Single(Token::Identifier(vals.1, vals.2))); - tokens.drain(0..1); - continue; - } - match tokens.as_slice() { - [Token::Identifier(var_type, state0), Token::Identifier(var_name, _state1), Token::Round(round, _state2), Token::Curly(curly, _state3), ..] => - { - ast.push(Ast::Function( - 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 += 3; - } - [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; - } - [Token::DKeyword(keyword, _), Token::Identifier(name, state), Token::Curly(curly, _), ..] => - { - match keyword.as_str() { - "struct" => ast.push(Ast::Struct( - vars.new_struct(name.clone(), state.clone(), String::from("")), - curly.clone(), - )), - _ => {} - } - drain += 2; - } - [Token::SKeyword(keyword, _), Token::Curly(curly, _), ..] => { - match keyword.as_str() { - "rust" => ast.push(Ast::Rust(curly.clone())), - _ => {} - } - drain += 1; - } - x => { - ast.push(Ast::Single(x[0].clone())); - //let estate = extract_values(x[0].clone()).1; - //if !pcon.contains(&(estate.line, estate.column)) { - // root.problems.push(ProblemCap::Error(Problem { - // problem_msg: format!("Invalid placement"), - // problem_type: ProblemType::SyntaxError, - // state: estate, - // })); - // pcon.push((root.state.line, root.state.column)); - //} - } - } - tokens.drain(0..drain); - } - ast } diff --git a/src/transpiler.rs b/src/transpiler.rs index 953c79c..00c7b11 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,24 +1,24 @@ use crate::{ - parser::{self, extract_ast, extract_values, Ast}, - utils::{ProblemCap, VariableType, Variables}, + parser::{self, Rule}, + utils::{ProblemCap, Variables}, }; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct State { pub line: u32, pub column: u32, pub file: Option, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct Transpiler { pub matched_vars: Variables, pub problems: Vec, pub state: State, pub inject: Inject, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct Inject { pub state: State, pub inject: bool, @@ -54,71 +54,72 @@ impl Default for Transpiler { impl Transpiler { pub fn transpile(&mut self, code: String, indent: usize, vars: &mut Variables) -> String { - let ast = parser::parse(code, vars, &mut self.state.clone(), self); + // args: code, vars, &mut self.state.clone(), self + let ast = parser::parse(code, Rule::top_expr); let mut res = String::new(); if indent > 0 { res += " ".repeat(indent * 2).as_str(); } - for a in ast { - let astval = extract_ast(a.clone()); - if self.inject.inject { - for val in astval { - if val.contains("list_vx") { - for (name, var) in vars.clone().iter_mut() { - if self.inject.state.line > var.state.line - || var.vtype != VariableType::Var - { - self.matched_vars.vars.insert(name.clone(), var.clone()); - } - } - } - } - } - match a { - Ast::Variable(var_type, var_name) => { - res += format!("let mut {}: {}", var_name, var_type).as_str(); - } - Ast::Function(var_type, var_name, round, curly) => { - res += format!( - "fn {}({}) -> {} {}\n{}{}\n", - var_name, - round, - var_type, - "{", - self.transpile(curly, indent + 1, &mut vars.clone()), - "}" - ) - .as_str(); - } - Ast::Struct(name, curly) => { - res += format!( - "struct {} {}\n{}{}\n", - name, - "{", - self.transpile(curly, indent + 1, &mut vars.clone()), - "}" - ) - .as_str() - } - Ast::Rust(rs) => { - res += "{"; - res += rs.as_str(); - res += "}"; - } - Ast::Single(x) => { - println!("{:?}", x); - let vals = extract_values(x); - match vals.0 { - 2 => res += vars.get_var(vals.1, self, vals.2).as_str(), - 3 => res += format!("({})", vals.1).as_str(), - 8 => res += vals.1.as_str(), - _ => { - res += vals.1.as_str(); - } - } - } - } - } + // for a in ast { + // let astval = extract_ast(a.clone()); + // if self.inject.inject { + // for val in astval { + // if val.contains("list_vx") { + // for (name, var) in vars.clone().iter_mut() { + // if self.inject.state.line > var.state.line + // || var.vtype != VariableType::Var + // { + // self.matched_vars.vars.insert(name.clone(), var.clone()); + // } + // } + // } + // } + // } + // match a { + // Ast::Variable(var_type, var_name) => { + // res += format!("let mut {}: {}", var_name, var_type).as_str(); + // } + // Ast::Function(var_type, var_name, round, curly) => { + // res += format!( + // "fn {}({}) -> {} {}\n{}{}\n", + // var_name, + // round, + // var_type, + // "{", + // self.transpile(curly, indent + 1, &mut vars.clone()), + // "}" + // ) + // .as_str(); + // } + // Ast::Struct(name, curly) => { + // res += format!( + // "struct {} {}\n{}{}\n", + // name, + // "{", + // self.transpile(curly, indent + 1, &mut vars.clone()), + // "}" + // ) + // .as_str() + // } + // Ast::Rust(rs) => { + // res += "{"; + // res += rs.as_str(); + // res += "}"; + // } + // Ast::Single(x) => { + // println!("{:?}", x); + // let vals = extract_values(x); + // match vals.0 { + // 2 => res += vars.get_var(vals.1, self, vals.2).as_str(), + // 3 => res += format!("({})", vals.1).as_str(), + // 8 => res += vals.1.as_str(), + // _ => { + // res += vals.1.as_str(); + // } + // } + // } + // } + // } if indent > 0 { res += "\n"; res += " ".repeat((indent - 1) * 2).as_str(); diff --git a/src/wyst.pest b/src/wyst.pest new file mode 100644 index 0000000..d6e9e37 --- /dev/null +++ b/src/wyst.pest @@ -0,0 +1,58 @@ +WHITESPACE = _{ " " | "\t" | "\n" } + +// [literals] +round = { "(" ~ (expr)* ~ ")" } +curly = { "{" ~ (code_expr)* ~ "}" } +escape = { "\\" ~ ANY } +raw_string = { (!("\\" | "\"") ~ ANY)+ } +string = { "\"" ~ (raw_string | escape )* ~ "\"" } +char = { "'" ~ (escape | ANY) ~ "'" } +bool = @{"true" | "false"} +semicolon = {";"} + +// [numbers] +hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*} +float = @{ ('0'..'9')* ~ "." ~ ('0'..'9')+ } +int = @{ '0'..'9'+ } + +// [identifiers] +identifier = @{ !(hex|float|int) ~ ("_" | 'a'..'z' | 'a'..'z') ~ ( "_" | 'a'..'z' | 'a'..'z' | int )* } + +// [definitions] +var_def = { identifier ~ identifier } +var_def_set = { var_def ~ "=" ~ expr ~ semicolon } +func_def = { identifier ~ identifier ~ round ~ curly } + +expr = {( + round | + curly | + char | + hex | + float | + int | + bool | + identifier | + string | + semicolon +)+} + +code_expr = {( + round | + curly | + char | + var_def_set | + (var_def ~ semicolon) | + hex | + float | + int | + bool | + // identifier | + string | + semicolon +)+} + +top_expr = { + ( + func_def + )+ +} \ No newline at end of file From 9e5079151bd3377486701fceafcb223e203b048a Mon Sep 17 00:00:00 2001 From: Leo dev Date: Thu, 11 Jul 2024 18:02:53 +0200 Subject: [PATCH 17/21] fixed bugs --- src/parser.rs | 6 +++--- src/wyst.pest | 31 +++++++++++++------------------ 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index d161d4a..6625ca9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -9,9 +9,9 @@ pub fn parse(input: String, rule: Rule) { match WystParser::parse(rule, &input) { Ok(parsed) => { for pair in parsed { - for inner in pair.into_inner() { - println!("{:?}", inner.into_inner()) - } + println!("---------START--------"); + println!("{:?}", pair); + println!("---------END--------"); } // println!("{:#?}", parsed); } diff --git a/src/wyst.pest b/src/wyst.pest index d6e9e37..34386e4 100644 --- a/src/wyst.pest +++ b/src/wyst.pest @@ -1,6 +1,10 @@ WHITESPACE = _{ " " | "\t" | "\n" } + // [literals] +filepath = { ("/" | identifier | "-" | "." )+ } +include = { "#" ~ "include" ~ "\"" ~ filepath ~ "\"" } +include_global = { "#" ~ "include" ~ "<" ~ filepath ~ ">" } round = { "(" ~ (expr)* ~ ")" } curly = { "{" ~ (code_expr)* ~ "}" } escape = { "\\" ~ ANY } @@ -23,7 +27,7 @@ var_def = { identifier ~ identifier } var_def_set = { var_def ~ "=" ~ expr ~ semicolon } func_def = { identifier ~ identifier ~ round ~ curly } -expr = {( +expr = { round | curly | char | @@ -32,27 +36,18 @@ expr = {( int | bool | identifier | - string | - semicolon -)+} + string +} -code_expr = {( - round | - curly | - char | +code_expr = { var_def_set | - (var_def ~ semicolon) | - hex | - float | - int | - bool | - // identifier | - string | - semicolon -)+} + (var_def ~ semicolon) +} top_expr = { ( - func_def + func_def | + include | + include_global )+ } \ No newline at end of file From 023ada1506a90e198a5cb881a7cfa6fe9a677e3b Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sun, 14 Jul 2024 18:13:08 +0200 Subject: [PATCH 18/21] working transpiler --- Cargo.toml | 2 +- src/compiler.rs | 32 +++---- src/main.rs | 2 +- src/parser.rs | 22 ----- src/transpiler.rs | 139 ++++++++++++++-------------- src/utils.rs | 228 +--------------------------------------------- src/wyst.pest | 30 +++--- 7 files changed, 108 insertions(+), 347 deletions(-) delete mode 100644 src/parser.rs diff --git a/Cargo.toml b/Cargo.toml index 51411da..e2ca43b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,5 @@ lsp-types = "0.97.0" zip = "2.1.3" dirs = "5.0.1" pest = "2" -pest_derive = "2" +pest_derive = "2.1" clap = "3" \ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index 27714b7..510e5a7 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -2,7 +2,7 @@ use std::{fs, path::Path, process::Command}; use crate::{ transpiler::{State, Transpiler}, - utils::{Problem, ProblemCap, ProblemType, Variables}, + utils::{Problem, ProblemCap, ProblemType}, }; pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 { @@ -10,23 +10,23 @@ pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 { let mut trsp = Transpiler { ..Default::default() }; - let mut vars = Variables::new(); if let Ok(file_contents) = fs::read_to_string(input_file) { - let mut output_code = trsp.transpile(file_contents, 0, &mut vars); + let output_code = trsp.transpile_code(file_contents, 0); + println!("{output_code}"); if is_main { - output_code += "fn main() {"; - output_code += vars - .get_var( - "main".to_string(), - &mut trsp, - State { - line: 0, - column: 0, - file: None, - }, - ) - .as_str(); - output_code += "();}"; + // output_code += "fn main() {"; + // output_code += vars + // .get_var( + // "main".to_string(), + // &mut trsp, + // State { + // line: 0, + // column: 0, + // file: None, + // }, + // ) + // .as_str(); + // output_code += "();}"; } if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {} } else { diff --git a/src/main.rs b/src/main.rs index 0fe5c31..d61a7ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ use std::{fs, process}; mod compiler; -mod parser; mod transpiler; mod utils; + use clap::{App, Arg}; use compiler::{compile_rust, transpile}; diff --git a/src/parser.rs b/src/parser.rs deleted file mode 100644 index 6625ca9..0000000 --- a/src/parser.rs +++ /dev/null @@ -1,22 +0,0 @@ -use pest::Parser; -use pest_derive::Parser; - -#[derive(Parser)] -#[grammar = "wyst.pest"] -pub struct WystParser; - -pub fn parse(input: String, rule: Rule) { - match WystParser::parse(rule, &input) { - Ok(parsed) => { - for pair in parsed { - println!("---------START--------"); - println!("{:?}", pair); - println!("---------END--------"); - } - // println!("{:#?}", parsed); - } - Err(e) => { - println!("Ok: {}", e); - } - } -} diff --git a/src/transpiler.rs b/src/transpiler.rs index 00c7b11..9d1c307 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,9 +1,14 @@ -use crate::{ - parser::{self, Rule}, - utils::{ProblemCap, Variables}, -}; +use pest::iterators::{Pair, Pairs}; +use crate::utils::{ProblemCap}; use serde::{Deserialize, Serialize}; +// The Parser +use pest::Parser; +use pest_derive::Parser; +#[derive(Parser)] +#[grammar = "wyst.pest"] +pub struct WystParser; + #[derive(Deserialize, Serialize, Debug, Clone)] pub struct State { pub line: u32, @@ -13,7 +18,6 @@ pub struct State { #[derive(Deserialize, Serialize, Debug, Clone)] pub struct Transpiler { - pub matched_vars: Variables, pub problems: Vec, pub state: State, pub inject: Inject, @@ -40,7 +44,6 @@ impl Default for Inject { impl Default for Transpiler { fn default() -> Self { Transpiler { - matched_vars: Variables::new(), inject: Inject::default(), problems: Vec::new(), state: State { @@ -52,74 +55,72 @@ impl Default for Transpiler { } } +pub fn to_indexable(pairs: Pairs) -> Vec> { + let mut arr: Vec> = Vec::new(); + for pair in pairs {arr.push(pair)} + arr + +} + impl Transpiler { - pub fn transpile(&mut self, code: String, indent: usize, vars: &mut Variables) -> String { - // args: code, vars, &mut self.state.clone(), self - let ast = parser::parse(code, Rule::top_expr); + pub fn transpile_pairs(&mut self, pairs: Pairs) -> String { let mut res = String::new(); + for pair in pairs { + res+=self.transpile(pair).as_str(); + } + res + } + pub fn transpile(&mut self, pair: Pair) -> String { + let mut res = String::new(); + let tokens = to_indexable(pair.clone().into_inner()); + match pair.as_rule() { + Rule::func_def => { + res += format!("fn {}({}) -> {} {}", tokens[1].as_str(), + self.transpile_pairs(tokens[2].clone().into_inner()).as_str(), + tokens[0].as_str(), + self.transpile(tokens[3].clone()) + ).as_str(); + } + Rule::var_def => { + res += format!("let mut {}: {}", tokens[1].as_str(), tokens[0].as_str()).as_str(); + } + Rule::curly => { + res += "{"; + res += &self.transpile_pairs(pair.clone().into_inner()); + res += "}"; + } + Rule::code_expr => { + res += &self.transpile_pairs(pair.clone().into_inner()); + } + //TODO: use LibManager to manage the includes + Rule::include_global => {} + Rule::include => {} + + _ => { + res += " "; + res += pair.as_str(); + res += " "; + } + } + res + } + pub fn transpile_code(&mut self, code: String, indent: usize) -> String { + let mut res = String::new(); + match WystParser::parse(Rule::top_expr, &code) { + Ok(parsed) => { + for pair in parsed { + res += self.transpile_pairs(pair.into_inner()).as_str(); + } + } + Err(e) => { + // println!("err: {}", e.line()); + println!("{}", e); + } + } if indent > 0 { res += " ".repeat(indent * 2).as_str(); } - // for a in ast { - // let astval = extract_ast(a.clone()); - // if self.inject.inject { - // for val in astval { - // if val.contains("list_vx") { - // for (name, var) in vars.clone().iter_mut() { - // if self.inject.state.line > var.state.line - // || var.vtype != VariableType::Var - // { - // self.matched_vars.vars.insert(name.clone(), var.clone()); - // } - // } - // } - // } - // } - // match a { - // Ast::Variable(var_type, var_name) => { - // res += format!("let mut {}: {}", var_name, var_type).as_str(); - // } - // Ast::Function(var_type, var_name, round, curly) => { - // res += format!( - // "fn {}({}) -> {} {}\n{}{}\n", - // var_name, - // round, - // var_type, - // "{", - // self.transpile(curly, indent + 1, &mut vars.clone()), - // "}" - // ) - // .as_str(); - // } - // Ast::Struct(name, curly) => { - // res += format!( - // "struct {} {}\n{}{}\n", - // name, - // "{", - // self.transpile(curly, indent + 1, &mut vars.clone()), - // "}" - // ) - // .as_str() - // } - // Ast::Rust(rs) => { - // res += "{"; - // res += rs.as_str(); - // res += "}"; - // } - // Ast::Single(x) => { - // println!("{:?}", x); - // let vals = extract_values(x); - // match vals.0 { - // 2 => res += vars.get_var(vals.1, self, vals.2).as_str(), - // 3 => res += format!("({})", vals.1).as_str(), - // 8 => res += vals.1.as_str(), - // _ => { - // res += vals.1.as_str(); - // } - // } - // } - // } - // } + if indent > 0 { res += "\n"; res += " ".repeat((indent - 1) * 2).as_str(); diff --git a/src/utils.rs b/src/utils.rs index ad41986..169095a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,5 @@ use crate::transpiler::State; -use crate::transpiler::Transpiler; -use rand::Rng; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum ProblemType { @@ -22,227 +19,4 @@ pub struct Problem { pub problem_type: ProblemType, pub problem_msg: String, pub state: State, -} - -#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] -pub enum VariableType { - Var, - Func, - Keyword, - Struct, - Namespace, - Enum, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Variable { - pub vtype: VariableType, - pub desc: String, - pub state: State, - pub params: Variables, - pub rname: String, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Variables { - pub vars: HashMap, -} - -impl Variables { - pub fn new() -> Variables { - Variables { - vars: HashMap::from([ - ( - "void".to_string(), - Variable { - vtype: VariableType::Keyword, - desc: "".to_string(), - state: State { - line: 0, - column: 0, - file: None, - }, - params: Variables { - vars: HashMap::new(), - }, - rname: "".to_string(), - }, - ), - ( - "println".to_string(), - Variable { - vtype: VariableType::Keyword, - desc: "".to_string(), - state: State { - line: 0, - column: 0, - file: None, - }, - params: Variables { - vars: HashMap::new(), - }, - rname: "println".to_string(), - }, - ), - ]), - } - } - pub fn new_var(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Var, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - - pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Namespace, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - - pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Struct, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Enum, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - - // pub fn new_keyword(&mut self, name: String, state: State, desc: String) { - // self.vars.insert( - // name, - // Variable { - // vtype: VariableType::Keyword, - // desc, - // state, - // params: Variables { - // vars: HashMap::new(), - // }, - // rname: generate_varname(), - // }, - // ); - // } - - pub fn new_func(&mut self, name: String, state: State, desc: String) -> String { - let rname = generate_varname(); - self.vars.insert( - name, - Variable { - vtype: VariableType::Func, - desc, - state, - params: Variables { - vars: HashMap::new(), - }, - rname: rname.clone(), - }, - ); - rname - } - 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(ProblemCap::Error(Problem { - problem_type: ProblemType::VariableNotFound, - problem_msg: format!("'{}' doesn't exist", &name), - state: state, - })); - return name; - } - } - pub fn iter_mut( - &mut self, - ) -> std::collections::hash_map::IterMut<'_, std::string::String, Variable> { - self.vars.iter_mut() - } - pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> { - if !name.contains("::") { - return self.vars.get_mut(&name); - } - if let Some((x, _)) = name.split_once("::") { - println!("{x}"); - if let Some(v) = self.vars.get_mut(x) { - println!("{:?}", v); - let mut var = v; - for a in name.split("::") { - if let Some(b) = var.params.vars.get_mut(a) { - var = b; - } else { - return None; - } - } - return Some(var); - } - return None; - } - None - } - pub fn expand(&mut self, vars: Variables) { - for (x, y) in vars.vars { - self.vars.insert(x, y); - } - } -} - -pub fn generate_varname() -> String { - let mut rng = rand::thread_rng(); - let charset: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789"; - let mut result = String::with_capacity(19); - result.push('_'); - result.push('0'); - result.push('x'); - for _ in 0..14 { - let random_char = charset[rng.gen_range(0..charset.len())] as char; - result.push(random_char); - } - result -} +} \ No newline at end of file diff --git a/src/wyst.pest b/src/wyst.pest index 34386e4..b910e59 100644 --- a/src/wyst.pest +++ b/src/wyst.pest @@ -1,18 +1,20 @@ WHITESPACE = _{ " " | "\t" | "\n" } +// [chars] +comma = {","} +semicolon = {";"} // [literals] -filepath = { ("/" | identifier | "-" | "." )+ } +filepath = { ("/"|('a'..'z' | 'a'..'z' | '0'..'9' | "_" | "-" | "."))+ } include = { "#" ~ "include" ~ "\"" ~ filepath ~ "\"" } include_global = { "#" ~ "include" ~ "<" ~ filepath ~ ">" } -round = { "(" ~ (expr)* ~ ")" } +round = { "(" ~ ((expr ~ comma)* ~ expr?) ~ ")" } curly = { "{" ~ (code_expr)* ~ "}" } escape = { "\\" ~ ANY } raw_string = { (!("\\" | "\"") ~ ANY)+ } string = { "\"" ~ (raw_string | escape )* ~ "\"" } char = { "'" ~ (escape | ANY) ~ "'" } bool = @{"true" | "false"} -semicolon = {";"} // [numbers] hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*} @@ -20,14 +22,18 @@ float = @{ ('0'..'9')* ~ "." ~ ('0'..'9')+ } int = @{ '0'..'9'+ } // [identifiers] -identifier = @{ !(hex|float|int) ~ ("_" | 'a'..'z' | 'a'..'z') ~ ( "_" | 'a'..'z' | 'a'..'z' | int )* } +identifier = @{ !(hex|float|int) ~ ("." | "::" | "_" | 'a'..'z' | 'A'..'Z') ~ ( "." | "::" | "_" | 'a'..'z' | 'A'..'Z' | int )*} +def_identifier = {identifier ~ ("<" ~ ((def_identifier ~ comma)* ~ def_identifier?) ~ ">")?} // [definitions] -var_def = { identifier ~ identifier } -var_def_set = { var_def ~ "=" ~ expr ~ semicolon } -func_def = { identifier ~ identifier ~ round ~ curly } +round_def = { "(" ~ ((var_def ~ comma)* ~ var_def?) ~ ")" } +var_def = { def_identifier ~ identifier } +var_def_set = { var_def ~ "=" ~ expr } +var_set = { def_identifier ~ "=" ~ expr } +func_def = { def_identifier ~ identifier ~ round_def ~ curly } expr = { + (identifier ~ round) | round | curly | char | @@ -40,14 +46,16 @@ expr = { } code_expr = { - var_def_set | - (var_def ~ semicolon) + (var_def_set ~ semicolon) | + (var_def ~ semicolon) | + (var_set ~ semicolon) | + (expr ~ semicolon) } top_expr = { ( - func_def | include | - include_global + include_global | + func_def )+ } \ No newline at end of file From 82bb846e094933234d190c2e87c0a80727152c85 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sun, 14 Jul 2024 20:00:00 +0200 Subject: [PATCH 19/21] fixed bugs --- src/compiler.rs | 8 +++++++- src/transpiler.rs | 21 ++++++++++++++++++--- src/wyst.pest | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 510e5a7..d1d0945 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,4 +1,5 @@ use std::{fs, path::Path, process::Command}; +use std::str; use crate::{ transpiler::{State, Transpiler}, @@ -65,10 +66,15 @@ pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 { } pub fn compile_rust(exe_file: String) { - Command::new("rustc") + let output = Command::new("rustc") .arg(Path::new("build").join("main.rs")) .arg("-o") .arg(exe_file) .output() .expect("Error compiling rust: "); + if &output.stderr.len() == &0 { + println!("Compiled successfully"); + } else { + println!("{}", str::from_utf8(&output.stderr).expect("Error encoding stderr")); + } } diff --git a/src/transpiler.rs b/src/transpiler.rs index 9d1c307..687552f 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -75,9 +75,9 @@ impl Transpiler { let tokens = to_indexable(pair.clone().into_inner()); match pair.as_rule() { Rule::func_def => { - res += format!("fn {}({}) -> {} {}", tokens[1].as_str(), + res += format!("fn {}({}) -> {} {}", self.transpile(tokens[1].clone()), self.transpile_pairs(tokens[2].clone().into_inner()).as_str(), - tokens[0].as_str(), + self.transpile(tokens[0].clone()), self.transpile(tokens[3].clone()) ).as_str(); } @@ -96,6 +96,22 @@ impl Transpiler { Rule::include_global => {} Rule::include => {} + Rule::identifier => { + let ident = pair.as_str().trim(); + res+=match ident { + "void" => {"()"} + _ => {ident} + }; + } + + Rule::def_identifier => { + let ident = pair.as_str().trim(); + res+=match ident { + "void" => {"()"} + _ => {ident} + }; + } + _ => { res += " "; res += pair.as_str(); @@ -113,7 +129,6 @@ impl Transpiler { } } Err(e) => { - // println!("err: {}", e.line()); println!("{}", e); } } diff --git a/src/wyst.pest b/src/wyst.pest index b910e59..6e1ddea 100644 --- a/src/wyst.pest +++ b/src/wyst.pest @@ -57,5 +57,5 @@ top_expr = { include | include_global | func_def - )+ + )* ~ !ANY } \ No newline at end of file From 3a09288a52eb573a58017424b4fe09bfc131d7c8 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 19 Jul 2024 21:02:27 +0200 Subject: [PATCH 20/21] changes --- README.md | 12 +++--- lib/stdio.rs | 6 +++ src/compiler.rs | 37 ++++++++-------- src/main.rs | 9 ++-- src/transpiler.rs | 67 ++++++++++++++++++++++------- src/utils.rs | 106 +++++++++++++++++++++++++++++++++++++++++++++- src/wyst.pest | 26 +++++++++--- 7 files changed, 213 insertions(+), 50 deletions(-) create mode 100644 lib/stdio.rs diff --git a/README.md b/README.md index 72248c2..929a42b 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,9 @@

Wyst is a programing language that has similar syntax to C and transpiles to Rust

-<<<<<<< HEAD -# Re Write -We are re-writing the parser and transpiler due to the messy code that is very hard to expand -======= +# Hello World ```c +// main.wst #include int main() { @@ -19,7 +17,11 @@ int main() { return 0; } ``` ->>>>>>> 30ed01f (Update README.md) + +# Compile it +```bash +wyst main.wst -o +``` # Alpha We are on pure alpha. if you would like to contribute please open a new issue. diff --git a/lib/stdio.rs b/lib/stdio.rs new file mode 100644 index 0000000..2a7ac7d --- /dev/null +++ b/lib/stdio.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! printf { + ($($arg:tt)*) => { + println!($($arg)*); + }; +} \ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index d1d0945..c79f8ab 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -6,30 +6,29 @@ use crate::{ utils::{Problem, ProblemCap, ProblemType}, }; -pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 { +pub fn transpile_file(input_file: String, output_file: String, is_main: bool) -> u8 { let mut ecode: u8 = 0; let mut trsp = Transpiler { ..Default::default() }; if let Ok(file_contents) = fs::read_to_string(input_file) { - let output_code = trsp.transpile_code(file_contents, 0); - println!("{output_code}"); + let mut module_code = String::new(); + let mut output_code = String::new(); + match trsp.transpile_code(file_contents, 0) { + Ok(rcode) => output_code+=rcode.as_str(), + Err(e) => {ecode=1;println!("{e}")} + } if is_main { - // output_code += "fn main() {"; - // output_code += vars - // .get_var( - // "main".to_string(), - // &mut trsp, - // State { - // line: 0, - // column: 0, - // file: None, - // }, - // ) - // .as_str(); - // output_code += "();}"; + for module in trsp.clone().mod_manager.modules { + module_code += "mod "; + module_code += module.rs_mod.as_str(); + module_code += ";\n"; + } + } + output_code = format!("{module_code}\n{output_code}"); + if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) { + trsp.problems.append(&mut trsp.mod_manager.write()); } - if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {} } else { trsp.problems.push(ProblemCap::Error(Problem { problem_msg: "File not found".to_string(), @@ -69,11 +68,11 @@ pub fn compile_rust(exe_file: String) { let output = Command::new("rustc") .arg(Path::new("build").join("main.rs")) .arg("-o") - .arg(exe_file) + .arg(exe_file.clone()) .output() .expect("Error compiling rust: "); if &output.stderr.len() == &0 { - println!("Compiled successfully"); + println!("Compiled successfully: \x1b[34;4m{}", exe_file.clone()); } else { println!("{}", str::from_utf8(&output.stderr).expect("Error encoding stderr")); } diff --git a/src/main.rs b/src/main.rs index d61a7ea..cfaccb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,10 @@ use std::{fs, process}; - mod compiler; mod transpiler; mod utils; use clap::{App, Arg}; -use compiler::{compile_rust, transpile}; +use compiler::{compile_rust, transpile_file}; fn main() { let matches = App::new("Wyst") @@ -44,8 +43,10 @@ fn main() { let file = matches.value_of("file").unwrap().to_string(); let output = matches.value_of("output").unwrap_or("out").to_string(); if let Ok(_) = fs::create_dir("build") {} - let ecode = transpile(file, "main.rs".to_string(), true); - compile_rust(output); + let ecode = transpile_file(file, "main.rs".to_string(), true); + if ecode == 0 { + compile_rust(output); + } if !matches.is_present("build") { fs::remove_dir_all("build").expect("Error removing build"); } diff --git a/src/transpiler.rs b/src/transpiler.rs index 687552f..8718927 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,9 +1,9 @@ use pest::iterators::{Pair, Pairs}; -use crate::utils::{ProblemCap}; +use crate::utils::{ModManager, ProblemCap}; use serde::{Deserialize, Serialize}; // The Parser -use pest::Parser; +use pest::{Parser, error::Error}; use pest_derive::Parser; #[derive(Parser)] #[grammar = "wyst.pest"] @@ -16,13 +16,16 @@ pub struct State { pub file: Option, } -#[derive(Deserialize, Serialize, Debug, Clone)] +#[derive(Debug, Clone)] +#[allow(dead_code)] pub struct Transpiler { pub problems: Vec, pub state: State, pub inject: Inject, + pub mod_manager: ModManager, } -#[derive(Deserialize, Serialize, Debug, Clone)] +#[derive(Debug, Clone)] +#[allow(dead_code)] pub struct Inject { pub state: State, pub inject: bool, @@ -46,6 +49,7 @@ impl Default for Transpiler { Transpiler { inject: Inject::default(), problems: Vec::new(), + mod_manager: ModManager::new(), state: State { line: 1, column: 0, @@ -75,7 +79,7 @@ impl Transpiler { let tokens = to_indexable(pair.clone().into_inner()); match pair.as_rule() { Rule::func_def => { - res += format!("fn {}({}) -> {} {}", self.transpile(tokens[1].clone()), + res += format!("pub fn {}({}) -> {} {}\n", self.transpile(tokens[1].clone()), self.transpile_pairs(tokens[2].clone().into_inner()).as_str(), self.transpile(tokens[0].clone()), self.transpile(tokens[3].clone()) @@ -92,16 +96,29 @@ impl Transpiler { Rule::code_expr => { res += &self.transpile_pairs(pair.clone().into_inner()); } - //TODO: use LibManager to manage the includes - Rule::include_global => {} - Rule::include => {} + + Rule::include_global => { + res += "#[allow(unused_imports)]\nuse "; + res += self.mod_manager.add(tokens[0].as_str().to_string(), true).as_str(); + res += "::*;\n"; + } + Rule::include => { + res += "#[allow(unused_imports)]\nuse "; + res += self.mod_manager.add(tokens[0].as_str().to_string(), false).as_str(); + res += "::*;\n"; + } Rule::identifier => { let ident = pair.as_str().trim(); - res+=match ident { - "void" => {"()"} - _ => {ident} - }; + if self.mod_manager.macros.contains(&ident.to_string()) { + res+=ident; + res+="!"; + } else { + res+=match ident { + "void" => {"()"} + _ => {ident} + }; + } } Rule::def_identifier => { @@ -112,6 +129,26 @@ impl Transpiler { }; } + Rule::call => { + res += " "; + res += self.transpile(tokens[0].clone()).as_str(); + res += self.transpile(tokens[1].clone()).as_str(); + } + + Rule::round => { + res += "("; + res += self.transpile_pairs(pair.into_inner()).as_str(); + res += ")"; + } + + Rule::expr => { + res += self.transpile_pairs(pair.into_inner()).as_str(); + } + + Rule::expr_ => { + res += self.transpile_pairs(pair.into_inner()).as_str(); + } + _ => { res += " "; res += pair.as_str(); @@ -120,7 +157,7 @@ impl Transpiler { } res } - pub fn transpile_code(&mut self, code: String, indent: usize) -> String { + pub fn transpile_code(&mut self, code: String, indent: usize) -> Result> { let mut res = String::new(); match WystParser::parse(Rule::top_expr, &code) { Ok(parsed) => { @@ -129,7 +166,7 @@ impl Transpiler { } } Err(e) => { - println!("{}", e); + return Err(e); } } if indent > 0 { @@ -140,6 +177,6 @@ impl Transpiler { res += "\n"; res += " ".repeat((indent - 1) * 2).as_str(); } - res + Ok(res) } } diff --git a/src/utils.rs b/src/utils.rs index 169095a..740fb1b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,9 @@ -use crate::transpiler::State; +use std::fs; +use std::path::Path; +use crate::transpiler::{Rule, State, Transpiler, WystParser}; use serde::{Deserialize, Serialize}; +use dirs::home_dir; +use pest::Parser; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum ProblemType { @@ -19,4 +23,104 @@ pub struct Problem { pub problem_type: ProblemType, pub problem_msg: String, pub state: State, +} + +#[derive(Debug, Clone)] +pub struct Module { + pub rs_mod: String, + pub file_path: String, + pub code: String +} + +#[derive(Debug, Clone)] +pub struct ModManager { + pub modules: Vec, + pub macros: Vec +} + +impl ModManager { + pub fn new() -> ModManager { + ModManager {modules: Vec::new(), macros: Vec::new()} + } + pub fn check(&mut self, path: String) -> Option { + for module in self.modules.clone() { + if module.file_path == path { + return Some(module); + } + } + None + } + pub fn add(&mut self, file_path: String, global: bool) -> String { + let mut problems: Vec = Vec::new(); + let mod_name = format!("mod_{}", self.modules.len()); + let home_dirpb = home_dir().unwrap(); + let home_dir = home_dirpb.to_str().unwrap(); + let mut file_path = file_path; + if global { + let mut tmp = Path::new(home_dir).join("wyst").join("lib").join(file_path.clone()).to_str().unwrap().to_string(); + if !Path::new(&tmp).exists() { + tmp = Path::new("lib").join(file_path).to_str().unwrap().to_string(); + } + file_path = tmp; + } + if let Some(modl) = self.check(file_path.clone()) { + return modl.rs_mod; + } + if let Ok(code) = fs::read_to_string(file_path.clone()) { + self.modules.push(Module { rs_mod: mod_name.clone(), file_path: file_path.clone(), code: code.clone() }); + match file_path.rsplit_once('.').unwrap_or(("", "")).1 { + "rs" => { + match WystParser::parse(Rule::rust_code, &code) { + Ok(parsed) => { + for pair in parsed { + for p in pair.into_inner() { + if p.as_rule() == Rule::rust_macro_lint { + self.macros.push(p.into_inner().as_str().to_string()); + } + } + } + } + Err(_) => {} + } + } + _ => {} + } + } else { + problems.push(ProblemCap::Error(Problem { + problem_msg: format!("File not found '{}'", file_path), + problem_type: ProblemType::FileNotFound, + state: State { + line: 0, + column: 0, + file: None, + }, + })) + } + mod_name + } + pub fn write(&mut self) -> Vec { + let mut problems: Vec = Vec::new(); + for module in self.modules.clone() { + let file_path = module.file_path; + match file_path.rsplit_once('.').unwrap_or(("", "")).1 { + "wst" => { + let mut trsp = Transpiler { + mod_manager: self.clone(), + ..Default::default() + }; + let rust_code = trsp.transpile_code(module.code, 0).expect(""); + fs::write(Path::new("build").join((module.rs_mod+".rs").as_str()), rust_code).expect("Error writing rust file: "); + problems.append(&mut trsp.problems); + self.modules = trsp.mod_manager.modules; + } + + "rs" => { + fs::write(Path::new("build").join((module.rs_mod+".rs").as_str()), &module.code).unwrap() + } + + _ => {} + } + } + problems + } } \ No newline at end of file diff --git a/src/wyst.pest b/src/wyst.pest index 6e1ddea..ff665ab 100644 --- a/src/wyst.pest +++ b/src/wyst.pest @@ -32,8 +32,15 @@ var_def_set = { var_def ~ "=" ~ expr } var_set = { def_identifier ~ "=" ~ expr } func_def = { def_identifier ~ identifier ~ round_def ~ curly } -expr = { - (identifier ~ round) | +rust_macro_lint = { "macro_rules" ~ "!" ~ identifier } +rust_code = { (rust_macro_lint | ANY)* } + +plus = {"+"} + +call = {identifier ~ round} + +expr_ = { + call | round | curly | char | @@ -45,11 +52,18 @@ expr = { string } +expr = { + (expr_ ~ plus ~ expr_) | + expr_ +} + code_expr = { - (var_def_set ~ semicolon) | - (var_def ~ semicolon) | - (var_set ~ semicolon) | - (expr ~ semicolon) + ( + var_def_set| + var_def | + var_set | + expr + ) ~ semicolon } top_expr = { From 4b1fbb0cc56e1a223261763bcf73e6a1264f7002 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Sat, 20 Jul 2024 05:27:25 +0200 Subject: [PATCH 21/21] obfucated names and updated stdio printf --- Cargo.toml | 3 ++- lib/README.md | 4 ++++ lib/stdio.rs | 7 +++--- src/compiler.rs | 21 +++++++++++++---- src/transpiler.rs | 58 +++++++++++++++++++++++++---------------------- src/wyst.pest | 2 +- 6 files changed, 58 insertions(+), 37 deletions(-) create mode 100644 lib/README.md diff --git a/Cargo.toml b/Cargo.toml index e2ca43b..5f466cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,4 +15,5 @@ zip = "2.1.3" dirs = "5.0.1" pest = "2" pest_derive = "2.1" -clap = "3" \ No newline at end of file +clap = "3" +hex = "0.4" diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..d41d038 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,4 @@ +# Wyst stdlib + +## > [!NOTE] +> any changes made here should be documented before pushed to master diff --git a/lib/stdio.rs b/lib/stdio.rs index 2a7ac7d..1e2f3de 100644 --- a/lib/stdio.rs +++ b/lib/stdio.rs @@ -1,6 +1,7 @@ #[macro_export] -macro_rules! printf { + +macro_rules! _0x7072696e7466 { ($($arg:tt)*) => { - println!($($arg)*); + print!($($arg)*); }; -} \ No newline at end of file +} diff --git a/src/compiler.rs b/src/compiler.rs index c79f8ab..b4270d9 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,5 +1,5 @@ -use std::{fs, path::Path, process::Command}; use std::str; +use std::{fs, path::Path, process::Command}; use crate::{ transpiler::{State, Transpiler}, @@ -15,8 +15,11 @@ pub fn transpile_file(input_file: String, output_file: String, is_main: bool) -> let mut module_code = String::new(); let mut output_code = String::new(); match trsp.transpile_code(file_contents, 0) { - Ok(rcode) => output_code+=rcode.as_str(), - Err(e) => {ecode=1;println!("{e}")} + Ok(rcode) => output_code += rcode.as_str(), + Err(e) => { + ecode = 1; + println!("{e}") + } } if is_main { for module in trsp.clone().mod_manager.modules { @@ -25,7 +28,12 @@ pub fn transpile_file(input_file: String, output_file: String, is_main: bool) -> module_code += ";\n"; } } - output_code = format!("{module_code}\n{output_code}"); + output_code = format!( + "{module_code}\n{output_code}\nfn main() {}{}{}", + "{_0x", + hex::encode("main"), + "();}" + ); if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) { trsp.problems.append(&mut trsp.mod_manager.write()); } @@ -74,6 +82,9 @@ pub fn compile_rust(exe_file: String) { if &output.stderr.len() == &0 { println!("Compiled successfully: \x1b[34;4m{}", exe_file.clone()); } else { - println!("{}", str::from_utf8(&output.stderr).expect("Error encoding stderr")); + println!( + "{}", + str::from_utf8(&output.stderr).expect("Error encoding stderr") + ); } } diff --git a/src/transpiler.rs b/src/transpiler.rs index 8718927..ef83d54 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,9 +1,9 @@ -use pest::iterators::{Pair, Pairs}; use crate::utils::{ModManager, ProblemCap}; +use pest::iterators::{Pair, Pairs}; use serde::{Deserialize, Serialize}; // The Parser -use pest::{Parser, error::Error}; +use pest::{error::Error, Parser}; use pest_derive::Parser; #[derive(Parser)] #[grammar = "wyst.pest"] @@ -61,16 +61,17 @@ impl Default for Transpiler { pub fn to_indexable(pairs: Pairs) -> Vec> { let mut arr: Vec> = Vec::new(); - for pair in pairs {arr.push(pair)} + for pair in pairs { + arr.push(pair) + } arr - } impl Transpiler { pub fn transpile_pairs(&mut self, pairs: Pairs) -> String { let mut res = String::new(); for pair in pairs { - res+=self.transpile(pair).as_str(); + res += self.transpile(pair).as_str(); } res } @@ -79,11 +80,15 @@ impl Transpiler { let tokens = to_indexable(pair.clone().into_inner()); match pair.as_rule() { Rule::func_def => { - res += format!("pub fn {}({}) -> {} {}\n", self.transpile(tokens[1].clone()), - self.transpile_pairs(tokens[2].clone().into_inner()).as_str(), - self.transpile(tokens[0].clone()), - self.transpile(tokens[3].clone()) - ).as_str(); + res += format!( + "pub fn {}({}) -> {} {}\n", + self.transpile(tokens[1].clone()), + self.transpile_pairs(tokens[2].clone().into_inner()) + .as_str(), + self.transpile(tokens[0].clone()), + self.transpile(tokens[3].clone()) + ) + .as_str(); } Rule::var_def => { res += format!("let mut {}: {}", tokens[1].as_str(), tokens[0].as_str()).as_str(); @@ -99,36 +104,35 @@ impl Transpiler { Rule::include_global => { res += "#[allow(unused_imports)]\nuse "; - res += self.mod_manager.add(tokens[0].as_str().to_string(), true).as_str(); + res += self + .mod_manager + .add(tokens[0].as_str().to_string(), true) + .as_str(); res += "::*;\n"; } Rule::include => { res += "#[allow(unused_imports)]\nuse "; - res += self.mod_manager.add(tokens[0].as_str().to_string(), false).as_str(); + res += self + .mod_manager + .add(tokens[0].as_str().to_string(), false) + .as_str(); res += "::*;\n"; } - Rule::identifier => { + Rule::identifier | Rule::def_identifier => { let ident = pair.as_str().trim(); - if self.mod_manager.macros.contains(&ident.to_string()) { - res+=ident; - res+="!"; + let ident_rs = format!("_0x{}", hex::encode(ident.as_bytes())); + if self.mod_manager.macros.contains(&ident_rs) { + res += ident_rs.as_str(); + res += "!"; } else { - res+=match ident { - "void" => {"()"} - _ => {ident} + res += match ident { + "void" => "()", + _ => ident_rs.as_str(), }; } } - Rule::def_identifier => { - let ident = pair.as_str().trim(); - res+=match ident { - "void" => {"()"} - _ => {ident} - }; - } - Rule::call => { res += " "; res += self.transpile(tokens[0].clone()).as_str(); diff --git a/src/wyst.pest b/src/wyst.pest index ff665ab..761a618 100644 --- a/src/wyst.pest +++ b/src/wyst.pest @@ -72,4 +72,4 @@ top_expr = { include_global | func_def )* ~ !ANY -} \ No newline at end of file +}