Change error type

This commit is contained in:
dalance 2020-01-23 16:36:28 +09:00
parent 94de205459
commit fde27fe7c2
7 changed files with 64 additions and 120 deletions

View File

@ -2,6 +2,7 @@
## [Unreleased](https://github.com/dalance/sv-parser/compare/v0.4.20...Unreleased) - ReleaseDate ## [Unreleased](https://github.com/dalance/sv-parser/compare/v0.4.20...Unreleased) - ReleaseDate
* [Changed] from `sv-parser-error::ErrorKind` to `sv-parser-error::Error`
* [Changed] Refine parse_sv -t option * [Changed] Refine parse_sv -t option
* [Added] Display trait of SyntaxTree * [Added] Display trait of SyntaxTree

View File

@ -14,4 +14,4 @@ edition = "2018"
disable-tag = true disable-tag = true
[dependencies] [dependencies]
failure = "0.1.5" thiserror = "1.0"

View File

@ -1,88 +1,35 @@
use failure::{Backtrace, Context, Fail};
use std::fmt;
use std::fmt::Display;
use std::io::Error as IOError;
use std::path::PathBuf; use std::path::PathBuf;
use thiserror::Error;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#[derive(Fail, Debug)] #[derive(Error, Debug)]
pub enum ErrorKind { pub enum Error {
#[fail(display = "IO error")] #[error("IO error")]
Io, Io(#[from] std::io::Error),
#[fail(display = "File error: {:?}", _0)] #[error("File error: {path:?}")]
File(PathBuf), File {
#[fail(display = "Include error")] #[source]
Include, source: std::io::Error,
#[fail(display = "Parse error: {:?}", _0)] path: PathBuf,
},
#[error("Include error")]
Include {
#[from]
source: Box<Error>,
},
#[error("Parse error: {0:?}")]
Parse(Option<(PathBuf, usize)>), Parse(Option<(PathBuf, usize)>),
#[fail(display = "Preprocess error")] #[error("Preprocess error")]
Preprocess, Preprocess,
#[fail(display = "Define argument not found: {}", _0)] #[error("Define argument not found: {0}")]
DefineArgNotFound(String), DefineArgNotFound(String),
#[fail(display = "Define not found: {}", _0)] #[error("Define not found: {0}")]
DefineNotFound(String), DefineNotFound(String),
#[fail(display = "Define must have argument")] #[error("Define must have argument")]
DefineNoArgs, DefineNoArgs,
#[fail(display = "Exceed recursive limit")] #[error("Exceed recursive limit")]
ExceedRecursiveLimit, ExceedRecursiveLimit,
#[fail(display = "Include line can't have other items")] #[error("Include line can't have other items")]
IncludeLine, IncludeLine,
} }
// -----------------------------------------------------------------------------
#[derive(Debug)]
pub struct Error {
inner: Context<ErrorKind>,
}
impl Fail for Error {
fn cause(&self) -> Option<&dyn Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
impl Error {
pub fn new(inner: Context<ErrorKind>) -> Error {
Error { inner }
}
pub fn kind(&self) -> &ErrorKind {
self.inner.get_context()
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
inner: Context::new(kind),
}
}
}
impl From<Context<ErrorKind>> for Error {
fn from(inner: Context<ErrorKind>) -> Error {
Error { inner }
}
}
// -----------------------------------------------------------------------------
impl From<IOError> for Error {
fn from(error: IOError) -> Error {
Error {
inner: error.context(ErrorKind::Io),
}
}
}

View File

@ -18,7 +18,6 @@ default = []
trace = ["sv-parser-parser/trace"] trace = ["sv-parser-parser/trace"]
[dependencies] [dependencies]
failure = "0.1.5"
nom = "5.0.0" nom = "5.0.0"
nom-greedyerror = "0.1.0" nom-greedyerror = "0.1.0"
sv-parser-error = {version = "^0.4.20", path = "../sv-parser-error"} sv-parser-error = {version = "^0.4.20", path = "../sv-parser-error"}

View File

@ -1,5 +1,4 @@
use crate::range::Range; use crate::range::Range;
use failure::ResultExt;
use nom::combinator::all_consuming; use nom::combinator::all_consuming;
use nom_greedyerror::error_position; use nom_greedyerror::error_position;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
@ -7,7 +6,7 @@ use std::convert::TryInto;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use sv_parser_error::{Error, ErrorKind}; use sv_parser_error::Error;
use sv_parser_parser::{pp_parser, Span, SpanInfo}; use sv_parser_parser::{pp_parser, Span, SpanInfo};
use sv_parser_syntaxtree::{ use sv_parser_syntaxtree::{
IncludeCompilerDirective, Locate, NodeEvent, RefNode, SourceDescription, TextMacroUsage, IncludeCompilerDirective, Locate, NodeEvent, RefNode, SourceDescription, TextMacroUsage,
@ -120,8 +119,10 @@ pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>>(
pre_defines: &Defines, pre_defines: &Defines,
include_paths: &[U], include_paths: &[U],
) -> Result<(PreprocessedText, Defines), Error> { ) -> Result<(PreprocessedText, Defines), Error> {
let f = let f = File::open(path.as_ref()).map_err(|x| Error::File {
File::open(path.as_ref()).context(ErrorKind::File(PathBuf::from(path.as_ref())).into())?; source: x,
path: PathBuf::from(path.as_ref()),
})?;
let mut reader = BufReader::new(f); let mut reader = BufReader::new(f);
let mut s = String::new(); let mut s = String::new();
reader.read_to_string(&mut s)?; reader.read_to_string(&mut s)?;
@ -149,19 +150,19 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
let span = Span::new_extra(&s, SpanInfo::default()); let span = Span::new_extra(&s, SpanInfo::default());
let (_, pp_text) = all_consuming(pp_parser)(span).map_err(|x| match x { let (_, pp_text) = all_consuming(pp_parser)(span).map_err(|x| match x {
nom::Err::Incomplete(_) => ErrorKind::Parse(None), nom::Err::Incomplete(_) => Error::Parse(None),
nom::Err::Error(e) => { nom::Err::Error(e) => {
if let Some(pos) = error_position(&e) { if let Some(pos) = error_position(&e) {
ErrorKind::Parse(Some((PathBuf::from(path.as_ref()), pos))) Error::Parse(Some((PathBuf::from(path.as_ref()), pos)))
} else { } else {
ErrorKind::Parse(None) Error::Parse(None)
} }
} }
nom::Err::Failure(e) => { nom::Err::Failure(e) => {
if let Some(pos) = error_position(&e) { if let Some(pos) = error_position(&e) {
ErrorKind::Parse(Some((PathBuf::from(path.as_ref()), pos))) Error::Parse(Some((PathBuf::from(path.as_ref()), pos)))
} else { } else {
ErrorKind::Parse(None) Error::Parse(None)
} }
} }
})?; })?;
@ -186,7 +187,7 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
let locate: Locate = x.try_into().unwrap(); let locate: Locate = x.try_into().unwrap();
if let Some(last_include_line) = last_include_line { if let Some(last_include_line) = last_include_line {
if last_include_line == locate.line { if last_include_line == locate.line {
return Err(ErrorKind::IncludeLine.into()); return Err(Error::IncludeLine);
} }
} }
} }
@ -194,7 +195,7 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
let locate: Locate = x.try_into().unwrap(); let locate: Locate = x.try_into().unwrap();
if let Some(last_include_line) = last_include_line { if let Some(last_include_line) = last_include_line {
if last_include_line == locate.line { if last_include_line == locate.line {
return Err(ErrorKind::IncludeLine.into()); return Err(Error::IncludeLine);
} }
} }
} }
@ -361,7 +362,7 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
if let Some(last_item_line) = last_item_line { if let Some(last_item_line) = last_item_line {
if last_item_line == locate.line { if last_item_line == locate.line {
return Err(ErrorKind::IncludeLine.into()); return Err(Error::IncludeLine);
} }
} }
@ -408,7 +409,9 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
} }
} }
let (include, new_defines) = let (include, new_defines) =
preprocess(path, &defines, include_paths).context(ErrorKind::Include)?; preprocess(path, &defines, include_paths).map_err(|x| Error::Include {
source: Box::new(x),
})?;
defines = new_defines; defines = new_defines;
ret.merge(include); ret.merge(include);
} }
@ -518,7 +521,7 @@ fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
let id = identifier((&name.nodes.0).into(), &s).unwrap(); let id = identifier((&name.nodes.0).into(), &s).unwrap();
if resolve_depth > RECURSIVE_LIMIT { if resolve_depth > RECURSIVE_LIMIT {
return Err(ErrorKind::ExceedRecursiveLimit.into()); return Err(Error::ExceedRecursiveLimit);
} }
let mut actual_args = Vec::new(); let mut actual_args = Vec::new();
@ -542,7 +545,7 @@ fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
let mut arg_map = HashMap::new(); let mut arg_map = HashMap::new();
if !define.arguments.is_empty() && no_args { if !define.arguments.is_empty() && no_args {
return Err(ErrorKind::DefineNoArgs.into()); return Err(Error::DefineNoArgs);
} }
for (i, (arg, default)) in define.arguments.iter().enumerate() { for (i, (arg, default)) in define.arguments.iter().enumerate() {
@ -559,7 +562,7 @@ fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
if let Some(default) = default { if let Some(default) = default {
default default
} else { } else {
return Err(ErrorKind::DefineArgNotFound(String::from(arg)).into()); return Err(Error::DefineArgNotFound(String::from(arg)));
} }
} }
}; };
@ -606,7 +609,7 @@ fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
} else if let Some(_) = define { } else if let Some(_) = define {
Ok(None) Ok(None)
} else { } else {
Err(ErrorKind::DefineNotFound(String::from(id)).into()) Err(Error::DefineNotFound(String::from(id)))
} }
} }
@ -773,39 +776,27 @@ endmodule
#[test] #[test]
fn test7() { fn test7() {
let ret = preprocess(get_testcase("test7.sv"), &HashMap::new(), &[] as &[String]); let ret = preprocess(get_testcase("test7.sv"), &HashMap::new(), &[] as &[String]);
assert_eq!( assert_eq!(format!("{:?}", ret), "Err(ExceedRecursiveLimit)");
format!("{:?}", ret),
"Err(Error { inner: \n\nExceed recursive limit })"
);
} }
#[test] #[test]
fn test8() { fn test8() {
let ret = preprocess(get_testcase("test8.sv"), &HashMap::new(), &[] as &[String]); let ret = preprocess(get_testcase("test8.sv"), &HashMap::new(), &[] as &[String]);
assert_eq!( assert_eq!(format!("{:?}", ret), "Err(ExceedRecursiveLimit)");
format!("{:?}", ret),
"Err(Error { inner: \n\nExceed recursive limit })"
);
} }
#[test] #[test]
fn test9() { fn test9() {
let include_paths = [get_testcase("")]; let include_paths = [get_testcase("")];
let ret = preprocess(get_testcase("test9.sv"), &HashMap::new(), &include_paths); let ret = preprocess(get_testcase("test9.sv"), &HashMap::new(), &include_paths);
assert_eq!( assert_eq!(format!("{:?}", ret), "Err(IncludeLine)");
format!("{:?}", ret),
"Err(Error { inner: \n\nInclude line can\'t have other items })"
);
} }
#[test] #[test]
fn test10() { fn test10() {
let include_paths = [get_testcase("")]; let include_paths = [get_testcase("")];
let ret = preprocess(get_testcase("test10.sv"), &HashMap::new(), &include_paths); let ret = preprocess(get_testcase("test10.sv"), &HashMap::new(), &include_paths);
assert_eq!( assert_eq!(format!("{:?}", ret), "Err(IncludeLine)");
format!("{:?}", ret),
"Err(Error { inner: \n\nInclude line can\'t have other items })"
);
} }
#[test] #[test]

