better error checking

This commit is contained in:
2024-06-29 19:48:11 +02:00
parent 8cbe87d59c
commit beff172ff4
4 changed files with 70 additions and 22 deletions
+6 -2
View File
@@ -7,6 +7,10 @@ mod variable;
fn main() { fn main() {
let mut vars = Variables::new(); let mut vars = Variables::new();
let out = transpiler::Transpiler::default().transpile(r#"int x"#.to_string(), 0, &mut vars); let mut trsp = transpiler::Transpiler::default();
println!("{out}"); 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);
} }
+60 -19
View File
@@ -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)] #[derive(Clone, Debug)]
pub enum Token { pub enum Token {
Number(String), Number(String, State),
Identifier(String), Identifier(String, State),
// Curly(String), // Curly(String),
// Round(String), // Round(String),
// Square(String), // Square(String),
@@ -12,24 +18,26 @@ pub enum Ast {
Variable(String, String), 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 { match t {
1 => Token::Number(v), 1 => Token::Number(v, state),
2 => Token::Identifier(v), 2 => Token::Identifier(v, state),
_ => Token::Number(String::from("")), _ => Token::Number(String::from(""), state),
} }
} }
pub fn tokenize(code: String) -> Vec<Token> { pub fn tokenize(code: String, root: &mut Transpiler) -> Vec<Token> {
let mut code = code; let mut code = code;
let mut tokens: Vec<Token> = Vec::new(); let mut tokens: Vec<Token> = Vec::new();
let mut token_value: String = String::new(); let mut token_value: String = String::new();
let mut token_type: u32 = 0; let mut token_type: u32 = 0;
//let mut state = State { line: }
while !code.is_empty() { while !code.is_empty() {
if let Some(c) = code.chars().next() { if let Some(c) = code.chars().next() {
code.remove(0); code.remove(0);
let mut tval: char = c; let mut tval: char = c;
let mut t: u32 = 0; let mut t: u32 = 0;
root.state.column += 1;
match c { match c {
'0'..='9' => { '0'..='9' => {
if token_type == 2 { if token_type == 2 {
@@ -42,37 +50,70 @@ pub fn tokenize(code: String) -> Vec<Token> {
t = 2; t = 2;
} }
'\t' | ' ' => tval = ' ', '\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 == ' ' { 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_type = 0;
token_value = String::new(); token_value = String::new();
} }
if tval != ' ' { if tval != ' ' && tval != '\n' {
token_type = t; token_type = t;
token_value += tval.to_string().as_str(); token_value += tval.to_string().as_str();
} }
} }
} }
if token_type != 0 { 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 tokens
} }
pub fn parse(code: String, vars: &mut Variables) -> Vec<Ast> { pub fn parse(code: String, vars: &mut Variables, root: &mut Transpiler) -> Vec<Ast> {
let mut ast: Vec<Ast> = Vec::new(); let mut ast: Vec<Ast> = 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 { while tokens.len() > 0 {
let mut drain: usize = 0; let mut drain: usize = 1;
match tokens.as_slice() { 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())); ast.push(Ast::Variable(var_type.clone(), var_name.clone()));
drain += 2; drain += 1;
// vars.new_var(var_name, State {}, desc) 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); tokens.drain(0..drain);
} }
+3 -1
View File
@@ -17,6 +17,7 @@ pub struct Transpiler {
pub peek: String, pub peek: String,
// pub libmgr: LibManager, // pub libmgr: LibManager,
pub problems: Vec<Problem>, pub problems: Vec<Problem>,
pub state: State,
} }
impl Default for Transpiler { impl Default for Transpiler {
@@ -26,13 +27,14 @@ impl Default for Transpiler {
peek: String::new(), peek: String::new(),
// libmgr: LibManager::new(".".to_string()), // libmgr: LibManager::new(".".to_string()),
problems: Vec::new(), problems: Vec::new(),
state: State { line: 1, column: 0 },
} }
} }
} }
impl Transpiler { impl Transpiler {
pub fn transpile(&mut self, code: String, indent: u32, vars: &mut Variables) -> String { 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(); let mut res = String::new();
for a in ast { for a in ast {
match a { match a {
+1
View File
@@ -5,6 +5,7 @@ pub enum ProblemType {
VariableNotFound, VariableNotFound,
FileNotFound, FileNotFound,
HeaderSyntaxError, HeaderSyntaxError,
SyntaxError,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]