diff options
| author | Jonas Maier <> | 2026-03-07 11:35:38 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-07 11:35:38 +0100 |
| commit | c36bf58bd0d3d8d2b89211c0bfccab68dad53d66 (patch) | |
| tree | 4c7bd138a280aed1120f85e4110beb51a8356b24 /src | |
| parent | b3ea0f7580a41f0c7769ba610a6219a5fc7c9eb6 (diff) | |
| download | pish-c36bf58bd0d3d8d2b89211c0bfccab68dad53d66.tar.gz | |
finish parsing stuff, add first parsing test
Diffstat (limited to 'src')
| -rw-r--r-- | src/parse/mod.rs (renamed from src/parse.rs) | 38 | ||||
| -rw-r--r-- | src/parse/test.rs | 16 |
2 files changed, 39 insertions, 15 deletions
diff --git a/src/parse.rs b/src/parse/mod.rs index 61d268d..4f38f9b 100644 --- a/src/parse.rs +++ b/src/parse/mod.rs @@ -1,16 +1,19 @@ use crate::BString; -pub trait Stage { - type Str: std::fmt::Debug + Clone; +#[cfg(test)] +mod test; + +pub trait Stage : PartialEq { + type Str: std::fmt::Debug + Clone + PartialEq; } pub trait CmdDisplay { fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()>; } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct PreExpansion; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct PostExpansion; impl Stage for PreExpansion { @@ -29,7 +32,7 @@ pub trait Expander { fn expand_cmd(&mut self, c: Ast<PostExpansion>) -> Res<BString, Self::Error>; } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Ast<T: Stage> { FunDecl(FunDecl<T>), VarAssign(VarAssign<T>), @@ -121,12 +124,17 @@ impl CmdDisplay for ExpString { if self.parts.len() == 1 && self.parts[0].is_boring() { write!( w, - "estr({})", + "estr(b\"{}\")", self.parts[0].clone().unwrap_boring().escape_ascii() ) } else { write!(w, "str([")?; + let mut first = true; for part in self.parts.iter() { + if !first { + write!(w, ",")?; + } + first = false; part.cdisplay(w)?; } write!(w, "])") @@ -138,7 +146,7 @@ impl CmdDisplay for StringPart { fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> { match self { StringPart::Boring(items) => { - write!(w, "bstr(")?; + write!(w, "plain(")?; items.as_slice().cdisplay(w)?; write!(w, ")") } @@ -186,7 +194,7 @@ impl Ast<PreExpansion> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct FunBody { pub body: Box<Ast<PreExpansion>>, } @@ -219,7 +227,7 @@ impl Parse for FunBody { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct FunDecl<S: Stage> { pub name: S::Str, pub body: FunBody, @@ -247,7 +255,7 @@ impl FunDecl<PreExpansion> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct VarAssign<S: Stage> { pub var: S::Str, pub val: S::Str, @@ -285,7 +293,7 @@ impl VarAssign<PreExpansion> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct Pipes<T: Stage> { pub cmds: Vec<Command<T>>, } @@ -300,7 +308,7 @@ impl Pipes<PreExpansion> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum StringPart { Boring(BString), Var(VarName), @@ -319,7 +327,7 @@ impl StringPart { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] /// `"hi ${var} $(cmd) "` gets mapped to `[Boring("hi "), Var("var"), String(" "), Cmd(...), Boring(" ")]` pub struct ExpString { parts: Vec<StringPart>, @@ -357,7 +365,7 @@ fn is_var_name(x: u8) -> bool { x.is_ascii_alphanumeric() || x == b'_' } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct VarName { name: BString, } @@ -509,7 +517,7 @@ impl Parse for ExpString { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct Command<T: Stage> { pub cmd: T::Str, pub args: Vec<T::Str>, diff --git a/src/parse/test.rs b/src/parse/test.rs new file mode 100644 index 0000000..6cd7793 --- /dev/null +++ b/src/parse/test.rs @@ -0,0 +1,16 @@ +use super::*; + +fn parse(x: &[u8]) -> Ast<PreExpansion> { + do_parse(x).unwrap() +} + +#[test] +fn command_interp() { + assert_eq!( + parse(br#"echo "$(echo hi)""#), + pipes([cmd([ + estr(b"echo"), + str([cmdp(pipes([cmd([estr(b"echo"), estr(b"hi")]),])),]) + ]),]) + ); +} |
