mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-07 13:15:21 +00:00
Fix inconsistencies with cpython while parsing format strings (#124)
* Fix inconsistencies with cpython while parsing format strings which contain colons inside square brackets Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com>
This commit is contained in:
parent
a5b08096a0
commit
5e9d9853e7
1 changed files with 65 additions and 8 deletions
|
@ -863,17 +863,46 @@ impl FormatString {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_part_in_brackets(text: &str) -> Result<FormatPart, FormatParseError> {
|
fn parse_part_in_brackets(text: &str) -> Result<FormatPart, FormatParseError> {
|
||||||
let parts: Vec<&str> = text.splitn(2, ':').collect();
|
let mut chars = text.chars().peekable();
|
||||||
|
|
||||||
|
let mut left = String::new();
|
||||||
|
let mut right = String::new();
|
||||||
|
|
||||||
|
let mut split = false;
|
||||||
|
let mut selected = &mut left;
|
||||||
|
let mut inside_brackets = false;
|
||||||
|
|
||||||
|
while let Some(char) = chars.next() {
|
||||||
|
if char == '[' {
|
||||||
|
inside_brackets = true;
|
||||||
|
|
||||||
|
selected.push(char);
|
||||||
|
|
||||||
|
while let Some(next_char) = chars.next() {
|
||||||
|
selected.push(next_char);
|
||||||
|
|
||||||
|
if next_char == ']' {
|
||||||
|
inside_brackets = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if chars.peek().is_none() {
|
||||||
|
return Err(FormatParseError::MissingRightBracket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if char == ':' && !split && !inside_brackets {
|
||||||
|
split = true;
|
||||||
|
selected = &mut right;
|
||||||
|
} else {
|
||||||
|
selected.push(char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// before the comma is a keyword or arg index, after the comma is maybe a spec.
|
// before the comma is a keyword or arg index, after the comma is maybe a spec.
|
||||||
let arg_part = parts[0];
|
let arg_part: &str = &left;
|
||||||
|
|
||||||
let format_spec = if parts.len() > 1 {
|
let format_spec = if split { right } else { String::new() };
|
||||||
parts[1].to_owned()
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
// On parts[0] can still be the conversion (!r, !s, !a)
|
// left can still be the conversion (!r, !s, !a)
|
||||||
let parts: Vec<&str> = arg_part.splitn(2, '!').collect();
|
let parts: Vec<&str> = arg_part.splitn(2, '!').collect();
|
||||||
// before the bang is a keyword or arg index, after the comma is maybe a conversion spec.
|
// before the bang is a keyword or arg index, after the comma is maybe a conversion spec.
|
||||||
let arg_part = parts[0];
|
let arg_part = parts[0];
|
||||||
|
@ -1168,6 +1197,34 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_square_brackets_inside_format() {
|
||||||
|
assert_eq!(
|
||||||
|
FormatString::from_str("{[:123]}"),
|
||||||
|
Ok(FormatString {
|
||||||
|
format_parts: vec![FormatPart::Field {
|
||||||
|
field_name: "[:123]".to_owned(),
|
||||||
|
conversion_spec: None,
|
||||||
|
format_spec: "".to_owned(),
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(FormatString::from_str("{asdf[:123]asdf}"), {
|
||||||
|
Ok(FormatString {
|
||||||
|
format_parts: vec![FormatPart::Field {
|
||||||
|
field_name: "asdf[:123]asdf".to_owned(),
|
||||||
|
conversion_spec: None,
|
||||||
|
format_spec: "".to_owned(),
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(FormatString::from_str("{[1234}"), {
|
||||||
|
Err(FormatParseError::MissingRightBracket)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_parse_escape() {
|
fn test_format_parse_escape() {
|
||||||
let expected = Ok(FormatString {
|
let expected = Ok(FormatString {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue