1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
pub mod lower; pub mod parser; pub mod tokens; use lalrpop_util::ParseError; type Error<T> = ParseError<usize, T, String>; pub fn make_error( script: &str, unexpected: &str, line_number: usize, column_number: usize, ) -> String { format!( "{WS} | {line_number} | {line} {WS} | {underline} {WS} | {WS} = unexpected `{unexpected}`", WS = " ".repeat(line_number.to_string().len()), line_number = line_number, line = script.lines().nth(line_number - 1).unwrap(), underline = format!( "{}^{}", " ".repeat(column_number), "-".repeat(unexpected.len() - 1) ), unexpected = unexpected ) } fn get_line(script: &str, location: usize) -> (usize, String, usize) { let line_number = script[..location + 1].lines().count(); let line = match script.lines().nth(line_number - 1) { Some(line) => line, None => { let lines = script.lines().collect::<Vec<&str>>(); lines[lines.len() - 1] } }; let column = { let mut current_column = 0; let location = 0; for ch in script[..location].chars() { current_column += 1; if ch == '\n' { current_column = 0; } } current_column }; (line_number, String::from(line), column as usize) } pub fn format_error<T: core::fmt::Debug>(script: &str, err: Error<T>) -> String { match err { Error::InvalidToken { location } => { let (line_number, line, column) = get_line(script, location); make_error(script, &line, line_number, column) } Error::UnrecognizedEOF { location, .. } => { let (line_number, line, _) = get_line(script, location); make_error(script, "EOF", line_number, line.len()) } Error::UnrecognizedToken { token, .. } => { let start = token.0; let end = token.2; let (line_number, _, column) = get_line(script, start); let unexpected = &script[start..end]; make_error(script, unexpected, line_number, column) } Error::ExtraToken { token } => { let start = token.0; let end = token.2; let (line_number, _, column) = get_line(script, start); let unexpected = &script[start..end]; make_error(script, unexpected, line_number, column) } Error::User { error } => format!( " |\n? | {}\n | {}\n |\n = unexpected compiling error", error, format!("^{}", "-".repeat(error.len() - 1)) ), } }