diff options
| author | Jonas Maier <jonas@x77.dev> | 2026-03-18 13:21:23 +0100 |
|---|---|---|
| committer | Jonas Maier <jonas@x77.dev> | 2026-03-18 13:21:23 +0100 |
| commit | d8cceb822b8e2f2de189a1d4461c89311b82e752 (patch) | |
| tree | b4922dc581fc2ca93bf615d7ca1a0fc6807e5596 /src/parse | |
| parent | 37db397e58105fcc9f5fe0c356cd03f966715bff (diff) | |
| download | pish-d8cceb822b8e2f2de189a1d4461c89311b82e752.tar.gz | |
slightly cleaner parsing
Diffstat (limited to 'src/parse')
| -rw-r--r-- | src/parse/mod.rs | 158 | ||||
| -rw-r--r-- | src/parse/test.rs | 8 |
2 files changed, 86 insertions, 80 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 1e88337..f418600 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -730,14 +730,11 @@ impl Parse for ExpString { } } - let x = b.peek(); + let x = b.adv(); if x == b'\\' { - b.adv(); add_char(p, parse_escape_code(b)?); } else if x == b'$' && !delim.is_strict() { - b.adv(); - if !b.has() { add_char(p, b'$'); continue; @@ -745,98 +742,99 @@ impl Parse for ExpString { let x = b.peek(); - if x == b'?' || x == b'!' { - b.adv(); - p.push(StringPart::Var(Var::new(VarName { name: vec![x] }))) - } else if is_var_begin(x) { + if is_var_begin(x) { let v = VarName::parse(b)?; p.push(StringPart::Var(Var::new(v))); - } else if x == b'{' { - b.adv(); - let v = VarName::parse(b)?; - let mut default = None; + continue; + } + + b.adv(); + + match x { + b'?' | b'!' => p.push(StringPart::Var(Var::new(VarName { name: vec![x] }))), + b'{' => { + let v = VarName::parse(b)?; + let mut default = None; - if !b.has() { - if !b.is_completion() { - return Err(ParseError::Eof); - } - } else if b.peek() == b':' { - b.adv(); if !b.has() { - return Err(ParseError::Eof); - } - if b.peek() == b'-' { + if !b.is_completion() { + return Err(ParseError::Eof); + } + } else if b.peek() == b':' { b.adv(); - default = Some(ExpString::parse(b)?); - } else { - todo!(": in var expansion") + if !b.has() { + return Err(ParseError::Eof); + } + if b.peek() == b'-' { + b.adv(); + default = Some(ExpString::parse(b)?); + } else { + todo!(": in var expansion") + } } - } - if !b.has() { - if !b.is_completion() { - return Err(ParseError::Eof); + if !b.has() { + if !b.is_completion() { + return Err(ParseError::Eof); + } + } else if b.peek() != b'}' { + return Err(ParseError::Expected('}')); } - } else if b.peek() != b'}' { - return Err(ParseError::Expected('}')); - } - let already_complete = b.has(); + let already_complete = b.has(); - if already_complete { - b.adv(); - } + if already_complete { + b.adv(); + } - p.push(StringPart::Var(Var { - name: v, - default, - already_complete, - })); - } else if x == b'(' { - b.adv(); - let cmd = Ast::parse(b)?; - b.spaces(); - - if b.is_empty() && !b.is_completion() { - return Err(ParseError::Expected(')')); + p.push(StringPart::Var(Var { + name: v, + default, + already_complete, + })); } + b'(' => { + let cmd = Ast::parse(b)?; + b.spaces(); - if b.has() && b.peek() == b')' { - b.adv(); - p.push(StringPart::Cmd(CmdInterp { - cmd, - already_complete: true, - })); - } else if b.is_completion() { - p.push(StringPart::Cmd(CmdInterp { - cmd, - already_complete: false, - })) - } else { - return Err(ParseError::Expected(')')); + if b.is_empty() && !b.is_completion() { + return Err(ParseError::Expected(')')); + } + + if b.has() && b.peek() == b')' { + b.adv(); + p.push(StringPart::Cmd(CmdInterp { + cmd, + already_complete: true, + })); + } else if b.is_completion() { + p.push(StringPart::Cmd(CmdInterp { + cmd, + already_complete: false, + })) + } else { + return Err(ParseError::Expected(')')); + } + } + x => { + add_char(p, b'$'); + add_char(p, x); } - } else { - // doesn't seem to be a variable or expansion, just add $ back into the string - add_char(p, b'$'); } + } else if delim.is_none() + && x == b'~' + && p.is_empty() + && (!b.has() || b.peek().is_ascii_whitespace() || b.peek() == b'/') + { + p.push(StringPart::Var(Var { + name: VarName { + name: b"HOME".to_vec(), + }, + default: None, + already_complete: true, + })); } else { - b.adv(); - - if delim.is_none() - && x == b'~' - && p.is_empty() - && (!b.has() || b.peek().is_ascii_whitespace() || b.peek() == b'/') - { - p.push(StringPart::Var(Var { - name: VarName { - name: b"HOME".to_vec(), - }, - default: None, - already_complete: true, - })); - } else { - add_char(p, x); - } + add_char(p, x); } } } diff --git a/src/parse/test.rs b/src/parse/test.rs index 3513c3f..3058730 100644 --- a/src/parse/test.rs +++ b/src/parse/test.rs @@ -321,3 +321,11 @@ fn exit_code_2() { pipes([cmd([estr(b"echo"), str([var(b"?")])])]) ) } + +#[test] +fn dollar_non_var() { + parse_test!( + parse(b"echo $_"), + pipes([cmd([estr(b"echo"), estr(b"$_")]),]) + ) +} |
