mirror of
https://github.com/roc-lang/roc.git
synced 2025-11-01 05:24:15 +00:00
Merge pull request #7497 from smores56/new-interpolation-syntax
Move to new interpolation syntax
This commit is contained in:
commit
528d1d2b69
66 changed files with 630 additions and 596 deletions
|
|
@ -425,16 +425,18 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
|||
}
|
||||
}
|
||||
}
|
||||
b'(' if preceded_by_dollar && !is_single_quote => {
|
||||
b'(' | b'{' if preceded_by_dollar && !is_single_quote => {
|
||||
let old_style_interpolation_block = one_byte == b'(';
|
||||
|
||||
// We're about to begin string interpolation!
|
||||
//
|
||||
// End the previous segment so we can begin a new one.
|
||||
// Retroactively end it right before the `$` char we parsed.
|
||||
// (We can't use end_segment! here because it ends it right after
|
||||
// the just-parsed character, which here would be '(' rather than '$')
|
||||
// the just-parsed character, which here would be '{' rather than '$')
|
||||
// Don't push anything if the string would be empty.
|
||||
if segment_parsed_bytes > 2 {
|
||||
// exclude the 2 chars we just parsed, namely '$' and '('
|
||||
// exclude the 2 chars we just parsed, namely '$' and '{'
|
||||
let string_bytes = &state.bytes()[0..(segment_parsed_bytes - 2)];
|
||||
|
||||
match std::str::from_utf8(string_bytes) {
|
||||
|
|
@ -452,19 +454,27 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
|||
}
|
||||
}
|
||||
|
||||
// Advance past the `$(`
|
||||
// Advance past the `${`
|
||||
state.advance_mut(2);
|
||||
|
||||
let original_byte_count = state.bytes().len();
|
||||
|
||||
// Parse an arbitrary expression, followed by ')'
|
||||
// Parse an arbitrary expression, followed by '}' or ')'
|
||||
let terminating_char = if old_style_interpolation_block {
|
||||
b')'
|
||||
} else {
|
||||
b'}'
|
||||
};
|
||||
let (_progress, (mut loc_expr, sp), new_state) = and(
|
||||
specialize_err_ref(
|
||||
EString::Format,
|
||||
loc(allocated(reset_min_indent(expr::expr_help())))
|
||||
.trace("str_interpolation"),
|
||||
),
|
||||
skip_second(space0_e(EString::FormatEnd), byte(b')', EString::FormatEnd)),
|
||||
skip_second(
|
||||
space0_e(EString::FormatEnd),
|
||||
byte(terminating_char, EString::FormatEnd),
|
||||
),
|
||||
)
|
||||
.parse(arena, state, min_indent)?;
|
||||
|
||||
|
|
@ -488,8 +498,8 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
|||
}
|
||||
}
|
||||
|
||||
// iff the '$' is followed by '(', this is string interpolation.
|
||||
// We'll check for the '(' on the next iteration of the loop.
|
||||
// iff the '$' is followed by '{', this is string interpolation.
|
||||
// We'll check for the '{' on the next iteration of the loop.
|
||||
preceded_by_dollar = one_byte == b'$';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,17 +160,17 @@ mod test_parse {
|
|||
|
||||
#[test]
|
||||
fn escaped_interpolation() {
|
||||
assert_segments(r#""Hi, \$(name)!""#, |arena| {
|
||||
assert_segments(r#""Hi, \${name}!""#, |arena| {
|
||||
bumpalo::vec![in arena;
|
||||
Plaintext("Hi, "),
|
||||
EscapedChar(EscapedChar::Dollar),
|
||||
Plaintext("(name)!"),
|
||||
Plaintext("{name}!"),
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_with_interpolation_in_middle() {
|
||||
fn string_with_old_interpolation_still_works_for_now() {
|
||||
assert_segments(r#""Hi, $(name)!""#, |arena| {
|
||||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
|
|
@ -185,9 +185,31 @@ mod test_parse {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_with_mixed_new_and_old_interpolation_braces_fails() {
|
||||
assert_parsing_fails(r#""${foo)""#, SyntaxError::Unexpected(Region::zero()));
|
||||
assert_parsing_fails(r#""$(foo}""#, SyntaxError::Unexpected(Region::zero()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_with_interpolation_in_middle() {
|
||||
assert_segments(r#""Hi, ${name}!""#, |arena| {
|
||||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
});
|
||||
|
||||
bumpalo::vec![in arena;
|
||||
Plaintext("Hi, "),
|
||||
Interpolated(Loc::new(7, 11, expr)),
|
||||
Plaintext("!")
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_with_interpolation_in_front() {
|
||||
assert_segments(r#""$(name), hi!""#, |arena| {
|
||||
assert_segments(r#""${name}, hi!""#, |arena| {
|
||||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
|
|
@ -232,7 +254,7 @@ mod test_parse {
|
|||
|
||||
#[test]
|
||||
fn string_with_interpolation_in_back() {
|
||||
assert_segments(r#""Hello $(name)""#, |arena| {
|
||||
assert_segments(r#""Hello ${name}""#, |arena| {
|
||||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
|
|
@ -247,7 +269,7 @@ mod test_parse {
|
|||
|
||||
#[test]
|
||||
fn string_with_multiple_interpolations() {
|
||||
assert_segments(r#""Hi, $(name)! How is $(project) going?""#, |arena| {
|
||||
assert_segments(r#""Hi, ${name}! How is ${project} going?""#, |arena| {
|
||||
let expr1 = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
|
|
@ -271,7 +293,7 @@ mod test_parse {
|
|||
#[test]
|
||||
fn string_with_non_interpolation_dollar_signs() {
|
||||
assert_segments(
|
||||
r#""$a Hi, $(name)! $b How is $(project) going? $c""#,
|
||||
r#""$a Hi, ${name}! $b How is ${project} going? $c""#,
|
||||
|arena| {
|
||||
let expr1 = arena.alloc(Var {
|
||||
module_name: "",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue