String interpolation is back on the plan now with Pure Virtual Binding II. So this question is back, too.
We could start improving on the old code with UPARSE's new meaning of WHILE.
parse text [
collect while not <end> [
(capturing: false)
try keep between <here> ["$(" (capturing: true) | <end>]
:(if capturing '[
let inner: between <here> ")"
keep (as word! inner)
])
]
]
Slightly better. I'll point out a binding question:
-
should a spliced in parse-rule via GET-GROUP! run a bind operation on its material? I'm speaking about the soft-quoted splice of the block material from the IF. Interestingly this doesn't affect the parse "keywords" (like BETWEEN or KEEP or ) because they are looked up in a map. And it doesn't affect INNER because it's a LET-variable. What gets affected is the AS and WORD! lookup from the LIB context.
- I think it's clear that a spliced value via GET-GROUP! acts as if it had been written verbatim where it was found. So the quoted block--when unquoted--since it was unbound, would receive the binding of the PARSE ruleset in progress at that moment. But this means that curiously, you would be able to return an already bound block as another choice. Here that would give you no difference between if capturing @[...] and if capturing '[...], but if you had (let x: 10 if capturing '[...]) it would affect the visibility of that X... you would not see it if you used the quote, but would see it with the @.
Beyond that I'm a little puzzled over how to do this better.
I feel like the "right answer" wouldn't need a capturing
mode variable, but could express this as the difference of a complete rule with the between "$(" being its own line.
Following that line of thinking gets this:
parse text [collect while not <end> [
keep any [
[let inner: between "$(" ")" (as word! inner)]
between <here> [<end> | ahead "$("]
]
]]
If we believe the pattern of COLLECT plus one KEEP of the body should be ACCUMULATE that could be:
parse text [accumulate any [
[let inner: between "$(" ")" (as word! inner)]
further between <here> [<end> | ahead "$("]
]]
(That's a little tricky, because you need the FURTHER to avoid infinitely collecting empty strings once you reach the end with between <here> <end>
)
I still don't like the repetition (e.g. repeating "$(" in ahead "$("
).
This might need its own combinator that's a relative of BETWEEN which says what to do with the material that's not between.