Change Error::Parse

This commit is contained in:
dalance 2019-10-16 17:07:51 +09:00
parent 780f13eecc
commit da55a54420
6 changed files with 118 additions and 7 deletions

View File

@ -2,6 +2,7 @@
## [Unreleased](https://github.com/dalance/sv-parser/compare/v0.1.4...Unreleased) - ReleaseDate
* [Added] parse error position
* [Fixed] spacing rule aroung text_macro_identifier
* [Fixed] cond_predicate in cond_predicate
* [Fixed] fixed_number priority in delay_value

View File

@ -15,7 +15,7 @@ pub enum ErrorKind {
#[fail(display = "Include error")]
Include,
#[fail(display = "Parse error: {:?}", _0)]
Parse(Option<usize>),
Parse(Option<(PathBuf, usize)>),
#[fail(display = "Preprocess error")]
Preprocess,
#[fail(display = "Define argument not found: {}", _0)]

View File

@ -110,8 +110,20 @@ fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
let span = Span::new_extra(&s, SpanInfo::default());
let (_, pp_text) = pp_parser(span).map_err(|x| match x {
nom::Err::Incomplete(_) => ErrorKind::Parse(None),
nom::Err::Error(e) => ErrorKind::Parse(error_position(&e)),
nom::Err::Failure(e) => ErrorKind::Parse(error_position(&e)),
nom::Err::Error(e) => {
if let Some(pos) = error_position(&e) {
ErrorKind::Parse(Some((PathBuf::from(path.as_ref()), pos)))
} else {
ErrorKind::Parse(None)
}
}
nom::Err::Failure(e) => {
if let Some(pos) = error_position(&e) {
ErrorKind::Parse(Some((PathBuf::from(path.as_ref()), pos)))
} else {
ErrorKind::Parse(None)
}
}
})?;
let mut ret = PreprocessedText::new();

View File

@ -14,6 +14,14 @@ edition = "2018"
default = []
trace = ["sv-parser-parser/trace"]
[package.metadata.release]
pre-release-replacements = [
{file = "../README.md", search = "sv-parser = \"[a-z0-9\\.-]+\"", replace = "sv-parser = \"{{version}}\""},
{file = "../CHANGELOG.md", search = "Unreleased", replace = "v{{version}}"},
{file = "../CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}"},
{file = "../CHANGELOG.md", search = "Change Log", replace = "Change Log\n\n## [Unreleased](https://github.com/dalance/sv-parser/compare/v{{version}}...Unreleased) - ReleaseDate"},
]
[dependencies]
nom = "5.0.0"
nom-greedyerror = "0.1.0"

View File

@ -1,8 +1,11 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::process;
use std::{cmp, process};
use structopt::StructOpt;
use sv_parser::parse_sv;
use sv_parser_error::ErrorKind;
#[derive(StructOpt)]
struct Opt {
@ -37,10 +40,79 @@ fn main() {
}
}
Err(x) => {
println!("parse failed: {:?} ({})", path, x);
match x.kind() {
ErrorKind::Parse(Some((origin_path, origin_pos))) => {
println!("parse failed: {:?}", path);
print_parse_error(origin_path, origin_pos);
}
x => {
println!("parse failed: {:?} ({})", path, x);
}
}
exit = 1;
}
}
}
process::exit(exit);
}
static CHAR_CR: u8 = 0x0d;
static CHAR_LF: u8 = 0x0a;
fn print_parse_error(origin_path: &PathBuf, origin_pos: &usize) {
let mut f = File::open(&origin_path).unwrap();
let mut s = String::new();
let _ = f.read_to_string(&mut s);
let mut pos = 0;
let mut column = 1;
let mut last_lf = None;
while pos < s.len() {
if s.as_bytes()[pos] == CHAR_LF {
column += 1;
last_lf = Some(pos);
}
pos += 1;
if *origin_pos == pos {
let row = if let Some(last_lf) = last_lf {
pos - last_lf
} else {
pos + 1
};
let mut next_crlf = pos;
while next_crlf < s.len() {
if s.as_bytes()[next_crlf] == CHAR_CR || s.as_bytes()[next_crlf] == CHAR_LF {
break;
}
next_crlf += 1;
}
let column_len = format!("{}", column).len();
print!(" {}:{}:{}\n", origin_path.to_string_lossy(), column, row);
print!("{}|\n", " ".repeat(column_len + 1));
print!("{} |", column);
let beg = if let Some(last_lf) = last_lf {
last_lf + 1
} else {
0
};
print!(
" {}\n",
String::from_utf8_lossy(&s.as_bytes()[beg..next_crlf])
);
print!("{}|", " ".repeat(column_len + 1));
print!(
" {}{}\n",
" ".repeat(pos - beg),
"^".repeat(cmp::min(origin_pos + 1, next_crlf) - origin_pos)
);
}
}
}

View File

@ -86,7 +86,16 @@ pub fn parse_sv<T: AsRef<Path>, U: AsRef<Path>>(
nom::Err::Error(e) => error_position(&e),
nom::Err::Failure(e) => error_position(&e),
};
Err(ErrorKind::Parse(pos).into())
let origin = if let Some(pos) = pos {
if let Some(origin) = text.origin(pos) {
Some((origin.0.clone(), origin.1))
} else {
None
}
} else {
None
};
Err(ErrorKind::Parse(origin).into())
}
}
}
@ -113,7 +122,16 @@ pub fn parse_lib<T: AsRef<Path>, U: AsRef<Path>>(
nom::Err::Error(e) => error_position(&e),
nom::Err::Failure(e) => error_position(&e),
};
Err(ErrorKind::Parse(pos).into())
let origin = if let Some(pos) = pos {
if let Some(origin) = text.origin(pos) {
Some((origin.0.clone(), origin.1))
} else {
None
}
} else {
None
};
Err(ErrorKind::Parse(origin).into())
}
}
}