Merge pull request #1777 from philippeitis/patch-1

Update f-string errors, handle != in f-string.
This commit is contained in:
Noah
2020-02-27 15:52:02 -06:00
committed by GitHub
2 changed files with 36 additions and 7 deletions

View File

@@ -81,6 +81,7 @@ pub struct FStringError {
pub enum FStringErrorType {
UnclosedLbrace,
UnopenedRbrace,
ExpectedRbrace,
InvalidExpression(Box<ParseErrorType>),
InvalidConversionFlag,
EmptyExpression,
@@ -91,8 +92,9 @@ pub enum FStringErrorType {
impl fmt::Display for FStringErrorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FStringErrorType::UnclosedLbrace => write!(f, "Unclosed '('"),
FStringErrorType::UnopenedRbrace => write!(f, "Unopened ')'"),
FStringErrorType::UnclosedLbrace => write!(f, "Unclosed '{{'"),
FStringErrorType::UnopenedRbrace => write!(f, "Unopened '}}'"),
FStringErrorType::ExpectedRbrace => write!(f, "Expected '}}' after conversion flag."),
FStringErrorType::InvalidExpression(error) => {
write!(f, "Invalid expression: {}", error)
}

View File

@@ -29,7 +29,11 @@ impl<'a> FStringParser<'a> {
while let Some(ch) = self.chars.next() {
match ch {
'!' if delims.is_empty() => {
'!' if delims.is_empty() && self.chars.peek() != Some(&'=') => {
if expression.trim().is_empty() {
return Err(EmptyExpression);
}
conversion = Some(match self.chars.next() {
Some('s') => ConversionFlag::Str,
Some('a') => ConversionFlag::Ascii,
@@ -38,9 +42,13 @@ impl<'a> FStringParser<'a> {
return Err(InvalidConversionFlag);
}
None => {
break;
return Err(ExpectedRbrace);
}
})
});
if self.chars.peek() != Some(&'}') {
return Err(ExpectedRbrace);
}
}
':' if delims.is_empty() => {
let mut nested = false;
@@ -292,13 +300,32 @@ mod tests {
#[test]
fn test_parse_invalid_fstring() {
assert_eq!(parse_fstring("{"), Err(UnclosedLbrace));
assert_eq!(parse_fstring("}"), Err(UnopenedRbrace));
assert_eq!(parse_fstring("{5!a"), Err(ExpectedRbrace));
assert_eq!(parse_fstring("{5!a1}"), Err(ExpectedRbrace));
assert_eq!(parse_fstring("{5!"), Err(ExpectedRbrace));
assert_eq!(parse_fstring("abc{!a 'cat'}"), Err(EmptyExpression));
assert_eq!(parse_fstring("{!a"), Err(EmptyExpression));
assert_eq!(parse_fstring("{ !a}"), Err(EmptyExpression));
assert_eq!(parse_fstring("{5!}"), Err(InvalidConversionFlag));
assert_eq!(parse_fstring("{5!x}"), Err(InvalidConversionFlag));
assert_eq!(parse_fstring("{a:{a:{b}}"), Err(ExpressionNestedTooDeeply));
assert_eq!(parse_fstring("{a:b}}"), Err(UnopenedRbrace));
assert_eq!(parse_fstring("}"), Err(UnopenedRbrace));
assert_eq!(parse_fstring("{a:{b}"), Err(UnclosedLbrace));
assert_eq!(parse_fstring("{"), Err(UnclosedLbrace));
// TODO: check for InvalidExpression enum?
assert!(parse_fstring("{class}").is_err());
}
#[test]
fn test_parse_fstring_not_equals() {
let source = String::from("{1 != 2}");
let parse_ast = parse_fstring(&source);
assert!(parse_ast.is_ok());
}
}