Refuse to translate if set1 is longer than set2 and set2 ends in a character class

tr [:lower:]a [:upper:]

fails in GNU tr, so print an error for tr too.
This commit is contained in:
Christian von Elm 2024-06-15 12:38:19 +02:00
parent 6a13c48085
commit a46e4fd290
2 changed files with 25 additions and 0 deletions

View file

@ -35,6 +35,7 @@ pub enum BadSequence {
EmptySet2WhenNotTruncatingSet1,
ClassExceptLowerUpperInSet2,
ClassInSet2NotMatchedBySet1,
Set1LongerSet2EndsInClass,
}
impl Display for BadSequence {
@ -62,6 +63,9 @@ impl Display for BadSequence {
Self::ClassInSet2NotMatchedBySet1 => {
write!(f, "when translating, every 'upper'/'lower' in set2 must be matched by a 'upper'/'lower' in the same position in set1")
}
Self::Set1LongerSet2EndsInClass => {
write!(f, "when translating with string1 longer than string2,\nthe latter string must not end with a character class")
}
}
}
}
@ -259,6 +263,15 @@ impl Sequence {
.filter_map(to_u8)
.collect();
if set2_solved.len() < set1_solved.len()
&& !truncate_set1_flag
&& matches!(
set2.last().copied(),
Some(Self::Class(Class::Upper)) | Some(Self::Class(Class::Lower))
)
{
return Err(BadSequence::Set1LongerSet2EndsInClass);
}
//Truncation is done dead last. It has no influence on the other conversion steps
if truncate_set1_flag {
set1_solved.truncate(set2_solved.len());

View file

@ -1374,3 +1374,15 @@ fn check_disallow_blank_in_set2_when_translating() {
fn check_class_in_set2_must_be_matched_in_set1() {
new_ucmd!().args(&["-t", "1[:upper:]", "[:upper:]"]).fails();
}
#[test]
fn check_set1_longer_set2_ends_in_class() {
new_ucmd!().args(&["[:lower:]a", "[:upper:]"]).fails();
}
#[test]
fn check_set1_longer_set2_ends_in_class_with_trunc() {
new_ucmd!()
.args(&["-t", "[:lower:]a", "[:upper:]"])
.succeeds();
}