diff options
| author | Jonas Maier <> | 2026-03-17 16:37:44 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-17 16:37:44 +0100 |
| commit | fb63779507c21b5f0a73fef2dbaa10480b02b126 (patch) | |
| tree | 78eda19b71c2b0e47ac01714fd80b687a7b4b783 /src/parse/mod.rs | |
| parent | 890bde4d5dd1baadbcdb48ba51ecde88c1154f50 (diff) | |
| download | pish-fb63779507c21b5f0a73fef2dbaa10480b02b126.tar.gz | |
better parsing
Diffstat (limited to 'src/parse/mod.rs')
| -rw-r--r-- | src/parse/mod.rs | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 006fce2..9d3164e 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -912,6 +912,20 @@ struct Cursor<'a> { backtrace: bool, } +#[derive(Default)] +struct SpaceStats { + space: u32, + tab: u32, + lf: u32, + cr: u32, +} + +impl SpaceStats { + fn is_empty(&self) -> bool { + self.space == 0 && self.tab == 0 && self.lf == 0 && self.cr == 0 + } +} + impl<'a> Cursor<'a> { fn new(buf: &'a [u8], mode: ParseMode) -> Self { Self { @@ -978,6 +992,31 @@ impl<'a> Cursor<'a> { } } + fn spaces_stats(&mut self) -> SpaceStats { + let mut stats = SpaceStats::default(); + while self.has() && b" \t\n\r".contains(&self.buf[0]) { + match self.buf[0] { + b' ' => stats.space += 1, + b'\t' => stats.tab += 1, + b'\n' => stats.lf += 1, + b'\r' => stats.cr += 1, + _ => unreachable!(), + } + self.adv(); + } + stats + } + + /// returns true if the next thing in the buffer is whitespace (including at least one newline) + /// + /// does not modify the buffer + fn whitespace_newline(&mut self) -> bool { + let x = self.buf; + let s = self.spaces_stats(); + self.buf = x; + s.lf > 0 + } + fn is_completion(&self) -> bool { matches!(self.mode, ParseMode::Completion) } @@ -1015,7 +1054,7 @@ impl Parse for Command<PreExpansion> { fn parse(b: &mut Cursor<'_>) -> Result<Self> { let path: ExpString = b.parse()?; let mut args = Vec::new(); - loop { + while !b.whitespace_newline() { match ExpString::parse(b) { Ok(arg) => args.push(arg), Err(ParseError::NotAString) => break, @@ -1031,7 +1070,8 @@ impl Parse for Pipes<PreExpansion> { let mut cmds: Vec<Command<PreExpansion>> = vec![b.parse()?]; loop { - b.spaces(); + let space_stats = b.spaces_stats(); + if b.is_empty() { return Ok(Pipes { cmds }); } @@ -1040,7 +1080,7 @@ impl Parse for Pipes<PreExpansion> { if c == b'|' { b.adv(); cmds.push(b.parse()?); - } else if is_symbol(c) { + } else if space_stats.lf > 0 || is_symbol(c) { return Ok(Pipes { cmds }); } else { Err(ParseError::Unknown(c))?; |
