Skip to content

Commit

Permalink
fix: forbid single-element char ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
Aloso committed Nov 6, 2023
1 parent b9ae3ac commit 0513546
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 12 deletions.
4 changes: 2 additions & 2 deletions pomsky-lib/src/diagnose/diagnostic_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ diagnostic_code! {
RepetitionChain = 112,
CharRangeStringEmpty = 113,
CharRangeTooManyCodePoints = 114,
CharClassHasDescendingRange = 115,
CharClassHasNonAscendingRange = 115,
CharClassUnknownShorthand = 116,
CharClassIllegalNegation = 117,
CharClassUnallowedCombination = 118,
Expand Down Expand Up @@ -152,7 +152,7 @@ impl<'a> From<&'a CharClassError> for DiagnosticCode {
match value {
E::Empty => Self::EmptyClass,
E::CaretInGroup | E::Invalid => Self::UnexpectedToken,
E::DescendingRange(_, _) => Self::CharClassHasDescendingRange,
E::NonAscendingRange(_, _) => Self::CharClassHasNonAscendingRange,
E::Unallowed => Self::CharClassUnallowedCombination,
E::UnknownNamedClass { .. } => Self::CharClassUnknownShorthand,
E::Negative => Self::CharClassIllegalNegation,
Expand Down
14 changes: 9 additions & 5 deletions pomsky-lib/src/diagnose/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,15 @@ pub(super) fn get_parser_help(
similar: Some(ref similar),
..
}) => Some(format!("Perhaps you meant `{similar}`")),
ParseErrorKind::CharClass(CharClassError::DescendingRange(..)) => {
let dash_pos = slice.find('-').unwrap();
let (part1, part2) = slice.split_at(dash_pos);
let part2 = part2.trim_start_matches('-');
Some(format!("Switch the characters: {}-{}", part2.trim(), part1.trim()))
ParseErrorKind::CharClass(CharClassError::NonAscendingRange(c1, c2)) => {
if c1 == c2 {
Some(format!("Use a single character: '{c1}'"))
} else {
let dash_pos = slice.find('-').unwrap();
let (part1, part2) = slice.split_at(dash_pos);
let part2 = part2.trim_start_matches('-');
Some(format!("Switch the characters: {}-{}", part2.trim(), part1.trim()))
}
}
ParseErrorKind::CharClass(CharClassError::CaretInGroup) => {
Some("Use `![...]` to negate a character class".into())
Expand Down
6 changes: 3 additions & 3 deletions pomsky-syntax/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ pub enum CharClassError {
/// This error is created when `[^` is encountered. This is a negated
/// character class in a regex, but pomsky instead uses the `![` syntax.
CaretInGroup,
/// Descending code point range, e.g. `['z'-'a']`
DescendingRange(char, char),
/// Non-ascending code point range, e.g. `['z'-'a']`
NonAscendingRange(char, char),
/// Invalid token within a character class
Invalid,
/// Character class contains incompatible shorthands, e.g. `[. codepoint]`
Expand All @@ -235,7 +235,7 @@ impl core::fmt::Display for CharClassError {
match self {
CharClassError::Empty => write!(f, "This character class is empty"),
CharClassError::CaretInGroup => write!(f, "`^` is not allowed here"),
&CharClassError::DescendingRange(a, b) => write!(
&CharClassError::NonAscendingRange(a, b) => write!(
f,
"Character range must be in increasing order, but it is U+{:04X?} - U+{:04X?}",
a as u32, b as u32
Expand Down
2 changes: 1 addition & 1 deletion pomsky-syntax/src/exprs/char_class/char_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl CharGroup {
/// Tries to create a `CharGroup` from a range of characters (inclusive).
/// Returns `None` if `last` is lower than `first`.
pub(crate) fn try_from_range(first: char, last: char) -> Option<Vec<GroupItem>> {
if first <= last {
if first < last {
Some(vec![GroupItem::Range { first, last }])
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion pomsky-syntax/src/parse/parser_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ impl<'i> Parser<'i> {
let last = last.to_char().map_err(|e| e.at(span2))?;

let group = CharGroup::try_from_range(first, last).ok_or_else(|| {
PEK::CharClass(CharClassError::DescendingRange(first, last)).at(span1.join(span2))
PEK::CharClass(CharClassError::NonAscendingRange(first, last)).at(span1.join(span2))
})?;
Ok(Some(group))
} else {
Expand Down

0 comments on commit 0513546

Please sign in to comment.