Incorrect parsing of unbalanced braces based on issue 6914 (#7621)

This commit is contained in:
Kangaxx-0 2023-01-24 00:05:46 -08:00 committed by GitHub
parent ef660be285
commit 0bb2e47c98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 6 deletions

View file

@ -396,7 +396,7 @@ proptest! {
{{"{0}": "sam"}} | to nuon | from nuon;
"#, c).as_ref()
));
assert!(actual.err.is_empty() || actual.err.contains("Unexpected end of code") || actual.err.contains("only strings can be keys"));
assert!(actual.err.is_empty() || actual.err.contains("Unexpected end of code") || actual.err.contains("only strings can be keys") || actual.err.contains("unbalanced { and }"));
// The second is for weird escapes due to backslashes
// The third is for chars like '0'
}

View file

@ -34,6 +34,10 @@ pub enum ParseError {
#[diagnostic(code(nu::parser::unclosed_delimiter), url(docsrs))]
Unclosed(String, #[label("unclosed {0}")] Span),
#[error("Unbalanced delimiter.")]
#[diagnostic(code(nu::parser::unbalanced_delimiter), url(docsrs))]
Unbalanced(String, String, #[label("unbalanced {0} and {1}")] Span),
#[error("Parse mismatch during operation.")]
#[diagnostic(code(nu::parser::parse_mismatch), url(docsrs))]
Expected(String, #[label("expected {0}")] Span),
@ -450,6 +454,7 @@ impl ParseError {
ParseError::ExtraPositional(_, s) => *s,
ParseError::UnexpectedEof(_, s) => *s,
ParseError::Unclosed(_, s) => *s,
ParseError::Unbalanced(_, _, s) => *s,
ParseError::Expected(_, s) => *s,
ParseError::Mismatch(_, _, s) => *s,
ParseError::UnsupportedOperation(_, _, _, s, _) => *s,

View file

@ -170,6 +170,23 @@ pub fn lex_item(
// We encountered a closing `}` delimiter. Pop off the opening `{`.
if let Some(BlockKind::CurlyBracket) = block_level.last() {
let _ = block_level.pop();
} else {
// We encountered a closing `}` delimiter, but the last opening
// delimiter was not a `{`. This is an error.
let span = Span::new(span_offset + token_start, span_offset + *curr_offset);
*curr_offset += 1;
return (
Token {
contents: TokenContents::Item,
span,
},
Some(ParseError::Unbalanced(
"{".to_string(),
"}".to_string(),
Span::new(span.end, span.end),
)),
);
}
} else if c == b'(' {
// We encountered an opening `(` delimiter.

View file

@ -4392,10 +4392,15 @@ pub fn parse_value(
}
b'{' => {
if !matches!(shape, SyntaxShape::Closure(..)) && !matches!(shape, SyntaxShape::Block) {
if let (expr, None) =
parse_full_cell_path(working_set, None, span, expand_aliases_denylist)
{
return (expr, None);
let (expr, err) =
parse_full_cell_path(working_set, None, span, expand_aliases_denylist);
match err {
Some(err) => {
if let ParseError::Unbalanced(_, _, _) = err {
return (expr, Some(err));
}
}
None => return (expr, None),
}
}
if matches!(shape, SyntaxShape::Closure(_)) || matches!(shape, SyntaxShape::Any) {

View file

@ -470,3 +470,8 @@ fn or_and_xor() -> TestResult {
// Assumes the precedence NOT > AND > XOR > OR
run_test(r#"true or false xor true or false"#, "true")
}
#[test]
fn unbalanced_delimiter() -> TestResult {
fail_test(r#"{a:{b:5}}}"#, "unbalanced { and }")
}

View file

@ -2,4 +2,4 @@ export def foo [] { "foo" }
export alias bar = "bar"
export-env { let-env BAZ = "baz" } }
export-env { let-env BAZ = "baz" }