From 1b1415e06cb815e2341eb1191d6636a9795e45ea Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 25 Mar 2023 15:31:59 +0100 Subject: [PATCH] Parse error reporting for riscv asm parser. --- src/asm_compiler/mod.rs | 3 +- src/parser/mod.rs | 61 +++-------------------------------------- src/riscv/parser.rs | 11 ++++++-- src/utils.rs | 56 +++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/asm_compiler/mod.rs b/src/asm_compiler/mod.rs index d41169856..3deb8e3f6 100644 --- a/src/asm_compiler/mod.rs +++ b/src/asm_compiler/mod.rs @@ -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>, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7055ed55f..0b96fb597 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -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> { 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> { powdr::ASMFileParser::new() .parse(input) - .map_err(|err| handle_error(err, file_name, input)) -} - -fn handle_error<'a>( - err: lalrpop_util::ParseError, - 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)] diff --git a/src/riscv/parser.rs b/src/riscv/parser.rs index a57761542..c56d6d815 100644 --- a/src/riscv/parser.rs +++ b/src/riscv/parser.rs @@ -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 { .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() } diff --git a/src/utils.rs b/src/utils.rs index ddae29a35..55e31bc2a 100644 --- a/src/utils.rs +++ b/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, + 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};