Add functions for error handling (merge)
This commit is contained in:
parent
f28e7394e9
commit
c83cd23d49
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -172,6 +172,7 @@ name = "misti"
|
||||
version = "0.0.3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"owo-colors",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -199,6 +200,12 @@ version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
|
@ -7,3 +7,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.23"
|
||||
owo-colors = "3.5.0"
|
||||
|
102
src/error_handling/lex_error.rs
Normal file
102
src/error_handling/lex_error.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use std::collections::VecDeque;
|
||||
use super::{PrintableError, LexError};
|
||||
|
||||
impl PrintableError for LexError {
|
||||
fn get_error_str(&self, chars: &Vec<char>) -> String {
|
||||
String::from("D:")
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts a line of code from `chars`. `pos` indicates a position,
|
||||
/// from where to extract the line.
|
||||
///
|
||||
/// Ex. Given:
|
||||
/// - `input = "first line\nsecond line\nthird line"`
|
||||
/// - `pos = 15`
|
||||
///
|
||||
/// this function should return `"second line"`
|
||||
fn get_line(chars: &Vec<char>, pos: usize) -> String {
|
||||
let mut result_chars = VecDeque::<char>::new();
|
||||
|
||||
// Push chars to the front until a new line is found
|
||||
let mut before_pos = pos;
|
||||
loop {
|
||||
let current_char = chars[before_pos];
|
||||
|
||||
if current_char == '\n' {
|
||||
break;
|
||||
}
|
||||
|
||||
result_chars.push_front(current_char);
|
||||
|
||||
if before_pos == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
before_pos -= 1;
|
||||
}
|
||||
|
||||
// Push chars to the end until a new line is found
|
||||
let mut after_pos = pos + 1;
|
||||
let char_count = chars.len();
|
||||
while after_pos < char_count {
|
||||
let current_char = chars[after_pos];
|
||||
|
||||
if current_char == '\n' {
|
||||
break;
|
||||
}
|
||||
|
||||
result_chars.push_back(current_char);
|
||||
after_pos += 1;
|
||||
}
|
||||
|
||||
result_chars.iter().collect::<String>()
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::lexic;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let input = String::from("val name' = 20");
|
||||
let result = lexic::get_tokens(&input);
|
||||
|
||||
match result {
|
||||
Ok(_) => assert!(false),
|
||||
Err(err_data) => {
|
||||
let chars: Vec<char> = input.chars().into_iter().collect();
|
||||
let err_str = err_data.get_error_str(&chars);
|
||||
assert_ne!(
|
||||
"\n\
|
||||
val name' = 20\n\
|
||||
. ^\n\
|
||||
\n\
|
||||
Invalid character at line 1, pos 9",
|
||||
err_str,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_line() {
|
||||
let input = String::from("first line\nsecond line\nthird line");
|
||||
let chars: Vec<char> = input.chars().into_iter().collect();
|
||||
|
||||
let result = get_line(&chars, 15);
|
||||
|
||||
assert_eq!("second line", result);
|
||||
|
||||
|
||||
let input = String::from("val binding = 322");
|
||||
let chars: Vec<char> = input.chars().into_iter().collect();
|
||||
|
||||
let result = get_line(&chars, 6);
|
||||
|
||||
assert_eq!("val binding = 322", result);
|
||||
}
|
||||
}
|
27
src/error_handling/mod.rs
Normal file
27
src/error_handling/mod.rs
Normal file
@ -0,0 +1,27 @@
|
||||
mod lex_error;
|
||||
|
||||
pub trait PrintableError {
|
||||
fn get_error_str(&self, chars: &Vec<char>) -> String;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MistiError {
|
||||
Lex(LexError)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LexError {
|
||||
pub position: usize,
|
||||
pub reason: String,
|
||||
}
|
||||
|
||||
|
||||
impl PrintableError for MistiError {
|
||||
fn get_error_str(&self, chars: &Vec<char>) -> String {
|
||||
match self {
|
||||
Self::Lex(err) => err.get_error_str(chars)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
mod utils;
|
||||
mod scanner;
|
||||
mod lex_error;
|
||||
|
||||
use super::token::{self, Token};
|
||||
use lex_error::LexError;
|
||||
use crate::error_handling::{MistiError, LexError};
|
||||
|
||||
type Chars = Vec<char>;
|
||||
|
||||
@ -34,7 +34,7 @@ pub enum LexResult {
|
||||
|
||||
|
||||
/// Scans and returns all the tokens in the input String
|
||||
pub fn get_tokens(input: &String) -> Result<Vec<Token>, LexError> {
|
||||
pub fn get_tokens(input: &String) -> Result<Vec<Token>, MistiError> {
|
||||
let chars: Vec<char> = input.chars().into_iter().collect();
|
||||
let mut results = Vec::new();
|
||||
let mut current_pos: usize = 0;
|
||||
@ -48,7 +48,9 @@ pub fn get_tokens(input: &String) -> Result<Vec<Token>, LexError> {
|
||||
LexResult::None(next_pos) => {
|
||||
current_pos = next_pos;
|
||||
},
|
||||
LexResult::Err(reason) => return Err(reason),
|
||||
LexResult::Err(error_info) => {
|
||||
return Err(MistiError::Lex(error_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::lexic::{
|
||||
token::{self, Token},
|
||||
utils, LexResult, lex_error::LexError,
|
||||
utils, LexResult,
|
||||
};
|
||||
use crate::error_handling::LexError;
|
||||
|
||||
/// Function to scan a number
|
||||
///
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::lexic::{
|
||||
token,
|
||||
utils, LexResult, lex_error::LexError,
|
||||
utils, LexResult,
|
||||
};
|
||||
use crate::error_handling::LexError;
|
||||
|
||||
/// Function to scan a string
|
||||
///
|
||||
|
14
src/main.rs
14
src/main.rs
@ -1,15 +1,25 @@
|
||||
use std::io;
|
||||
use chrono::{prelude::Utc, Datelike};
|
||||
|
||||
// Module to handle the repl and its compilation
|
||||
mod repl;
|
||||
mod syntax;
|
||||
mod lexic;
|
||||
// Defines the types of tokens and provides functions to create them
|
||||
mod token;
|
||||
// Module to handle lexical analysis
|
||||
mod syntax;
|
||||
// Module to handle syntactic analysis
|
||||
mod lexic;
|
||||
// Module to handle semantic analysis
|
||||
mod semantic;
|
||||
// Defines the AST
|
||||
mod ast_types;
|
||||
// Defines the Symbol table and operations within
|
||||
mod symbol_table;
|
||||
// Transforms an AST to JS
|
||||
mod codegen;
|
||||
|
||||
mod error_handling;
|
||||
|
||||
const VERSION: &str = "0.0.1";
|
||||
|
||||
fn get_copyright() -> String {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::io::{self, Write};
|
||||
|
||||
use crate::error_handling::PrintableError;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::token::Token;
|
||||
|
||||
@ -10,14 +11,15 @@ use super::codegen;
|
||||
|
||||
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
||||
fn compile(input: &String) {
|
||||
let _tokens = lexic::get_tokens(input);
|
||||
let tokens = lexic::get_tokens(input);
|
||||
|
||||
match _tokens {
|
||||
match tokens {
|
||||
Ok(tokens) => {
|
||||
build_ast(tokens);
|
||||
},
|
||||
Err(error) => {
|
||||
eprintln!("Error scanning.\n{} at pos {}", error.reason, error.position)
|
||||
let chars: Vec<char> = input.chars().into_iter().collect();
|
||||
eprintln!("{}", error.get_error_str(&chars))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user