You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Backtick command substitution (```...```) is still parsed by `read_backtick_inner` in `src/lexer/expansions.rs`, which walks characters and only knows about `\` escapes. It has the same latent bug class that `$(...)` had before #29: anything inside the backticks that looks like a terminator but isn't (e.g. a heredoc body containing a backtick) can close the scan at the wrong position.
Fix
Apply the same fork-and-merge pattern that #29 uses for `$(...)`:
In `Lexer::read_backtick`, fork a fresh parser over the shared source buffer.
Have the inner parser consume the body until the matching closing backtick.
Merge `pos`/`line` back.
Copy the consumed source range into `wb.value`.
The fork infrastructure is already in place from #29:
`Lexer::fork(&self) -> Self` — cheap refcounted clone of the source buffer
`parser::parse_cmdsub_body(outer, outer_depth)` — model for the new `parse_backtick_body`
`parser_depth` field — inner parser inherits outer depth for `MAX_DEPTH`
`in_cmdsub` flag on forked lexers — reuse or add a sibling `in_backtick` flag if the heredoc delimiter rewind logic differs
Complications specific to backticks
Backtick parsing is trickier than `$(...)` because of the escape rules:
`\\\`` inside a backtick is an escaped literal backtick
`\\\$` inside a backtick escapes a `$`
Nested backticks use `\\\\\\\`` to escape (every level of nesting adds a layer of backslashes)
`"\\\`...\\\`"` (backtick inside double quotes) has its own escape handling
The fork's inner lexer will need a mode that accounts for the backslash-escape stripping. Options:
Pre-process the source range into a scratch buffer with escapes stripped, then parse that. Breaks the shared-buffer assumption. Not recommended.
Problem
Backtick command substitution (```...```) is still parsed by `read_backtick_inner` in `src/lexer/expansions.rs`, which walks characters and only knows about `\` escapes. It has the same latent bug class that `$(...)` had before #29: anything inside the backticks that looks like a terminator but isn't (e.g. a heredoc body containing a backtick) can close the scan at the wrong position.
Fix
Apply the same fork-and-merge pattern that #29 uses for `$(...)`:
The fork infrastructure is already in place from #29:
Complications specific to backticks
Backtick parsing is trickier than `$(...)` because of the escape rules:
The fork's inner lexer will need a mode that accounts for the backslash-escape stripping. Options:
Option 2 is preferred for consistency with the `$(...)` path.
Tests to add
Scope
Independent of #29 and the process-sub follow-up. Keep the PR focused on backticks only.
References