Skip to content

Commit 72b5537

Browse files
Merge pull request #85 from Aaronontheweb/feature/v03-bash-structural
Adapt Bash parser to structural projections
2 parents c6dc9b3 + 9ae9d84 commit 72b5537

7 files changed

Lines changed: 1405 additions & 409 deletions

File tree

IMPLEMENTATION_PLAN.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,15 @@ priorities.
233233
precedence, ancestry coordinates, reference identity, span and enum
234234
validity, value/redirect invariants, safe defaults, copied collections,
235235
and the 16-container bound.
236-
- [ ] Adapt the existing Bash and PowerShell grammars to emit the structural
237-
and command-occurrence projections before enabling any control-flow
236+
- [x] Adapt the existing Bash grammar to emit structural and command-occurrence
237+
projections before enabling control flow. The recursive coordinator
238+
preserves pipeline/list precedence, isolated nested groups, decoded
239+
wrapper ownership and nullable spans, compatibility operators, and exact
240+
`Clause` identity; unsupported wrapper tails and depth overflow fail
241+
closed. Redirect-bearing leaves remain incomplete until the explicit
242+
redirect-analysis slice lands.
243+
- [ ] Adapt the existing PowerShell grammar to emit the structural and
244+
command-occurrence projections before enabling any control-flow
238245
construct.
239246
- [ ] Deliver paired Bash and PowerShell `$()` substitution slices for all
240247
locked executable value positions, including ordering, ancestry,

SPEC.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,10 @@ command := clause (compound_op clause)*
929929
compound_op := "&&" | "||" | ";" | "|" | NEWLINE
930930
clause := subshell | bash_c_wrapper | simple_clause
931931
subshell := "(" command ")"
932-
bash_c_wrapper := ("bash" | "sh") "-c" QUOTED_STRING
932+
bash_c_wrapper := ("bash" | "sh") static_flag* "-c" STATIC_QUOTED_STRING
933+
static_flag := exact-one literal Word beginning with "-"
934+
STATIC_QUOTED_STRING := QuotedString whose outer-shell provenance is entirely
935+
literal and exactly one value
933936
simple_clause := verb_chain arg* redirect*
934937
verb_chain := verb_like_word (FW_pair? verb_like_word)*
935938
// greedy walk per §6.1; FW_pair is a
@@ -1669,6 +1672,16 @@ The outer `bash -c` itself does not appear as a clause — it's "consumed"
16691672
by the recursion. Consumers that care that this came from a wrapper can
16701673
inspect `IsCommandStringWrapped` on the surfaced clauses.
16711674

1675+
A `bash` or `sh` clause whose authored arguments are dynamic, contain a decoded
1676+
`-c`, or contain a combined short option that may select command-string mode,
1677+
but that does not match the complete static wrapper production, remains visible
1678+
through its v0.2 compatibility leaf, including its direct outer source spans.
1679+
Its v0.3 command occurrence has `IsComplete=false`. Wrapper-control tokens and
1680+
the quoted body must each have literal, exactly-one outer-shell provenance;
1681+
token kind or decoded spelling alone is insufficient. A proved `--` ends this
1682+
conservative option scan. The parser does not claim to have discovered a
1683+
dynamic or otherwise unsupported command-string body.
1684+
16721685
**Recursion limit:** parse `bash -c "bash -c ..."` chains up to depth 5.
16731686
Deeper nesting → set the outer `ParsedCommand.IsUnparseable = true` with
16741687
reason `"bash -c recursion depth exceeded (>5)"` per locked interpretation

openspec/changes/v0-3-structured-shell-analysis/specs/executable-command-projection/spec.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ partial command and compatibility result.
6868
- **THEN** projection fails closed
6969
- **THEN** the occurrence is not published with `IsComplete=true`
7070

71+
#### Scenario: Dynamic Bash command string remains incomplete
72+
- **WHEN** Bash parses a `bash` or `sh` clause with dynamic wrapper-control input, decoded or combined command-string options, or an expanding quoted body that does not match the complete literal exactly-one wrapper production
73+
- **THEN** the existing outer compatibility leaf remains visible with direct source provenance
74+
- **THEN** its command occurrence has `IsComplete=false` because no hidden command-string body was discovered
75+
7176
#### Scenario: While condition and body roles
7277
- **WHEN** Bash parses `while curl URL; do sleep 1; done`
7378
- **THEN** `curl` is identified as a condition occurrence

openspec/changes/v0-3-structured-shell-analysis/tasks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
- [x] 3.3 Add `ParsedCommand.Syntax` and `ParsedCommand.Commands` while retaining all v0.2 members.
2828
- [x] 3.4 Build a library-owned traversal that emits each simple command occurrence exactly once in deterministic source order.
2929
- [x] 3.5 Build the conservative `Clauses` compatibility flattener without inventing cross-structure compound operators.
30-
- [ ] 3.6 Adapt the existing Bash grammar to emit the structural model with no newly supported syntax.
30+
- [x] 3.6 Adapt the existing Bash grammar to emit the structural model with no newly supported syntax.
3131
- [ ] 3.7 Adapt the existing PowerShell grammar to emit the structural model with no newly supported syntax.
3232
- [ ] 3.8 Add tests proving existing parser inputs retain their v0.2 leaf and compatibility results.
3333
- [ ] 3.9 Add corpus expectations for syntax shape, occurrences, roles, and completeness for existing constructs.

0 commit comments

Comments
 (0)