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)]