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"
|
version = "0.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"owo-colors",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -199,6 +200,12 @@ version = "1.16.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.47"
|
version = "1.0.47"
|
||||||
|
@ -7,3 +7,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4.23"
|
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 utils;
|
||||||
mod scanner;
|
mod scanner;
|
||||||
mod lex_error;
|
|
||||||
use super::token::{self, Token};
|
use super::token::{self, Token};
|
||||||
use lex_error::LexError;
|
use crate::error_handling::{MistiError, LexError};
|
||||||
|
|
||||||
type Chars = Vec<char>;
|
type Chars = Vec<char>;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ pub enum LexResult {
|
|||||||
|
|
||||||
|
|
||||||
/// Scans and returns all the tokens in the input String
|
/// 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 chars: Vec<char> = input.chars().into_iter().collect();
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
let mut current_pos: usize = 0;
|
let mut current_pos: usize = 0;
|
||||||
@ -48,7 +48,9 @@ pub fn get_tokens(input: &String) -> Result<Vec<Token>, LexError> {
|
|||||||
LexResult::None(next_pos) => {
|
LexResult::None(next_pos) => {
|
||||||
current_pos = 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::{
|
use crate::lexic::{
|
||||||
token::{self, Token},
|
token::{self, Token},
|
||||||
utils, LexResult, lex_error::LexError,
|
utils, LexResult,
|
||||||
};
|
};
|
||||||
|
use crate::error_handling::LexError;
|
||||||
|
|
||||||
/// Function to scan a number
|
/// Function to scan a number
|
||||||
///
|
///
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::lexic::{
|
use crate::lexic::{
|
||||||
token,
|
token,
|
||||||
utils, LexResult, lex_error::LexError,
|
utils, LexResult,
|
||||||
};
|
};
|
||||||
|
use crate::error_handling::LexError;
|
||||||
|
|
||||||
/// Function to scan a string
|
/// Function to scan a string
|
||||||
///
|
///
|
||||||
|
14
src/main.rs
14
src/main.rs
@ -1,15 +1,25 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use chrono::{prelude::Utc, Datelike};
|
use chrono::{prelude::Utc, Datelike};
|
||||||
|
|
||||||
|
// Module to handle the repl and its compilation
|
||||||
mod repl;
|
mod repl;
|
||||||
mod syntax;
|
// Defines the types of tokens and provides functions to create them
|
||||||
mod lexic;
|
|
||||||
mod token;
|
mod token;
|
||||||
|
// Module to handle lexical analysis
|
||||||
|
mod syntax;
|
||||||
|
// Module to handle syntactic analysis
|
||||||
|
mod lexic;
|
||||||
|
// Module to handle semantic analysis
|
||||||
mod semantic;
|
mod semantic;
|
||||||
|
// Defines the AST
|
||||||
mod ast_types;
|
mod ast_types;
|
||||||
|
// Defines the Symbol table and operations within
|
||||||
mod symbol_table;
|
mod symbol_table;
|
||||||
|
// Transforms an AST to JS
|
||||||
mod codegen;
|
mod codegen;
|
||||||
|
|
||||||
|
mod error_handling;
|
||||||
|
|
||||||
const VERSION: &str = "0.0.1";
|
const VERSION: &str = "0.0.1";
|
||||||
|
|
||||||
fn get_copyright() -> String {
|
fn get_copyright() -> String {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
|
use crate::error_handling::PrintableError;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
|
|
||||||
@ -10,14 +11,15 @@ use super::codegen;
|
|||||||
|
|
||||||
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
||||||
fn compile(input: &String) {
|
fn compile(input: &String) {
|
||||||
let _tokens = lexic::get_tokens(input);
|
let tokens = lexic::get_tokens(input);
|
||||||
|
|
||||||
match _tokens {
|
match tokens {
|
||||||
Ok(tokens) => {
|
Ok(tokens) => {
|
||||||
build_ast(tokens);
|
build_ast(tokens);
|
||||||
},
|
},
|
||||||
Err(error) => {
|
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