lalrpop_codespan/src/lib.rs

51 lines
2.1 KiB
Rust

use anyhow::bail;
use codespan_reporting::{
diagnostic::{Diagnostic, Label},
files::SimpleFiles,
term::{
emit,
termcolor::{ColorChoice, StandardStream},
},
};
use lalrpop_util::{lexer::Token, ParseError};
pub fn report_error<T>(
tree: Result<T, ParseError<usize, Token, &str>>,
file_name: &str,
file_contents: &str,
) -> anyhow::Result<T> {
match tree {
Ok(x) => Ok(x),
Err(e) => {
let mut err_files = SimpleFiles::new();
let err_writer = StandardStream::stderr(ColorChoice::Auto);
let err_config = codespan_reporting::term::Config::default();
let main_file_id = err_files.add(file_name, file_contents);
let emit_err = |d| emit(&mut err_writer.lock(), &err_config, &err_files, d);
let err = match e {
ParseError::InvalidToken { location } => Diagnostic::error()
.with_message("Invalid token")
.with_labels(vec![Label::primary(main_file_id, location..location + 1)]),
ParseError::UnrecognizedEOF { location, expected } => Diagnostic::error()
.with_message("Unexpected end of file")
.with_labels(vec![Label::primary(main_file_id, location..location + 1)])
.with_notes(expected.iter().map(|e| format!("Expected {}", e)).collect()),
ParseError::UnrecognizedToken { token, expected } => Diagnostic::error()
.with_message("Unrecognized token")
.with_labels(vec![Label::primary(main_file_id, token.0..token.2)])
.with_notes(expected.iter().map(|e| format!("Expected {}", e)).collect()),
ParseError::ExtraToken { token } => Diagnostic::error()
.with_message("Extra token")
.with_labels(vec![Label::primary(main_file_id, token.0..token.2)]),
ParseError::User { error } => bail!("User parse error: {}", error),
};
emit_err(&err)?;
bail!("Parse error");
}
}
}