Berry f-strings now support ':' in expression (#23618)

This commit is contained in:
s-hadinger 2025-06-29 22:46:18 +02:00 committed by GitHub
parent 99297d6dfc
commit 45dd2a331e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 5 deletions

View File

@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
## [15.0.1.1] ## [15.0.1.1]
### Added ### Added
- I2S additions (#23543) - I2S additions (#23543)
- Berry f-strings now support ':' in expression
### Breaking Changed ### Breaking Changed

View File

@ -539,9 +539,11 @@ static void scan_f_string(blexer *lexer)
/* if end of string is reached before '}' raise en error */ /* if end of string is reached before '}' raise en error */
for (; i < buf_unparsed_fstr.len; i++) { for (; i < buf_unparsed_fstr.len; i++) {
ch = buf_unparsed_fstr.s[i]; ch = buf_unparsed_fstr.s[i];
if (ch == ':' || ch == '}') { break; } /* stop parsing if single ':' or '}' */
save_char(lexer, ch); /* copy any character unless it's ':' or '}' */ if (ch == '}' || (ch == ':' && buf_unparsed_fstr.s[i+1] != ':')) { break; }
save_char(lexer, ch); /* copy any character unless it's '}' or single ':' */
if (ch == '=') { break; } /* '=' is copied but breaks parsing as well */ if (ch == '=') { break; } /* '=' is copied but breaks parsing as well */
if (ch == ':') { save_char(lexer, ch); i++; } /* if '::' then encode the second ':' but don't parse it again in next iteration */
} }
/* safe check if we reached the end of the string */ /* safe check if we reached the end of the string */
if (i >= buf_unparsed_fstr.len) { be_raise(lexer->vm, "syntax_error", "'}' expected"); } if (i >= buf_unparsed_fstr.len) { be_raise(lexer->vm, "syntax_error", "'}' expected"); }
@ -588,11 +590,17 @@ static void scan_f_string(blexer *lexer)
save_char(lexer, ','); /* add ',' to start next argument to `format()` */ save_char(lexer, ','); /* add ',' to start next argument to `format()` */
for (; i < buf_unparsed_fstr.len; i++) { for (; i < buf_unparsed_fstr.len; i++) {
ch = buf_unparsed_fstr.s[i]; ch = buf_unparsed_fstr.s[i];
if (ch == '=' || ch == ':' || ch == '}') { break; } if (ch == ':' && (buf_unparsed_fstr.s[i+1] == ':')) {
save_char(lexer, ch);
i++; /* skip second ':' */
} else if (ch == '=' || ch == ':' || ch == '}') {
break;
} else {
save_char(lexer, ch); /* copy expression until we reach ':', '=' or '}' */ save_char(lexer, ch); /* copy expression until we reach ':', '=' or '}' */
} }
}
/* no need to check for end of string here, it was done already in first pass */ /* no need to check for end of string here, it was done already in first pass */
if (ch == ':' || ch == '=') { /* if '=' or ':', skip everyting until '}' */ if (ch == '=' || ch == ':') { /* if '=' or ':', skip everyting until '}' */
i++; i++;
for (; i < buf_unparsed_fstr.len; i++) { for (; i < buf_unparsed_fstr.len; i++) {
ch = buf_unparsed_fstr.s[i]; ch = buf_unparsed_fstr.s[i];

View File

@ -175,6 +175,13 @@ assert(f"S = {a}" == 'S = foobar{0}')
assert(f"S = {a:i}" == 'S = 0') assert(f"S = {a:i}" == 'S = 0')
assert(f"{a=}" == 'a=foobar{0}') assert(f"{a=}" == 'a=foobar{0}')
# new option for f-strings, '::' encodes for ':'
assert(f"{true ? 1 :: 2}" == "1")
assert(f"{false ? 1 :: 2}" == "2")
assert(f"{false ? 1 :: 2 : i}" == " 2")
assert(f"{false ? 1 :: 2:i}" == "2")
assert(f"{false ? 1 :: 2:04i}" == "0002")
# startswith case sensitive # startswith case sensitive
assert(string.startswith("", "") == true) assert(string.startswith("", "") == true)
assert(string.startswith("qwerty", "qw") == true) assert(string.startswith("qwerty", "qw") == true)