From 5049b5c0d8a7df032f1842741d59d6281421ca85 Mon Sep 17 00:00:00 2001 From: dalance Date: Wed, 16 Oct 2019 14:20:23 +0900 Subject: [PATCH] Add parse error position --- Cargo.toml | 4 +++ sv-parser-error/src/lib.rs | 4 +-- sv-parser-parser/Cargo.toml | 3 +- sv-parser-parser/src/lib.rs | 7 +++-- .../source_text/configuration_source_text.rs | 2 +- .../source_text/system_verilog_source_text.rs | 4 +-- sv-parser-parser/src/utils.rs | 28 +++++++++++-------- sv-parser-pp/Cargo.toml | 1 + sv-parser-pp/src/preprocess.rs | 7 ++++- sv-parser/Cargo.toml | 1 + sv-parser/src/lib.rs | 19 +++++++++++-- 11 files changed, 57 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 14270f5..c3c18b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,7 @@ members = [ "sv-parser-pp", "sv-parser-syntaxtree", ] + +#[patch.crates-io] +#nom = {path = "../nom"} +#nom_locate = {path = "../nom_locate"} diff --git a/sv-parser-error/src/lib.rs b/sv-parser-error/src/lib.rs index 1cbe737..d410666 100644 --- a/sv-parser-error/src/lib.rs +++ b/sv-parser-error/src/lib.rs @@ -14,8 +14,8 @@ pub enum ErrorKind { File(PathBuf), #[fail(display = "Include error")] Include, - #[fail(display = "Parse error")] - Parse, + #[fail(display = "Parse error: {:?}", _0)] + Parse(Option), #[fail(display = "Preprocess error")] Preprocess, #[fail(display = "Define argument not found: {}", _0)] diff --git a/sv-parser-parser/Cargo.toml b/sv-parser-parser/Cargo.toml index 7fe5ca7..c8c73a4 100644 --- a/sv-parser-parser/Cargo.toml +++ b/sv-parser-parser/Cargo.toml @@ -20,9 +20,10 @@ trace = ["nom-tracable/trace"] [dependencies] nom = "5.0.0" nom_locate = "1.0.0" +nom-greedyerror = "0.1.0" nom-packrat = "0.3.0" nom-recursive = {version = "0.1.1", features = ["tracer128"]} -nom-tracable = "0.4.0" +nom-tracable = "0.4.1" str-concat = "0.1.4" sv-parser-macros = {version = "0.1.0", path = "../sv-parser-macros"} sv-parser-syntaxtree = {version = "0.1.0", path = "../sv-parser-syntaxtree"} diff --git a/sv-parser-parser/src/lib.rs b/sv-parser-parser/src/lib.rs index fd8d86d..4c2b7b9 100644 --- a/sv-parser-parser/src/lib.rs +++ b/sv-parser-parser/src/lib.rs @@ -31,10 +31,12 @@ pub(crate) use nom::branch::*; pub(crate) use nom::bytes::complete::*; pub(crate) use nom::character::complete::*; pub(crate) use nom::combinator::*; -pub(crate) use nom::error::{make_error, ErrorKind}; +pub(crate) use nom::error::{context, make_error, ErrorKind}; pub(crate) use nom::multi::*; pub(crate) use nom::sequence::*; -pub(crate) use nom::{Err, IResult}; +//pub(crate) use nom::{Err, IResult}; +pub(crate) use nom::Err; +pub(crate) use nom_greedyerror::GreedyError; pub(crate) use nom_packrat::{self, packrat_parser, HasExtraState}; pub(crate) use nom_recursive::{recursive_parser, HasRecursiveInfo, RecursiveInfo}; pub(crate) use nom_tracable::tracable_parser; @@ -52,6 +54,7 @@ pub struct SpanInfo { } pub type Span<'a> = nom_locate::LocatedSpanEx<&'a str, SpanInfo>; +pub type IResult = nom::IResult>; impl HasRecursiveInfo for SpanInfo { fn get_recursive_info(&self) -> RecursiveInfo { diff --git a/sv-parser-parser/src/source_text/configuration_source_text.rs b/sv-parser-parser/src/source_text/configuration_source_text.rs index 996ba1c..2a00ce5 100644 --- a/sv-parser-parser/src/source_text/configuration_source_text.rs +++ b/sv-parser-parser/src/source_text/configuration_source_text.rs @@ -5,7 +5,7 @@ use crate::*; #[tracable_parser] #[packrat_parser] pub(crate) fn config_declaration(s: Span) -> IResult { - let (s, a) = keyword("config")(s)?; + let (s, a) = context("config", keyword("config"))(s)?; let (s, b) = config_identifier(s)?; let (s, c) = symbol(";")(s)?; let (s, d) = many0(pair(local_parameter_declaration, symbol(";")))(s)?; diff --git a/sv-parser-parser/src/source_text/system_verilog_source_text.rs b/sv-parser-parser/src/source_text/system_verilog_source_text.rs index 2d65b43..84f0d31 100644 --- a/sv-parser-parser/src/source_text/system_verilog_source_text.rs +++ b/sv-parser-parser/src/source_text/system_verilog_source_text.rs @@ -7,8 +7,8 @@ use crate::*; pub(crate) fn source_text(s: Span) -> IResult { let (s, a) = many0(white_space)(s)?; let (s, b) = opt(timeunits_declaration)(s)?; - let (s, c) = many0(description)(s)?; - Ok((s, SourceText { nodes: (a, b, c) })) + let (s, c) = many_till(description, eof)(s)?; + Ok((s, SourceText { nodes: (a, b, c.0) })) } #[tracable_parser] diff --git a/sv-parser-parser/src/utils.rs b/sv-parser-parser/src/utils.rs index 2f2de25..2b6f022 100644 --- a/sv-parser-parser/src/utils.rs +++ b/sv-parser-parser/src/utils.rs @@ -51,8 +51,8 @@ pub(crate) fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, S #[cfg(not(feature = "trace"))] pub(crate) fn symbol_exact<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, Symbol> { move |s: Span<'a>| { - let (s, x) = map(no_ws(map(tag(t.clone()), into_locate)), |x| { - Symbol { nodes: x } + let (s, x) = map(no_ws(map(tag(t.clone()), into_locate)), |x| Symbol { + nodes: x, })(s)?; Ok((s, x)) } @@ -63,8 +63,8 @@ pub(crate) fn symbol_exact<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult| { let (depth, s) = nom_tracable::forward_trace(s, &format!("symbol(\"{}\")", t)); let body = || { - let (s, x) = map(no_ws(map(tag(t.clone()), into_locate)), |x| { - Symbol { nodes: x } + let (s, x) = map(no_ws(map(tag(t.clone()), into_locate)), |x| Symbol { + nodes: x, })(s)?; Ok((s, x)) }; @@ -79,10 +79,7 @@ pub(crate) fn keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, let (s, x) = map( ws(alt(( all_consuming(map(tag(t.clone()), into_locate)), - terminated( - map(tag(t.clone()), into_locate), - peek(none_of(AZ09_)), - ), + terminated(map(tag(t.clone()), into_locate), peek(none_of(AZ09_))), ))), |x| Keyword { nodes: x }, )(s)?; @@ -98,10 +95,7 @@ pub(crate) fn keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, let (s, x) = map( ws(alt(( all_consuming(map(tag(t.clone()), into_locate)), - terminated( - map(tag(t.clone()), into_locate), - peek(none_of(AZ09_)), - ), + terminated(map(tag(t.clone()), into_locate), peek(none_of(AZ09_))), ))), |x| Keyword { nodes: x }, )(s)?; @@ -315,6 +309,16 @@ where // ----------------------------------------------------------------------------- +pub(crate) fn eof(s: Span) -> IResult { + use nom::InputLength; + + if s.input_len() == 0 { + Ok((s, s)) + } else { + Err(Err::Error(make_error(s, ErrorKind::Eof))) + } +} + #[tracable_parser] #[packrat_parser] pub(crate) fn white_space(s: Span) -> IResult { diff --git a/sv-parser-pp/Cargo.toml b/sv-parser-pp/Cargo.toml index 868c5fe..fb00af4 100644 --- a/sv-parser-pp/Cargo.toml +++ b/sv-parser-pp/Cargo.toml @@ -20,6 +20,7 @@ trace = ["sv-parser-parser/trace"] [dependencies] failure = "0.1.5" nom = "5.0.0" +nom-greedyerror = "0.1.0" sv-parser-error = {version = "0.1.0", path = "../sv-parser-error"} sv-parser-parser = {version = "0.1.0", path = "../sv-parser-parser"} sv-parser-syntaxtree = {version = "0.1.0", path = "../sv-parser-syntaxtree"} diff --git a/sv-parser-pp/src/preprocess.rs b/sv-parser-pp/src/preprocess.rs index 828e778..646f30b 100644 --- a/sv-parser-pp/src/preprocess.rs +++ b/sv-parser-pp/src/preprocess.rs @@ -1,5 +1,6 @@ use crate::range::Range; use failure::ResultExt; +use nom_greedyerror::error_position; use std::collections::{BTreeMap, HashMap}; use std::convert::TryInto; use std::fs::File; @@ -107,7 +108,11 @@ fn preprocess_str, U: AsRef>( } let span = Span::new_extra(&s, SpanInfo::default()); - let (_, pp_text) = pp_parser(span).map_err(|_| ErrorKind::Parse)?; + 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)), + })?; let mut ret = PreprocessedText::new(); diff --git a/sv-parser/Cargo.toml b/sv-parser/Cargo.toml index 37da407..3d0c4ce 100644 --- a/sv-parser/Cargo.toml +++ b/sv-parser/Cargo.toml @@ -16,6 +16,7 @@ trace = ["sv-parser-parser/trace"] [dependencies] nom = "5.0.0" +nom-greedyerror = "0.1.0" sv-parser-error = {version = "0.1.0", path = "../sv-parser-error"} sv-parser-parser = {version = "0.1.0", path = "../sv-parser-parser"} sv-parser-pp = {version = "0.1.0", path = "../sv-parser-pp"} diff --git a/sv-parser/src/lib.rs b/sv-parser/src/lib.rs index 69fad50..237a260 100644 --- a/sv-parser/src/lib.rs +++ b/sv-parser/src/lib.rs @@ -1,6 +1,7 @@ #![recursion_limit = "256"] use nom::combinator::all_consuming; +use nom_greedyerror::error_position; use std::collections::HashMap; use std::fmt; use std::path::Path; @@ -79,7 +80,14 @@ pub fn parse_sv, U: AsRef>( }, defines, )), - Err(_) => Err(ErrorKind::Parse.into()), + Err(x) => { + let pos = match x { + nom::Err::Incomplete(_) => None, + nom::Err::Error(e) => error_position(&e), + nom::Err::Failure(e) => error_position(&e), + }; + Err(ErrorKind::Parse(pos).into()) + } } } @@ -99,7 +107,14 @@ pub fn parse_lib, U: AsRef>( }, defines, )), - Err(_) => Err(ErrorKind::Parse.into()), + Err(x) => { + let pos = match x { + nom::Err::Incomplete(_) => None, + nom::Err::Error(e) => error_position(&e), + nom::Err::Failure(e) => error_position(&e), + }; + Err(ErrorKind::Parse(pos).into()) + } } }