rable 0.1.9

A Rust implementation of the Parable bash parser — complete GNU Bash 5.3-compatible parsing with Python bindings
Documentation
# Iteration 6: Compound commands - comprehensive edge cases

# === Basic subshells ===

=== simple subshell
(echo foo)
---
(subshell (command (word "echo") (word "foo")))
---


=== subshell with multiple commands
(echo foo; echo bar)
---
(subshell (semi (command (word "echo") (word "foo")) (command (word "echo") (word "bar"))))
---


=== subshell with and
(cmd1 && cmd2)
---
(subshell (and (command (word "cmd1")) (command (word "cmd2"))))
---


=== subshell with or
(cmd1 || cmd2)
---
(subshell (or (command (word "cmd1")) (command (word "cmd2"))))
---


=== subshell with pipeline
(echo foo | cat)
---
(subshell (pipe (command (word "echo") (word "foo")) (command (word "cat"))))
---


=== subshell with complex pipeline
(cat file | grep pattern | head -5)
---
(subshell (pipe (command (word "cat") (word "file")) (pipe (command (word "grep") (word "pattern")) (command (word "head") (word "-5")))))
---


=== subshell no spaces
(echo foo)
---
(subshell (command (word "echo") (word "foo")))
---


# === Nested subshells ===
# Note: (( is arithmetic command, use spaces for nested subshells: ( (cmd) )

=== nested subshell
( (echo foo) )
---
(subshell (subshell (command (word "echo") (word "foo"))))
---


=== triple nested subshell
( ( (echo foo) ) )
---
(subshell (subshell (subshell (command (word "echo") (word "foo")))))
---


=== nested subshell with list
( (echo a; echo b) )
---
(subshell (subshell (semi (command (word "echo") (word "a")) (command (word "echo") (word "b")))))
---


# === Subshells in pipelines ===

=== subshell at pipeline start
(echo foo) | cat
---
(pipe (subshell (command (word "echo") (word "foo"))) (command (word "cat")))
---


=== subshell at pipeline end
echo foo | (cat)
---
(pipe (command (word "echo") (word "foo")) (subshell (command (word "cat"))))
---


=== subshell in middle of pipeline
echo foo | (grep foo) | wc -l
---
(pipe (command (word "echo") (word "foo")) (pipe (subshell (command (word "grep") (word "foo"))) (command (word "wc") (word "-l"))))
---


=== multiple subshells in pipeline
(echo foo) | (cat) | (wc)
---
(pipe (subshell (command (word "echo") (word "foo"))) (pipe (subshell (command (word "cat"))) (subshell (command (word "wc")))))
---


# === Subshells in lists ===

=== subshell in and list
(echo foo) && echo bar
---
(and (subshell (command (word "echo") (word "foo"))) (command (word "echo") (word "bar")))
---


=== subshell in or list
(false) || echo fallback
---
(or (subshell (command (word "false"))) (command (word "echo") (word "fallback")))
---


=== subshell in background
(sleep 10) &
---
(background (subshell (command (word "sleep") (word "10"))))
---


=== subshell with cd
(cd /tmp && ls)
---
(subshell (and (command (word "cd") (word "/tmp")) (command (word "ls"))))
---


# === Basic brace groups ===

=== simple brace group
{ echo foo; }
---
(brace-group (command (word "echo") (word "foo")))
---


=== brace group with multiple commands
{ echo foo; echo bar; }
---
(brace-group (semi (command (word "echo") (word "foo")) (command (word "echo") (word "bar"))))
---


=== brace group with and
{ cmd1 && cmd2; }
---
(brace-group (and (command (word "cmd1")) (command (word "cmd2"))))
---


=== brace group with or
{ cmd1 || cmd2; }
---
(brace-group (or (command (word "cmd1")) (command (word "cmd2"))))
---


=== brace group with pipeline
{ echo foo | cat; }
---
(brace-group (pipe (command (word "echo") (word "foo")) (command (word "cat"))))
---


=== brace group complex list
{ echo a && echo b || echo c; }
---
(brace-group (or (and (command (word "echo") (word "a")) (command (word "echo") (word "b"))) (command (word "echo") (word "c"))))
---


# === Nested brace groups ===

=== nested brace group
{ { echo foo; }; }
---
(brace-group (brace-group (command (word "echo") (word "foo"))))
---


=== brace inside subshell
({ echo foo; })
---
(subshell (brace-group (command (word "echo") (word "foo"))))
---


=== subshell inside brace
{ (echo foo); }
---
(brace-group (subshell (command (word "echo") (word "foo"))))
---


=== subshell inside brace no space
{(echo foo)}
---
(brace-group (subshell (command (word "echo") (word "foo"))))
---


# === Brace groups in pipelines ===

=== brace group in pipeline
{ echo foo; } | cat
---
(pipe (brace-group (command (word "echo") (word "foo"))) (command (word "cat")))
---


=== brace group at end of pipeline
echo foo | { cat; }
---
(pipe (command (word "echo") (word "foo")) (brace-group (command (word "cat"))))
---


# === Brace groups in lists ===

=== brace group in and list
{ echo foo; } && echo bar
---
(and (brace-group (command (word "echo") (word "foo"))) (command (word "echo") (word "bar")))
---


=== brace group in or list
{ false; } || echo fallback
---
(or (brace-group (command (word "false"))) (command (word "echo") (word "fallback")))
---


# === From tree-sitter-bash ===

=== subshell in background with path
( ./start-server --port=80 ) &
---
(background (subshell (command (word "./start-server") (word "--port=80"))))
---


=== brace with or fallback
{ echo "b"; return 0; }
---
(brace-group (semi (command (word "echo") (word "\"b\"")) (command (word "return") (word "0"))))
---


# === Complex combinations ===

=== subshell and brace mixed
(echo a) && { echo b; }
---
(and (subshell (command (word "echo") (word "a"))) (brace-group (command (word "echo") (word "b"))))
---


=== pipeline with both types
{ echo a; } | (cat) | { wc; }
---
(pipe (brace-group (command (word "echo") (word "a"))) (pipe (subshell (command (word "cat"))) (brace-group (command (word "wc")))))
---