diff --git a/lrlex/src/lib/mod.rs b/lrlex/src/lib/mod.rs index ac1b37008..9dc71ceb3 100644 --- a/lrlex/src/lib/mod.rs +++ b/lrlex/src/lib/mod.rs @@ -46,7 +46,7 @@ pub struct LexBuildError { impl Error for LexBuildError {} /// The various different possible Lex parser errors. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] #[non_exhaustive] pub enum LexErrorKind { PrematureEnd, @@ -59,13 +59,37 @@ pub enum LexErrorKind { InvalidStartState, InvalidStartStateName, DuplicateName, - RegexError, + RegexError(regex::Error), InvalidGrmtoolsSectionValue, InvalidNumber, DuplicateGrmtoolsSectionValue, VerbatimNotSupported, } +impl LexErrorKind { + fn is_same_kind(&self, other: &Self) -> bool { + use LexErrorKind as EK; + match (self, other) { + (EK::PrematureEnd, EK::PrematureEnd) + | (EK::RoutinesNotSupported, EK::RoutinesNotSupported) + | (EK::UnknownDeclaration, EK::UnknownDeclaration) + | (EK::MissingSpace, EK::MissingSpace) + | (EK::InvalidName, EK::InvalidName) + | (EK::UnknownStartState, EK::UnknownStartState) + | (EK::DuplicateStartState, EK::DuplicateStartState) + | (EK::InvalidStartState, EK::InvalidStartState) + | (EK::InvalidStartStateName, EK::InvalidStartStateName) + | (EK::DuplicateName, EK::DuplicateName) + | (EK::InvalidGrmtoolsSectionValue, EK::InvalidGrmtoolsSectionValue) + | (EK::InvalidNumber, EK::InvalidNumber) + | (EK::DuplicateGrmtoolsSectionValue, EK::DuplicateGrmtoolsSectionValue) + | (EK::RegexError(_), EK::RegexError(_)) + | (EK::VerbatimNotSupported, EK::VerbatimNotSupported) => true, + _ => false, + } + } +} + impl Spanned for LexBuildError { fn spans(&self) -> &[Span] { self.spans.as_slice() @@ -84,7 +108,7 @@ impl Spanned for LexBuildError { | LexErrorKind::InvalidGrmtoolsSectionValue | LexErrorKind::InvalidNumber | LexErrorKind::VerbatimNotSupported - | LexErrorKind::RegexError => SpansKind::Error, + | LexErrorKind::RegexError(_) => SpansKind::Error, LexErrorKind::DuplicateName | LexErrorKind::DuplicateStartState | LexErrorKind::DuplicateGrmtoolsSectionValue => SpansKind::DuplicationError, @@ -94,7 +118,7 @@ impl Spanned for LexBuildError { impl fmt::Display for LexBuildError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let s = match self.kind { + let s = match &self.kind { LexErrorKind::VerbatimNotSupported => "Verbatim code not supported", LexErrorKind::PrematureEnd => "File ends prematurely", LexErrorKind::RoutinesNotSupported => "Routines not currently supported", @@ -109,7 +133,7 @@ impl fmt::Display for LexBuildError { LexErrorKind::InvalidNumber => "Invalid number", LexErrorKind::DuplicateGrmtoolsSectionValue => "Duplicate grmtools section value", LexErrorKind::DuplicateName => "Rule name already exists", - LexErrorKind::RegexError => "Invalid regular expression", + LexErrorKind::RegexError(e) => return write!(f, "Invalid regular expression: {e}"), }; write!(f, "{s}") } diff --git a/lrlex/src/lib/parser.rs b/lrlex/src/lib/parser.rs index 1c78d3e72..d2af8f8ad 100644 --- a/lrlex/src/lib/parser.rs +++ b/lrlex/src/lib/parser.rs @@ -125,7 +125,7 @@ fn add_duplicate_occurrence( dup_span: Span, ) { if !errs.iter_mut().any(|e| { - if e.kind == kind && e.spans[0] == orig_span { + if e.kind.is_same_kind(&kind) && e.spans[0] == orig_span { e.spans.push(dup_span); true } else { @@ -618,7 +618,7 @@ where target_state, &self.lex_flags, ) - .map_err(|_| self.mk_error(LexErrorKind::RegexError, i))?; + .map_err(|e| self.mk_error(LexErrorKind::RegexError(e), i))?; self.rules.push(rule); } Ok(i + line_len) @@ -864,7 +864,7 @@ mod test { .expect_err("Parsed ok while expecting error"); assert_eq!(errs.len(), 1); let e = &errs[0]; - assert_eq!(e.kind, kind); + assert!(e.kind.is_same_kind(&kind)); assert_eq!( e.spans() .iter() @@ -892,20 +892,22 @@ mod test { } } - assert_eq!( - errs.iter() - .map(|e| { - ( - e.kind.clone(), - e.spans() - .iter() - .map(|span| line_col!(src, span)) - .collect::>(), - ) - }) - .collect::>(), - expected.collect::>() - ); + for ((ek1, es1), (ek2, es2)) in errs + .iter() + .map(|e| { + ( + e.kind.clone(), + e.spans() + .iter() + .map(|span| line_col!(src, span)) + .collect::>(), + ) + }) + .zip(expected) + { + assert!(ek1.is_same_kind(&ek2)); + assert_eq!(es1, es2); + } } }