mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-05-13 03:00:26 -04:00
Merge pull request #110 from chriseth/riscv_error_reporting
Parse error reporting for riscv asm parser.
This commit is contained in:
@@ -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>,
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
56
src/utils.rs
56
src/utils.rs
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user