Merge pull request #110 from chriseth/riscv_error_reporting

Parse error reporting for riscv asm parser.
This commit is contained in:
chriseth
2023-03-25 15:37:21 +01:00
committed by GitHub
4 changed files with 71 additions and 60 deletions

View File

@@ -2,9 +2,10 @@ use std::collections::{BTreeMap, HashMap};
use crate::number::AbstractNumberType;
use crate::number::DegreeType;
use crate::parser;
use crate::parser::asm_ast::*;
use crate::parser::ast::*;
use crate::parser::{self, ParseError};
use crate::utils::ParseError;
pub fn compile<'a>(
file_name: Option<&str>,

View File

@@ -1,9 +1,7 @@
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use lalrpop_util::*;
use crate::utils::{handle_parse_error, ParseError};
pub mod asm_ast;
pub mod ast;
pub mod display;
@@ -14,32 +12,10 @@ lalrpop_mod!(
"/parser/powdr.rs"
);
#[derive(Debug)]
pub struct ParseError<'a> {
start: usize,
end: usize,
file_name: String,
contents: &'a str,
message: String,
}
impl<'a> ParseError<'a> {
pub fn output_to_stderr(&self) {
let config = term::Config::default();
let mut files = SimpleFiles::new();
let file_id = files.add(&self.file_name, self.contents);
let diagnostic = Diagnostic::error()
.with_message(&self.message)
.with_labels(vec![Label::primary(file_id, self.start..self.end)]);
let mut writer = StandardStream::stderr(ColorChoice::Always);
term::emit(&mut writer, &config, &files, &diagnostic).unwrap()
}
}
pub fn parse<'a>(file_name: Option<&str>, input: &'a str) -> Result<ast::PILFile, ParseError<'a>> {
powdr::PILFileParser::new()
.parse(input)
.map_err(|err| handle_error(err, file_name, input))
.map_err(|err| handle_parse_error(err, file_name, input))
}
pub fn parse_asm<'a>(
@@ -48,36 +24,7 @@ pub fn parse_asm<'a>(
) -> Result<asm_ast::ASMFile, ParseError<'a>> {
powdr::ASMFileParser::new()
.parse(input)
.map_err(|err| handle_error(err, file_name, input))
}
fn handle_error<'a>(
err: lalrpop_util::ParseError<usize, lexer::Token, &str>,
file_name: Option<&str>,
input: &'a str,
) -> ParseError<'a> {
let (&start, &end) = match &err {
lalrpop_util::ParseError::InvalidToken { location } => (location, location),
lalrpop_util::ParseError::UnrecognizedEOF {
location,
expected: _,
} => (location, location),
lalrpop_util::ParseError::UnrecognizedToken {
token: (start, _, end),
expected: _,
} => (start, end),
lalrpop_util::ParseError::ExtraToken {
token: (start, _, end),
} => (start, end),
lalrpop_util::ParseError::User { error: _ } => (&0, &0),
};
ParseError {
start,
end,
file_name: file_name.unwrap_or("input").to_string(),
contents: input,
message: format!("{err}"),
}
.map_err(|err| handle_parse_error(err, file_name, input))
}
#[cfg(test)]

View File

@@ -3,6 +3,8 @@ use std::fmt::{self, Display};
use lalrpop_util::*;
use crate::utils::handle_parse_error;
lalrpop_mod!(
#[allow(clippy::all)]
riscv_asm,
@@ -72,8 +74,13 @@ pub fn parse_asm(input: &str) -> Vec<Statement> {
.map(|l| l.trim())
.filter(|l| !l.is_empty())
.flat_map(|line| {
riscv_asm::MaybeStatementParser::new().parse(line).unwrap()
//.map_err(|err| handle_error(err, file_name, input))
riscv_asm::MaybeStatementParser::new()
.parse(line)
.map_err(|err| {
handle_parse_error(err, None, line).output_to_stderr();
panic!("RISCV assembly parse error");
})
.unwrap()
})
.collect()
}

View File

@@ -23,6 +23,62 @@ pub fn indent(input: &str, indentation: &str) -> String {
}
}
#[derive(Debug)]
pub struct ParseError<'a> {
start: usize,
end: usize,
file_name: String,
contents: &'a str,
message: String,
}
impl<'a> ParseError<'a> {
pub fn output_to_stderr(&self) {
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
let config = term::Config::default();
let mut files = SimpleFiles::new();
let file_id = files.add(&self.file_name, self.contents);
let diagnostic = Diagnostic::error()
.with_message(&self.message)
.with_labels(vec![Label::primary(file_id, self.start..self.end)]);
let mut writer = StandardStream::stderr(ColorChoice::Always);
term::emit(&mut writer, &config, &files, &diagnostic).unwrap()
}
}
pub fn handle_parse_error<'a>(
err: lalrpop_util::ParseError<usize, lalrpop_util::lexer::Token, &str>,
file_name: Option<&str>,
input: &'a str,
) -> ParseError<'a> {
let (&start, &end) = match &err {
lalrpop_util::ParseError::InvalidToken { location } => (location, location),
lalrpop_util::ParseError::UnrecognizedEOF {
location,
expected: _,
} => (location, location),
lalrpop_util::ParseError::UnrecognizedToken {
token: (start, _, end),
expected: _,
} => (start, end),
lalrpop_util::ParseError::ExtraToken {
token: (start, _, end),
} => (start, end),
lalrpop_util::ParseError::User { error: _ } => (&0, &0),
};
ParseError {
start,
end,
file_name: file_name.unwrap_or("input").to_string(),
contents: input,
message: format!("{err}"),
}
}
#[cfg(test)]
mod test {
use super::{compute_line_starts, offset_to_line};