View File

@ -1,11 +1,12 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error as StdError;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use std::{cmp, process}; use std::{cmp, process};
use structopt::StructOpt; use structopt::StructOpt;
use sv_parser::parse_sv; use sv_parser::parse_sv;
use sv_parser_error::ErrorKind; use sv_parser_error::Error;
use sv_parser_pp::preprocess::preprocess; use sv_parser_pp::preprocess::preprocess;
#[derive(StructOpt)] #[derive(StructOpt)]
@ -54,13 +55,18 @@ fn main() {
} }
} }
Err(x) => { Err(x) => {
match x.kind() { match x {
ErrorKind::Parse(Some((origin_path, origin_pos))) => { Error::Parse(Some((origin_path, origin_pos))) => {
println!("parse failed: {:?}", path); println!("parse failed: {:?}", path);
print_parse_error(origin_path, origin_pos); print_parse_error(&origin_path, &origin_pos);
} }
x => { x => {
println!("parse failed: {:?} ({})", path, x); println!("parse failed: {:?} ({})", path, x);
let mut err = x.source();
while let Some(x) = err {
println!(" Caused by {}", x);
err = x.source();
}
} }
} }
exit = 1; exit = 1;

View File

@ -5,7 +5,7 @@ use nom_greedyerror::error_position;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
pub use sv_parser_error::{Error, ErrorKind}; pub use sv_parser_error::Error;
use sv_parser_parser::{lib_parser, sv_parser, Span, SpanInfo}; use sv_parser_parser::{lib_parser, sv_parser, Span, SpanInfo};
pub use sv_parser_pp::preprocess::{ pub use sv_parser_pp::preprocess::{
preprocess, preprocess_str, Define, DefineText, Defines, PreprocessedText, preprocess, preprocess_str, Define, DefineText, Defines, PreprocessedText,
@ -125,7 +125,7 @@ pub fn parse_sv<T: AsRef<Path>, U: AsRef<Path>>(
} else { } else {
None None
}; };
Err(ErrorKind::Parse(origin).into()) Err(Error::Parse(origin))
} }
} }
} }
@ -162,7 +162,7 @@ pub fn parse_sv_str<T: AsRef<Path>, U: AsRef<Path>>(
} else { } else {
None None
}; };
Err(ErrorKind::Parse(origin).into()) Err(Error::Parse(origin))
} }
} }
} }
@ -198,7 +198,7 @@ pub fn parse_lib<T: AsRef<Path>, U: AsRef<Path>>(
} else { } else {
None None
}; };
Err(ErrorKind::Parse(origin).into()) Err(Error::Parse(origin))
} }
} }
} }
@ -235,7 +235,7 @@ pub fn parse_lib_str<T: AsRef<Path>, U: AsRef<Path>>(
} else { } else {
None None
}; };
Err(ErrorKind::Parse(origin).into()) Err(Error::Parse(origin))
} }
} }
} }