diff options
| author | Jonas Maier <> | 2026-03-07 11:19:57 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-07 11:19:57 +0100 |
| commit | 6d396041ed8c00f6ac58a1b90473ec7ea5db43d8 (patch) | |
| tree | 45da4b9400ea36e719812775f4ae0dfbc3a409b6 /src/parse.rs | |
| parent | 6c37d7bcbbd09f7c6478384fc77f780a650ca15c (diff) | |
| download | pish-6d396041ed8c00f6ac58a1b90473ec7ea5db43d8.tar.gz | |
parse builtin that emits compact ast
Diffstat (limited to 'src/parse.rs')
| -rw-r--r-- | src/parse.rs | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/parse.rs b/src/parse.rs index 809f76b..61d268d 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -4,6 +4,10 @@ pub trait Stage { type Str: std::fmt::Debug + Clone; } +pub trait CmdDisplay { + fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()>; +} + #[derive(Debug, Clone)] pub struct PreExpansion; #[derive(Debug, Clone)] @@ -32,6 +36,146 @@ pub enum Ast<T: Stage> { Pipes(Pipes<T>), } +pub fn decl(name: ExpString, body: Ast<PreExpansion>) -> Ast<PreExpansion> { + Ast::FunDecl(FunDecl { + name: name, + body: FunBody { + body: Box::new(body), + }, + }) +} + +pub fn assign(var: ExpString, val: ExpString) -> Ast<PreExpansion> { + Ast::VarAssign(VarAssign { var, val }) +} + +pub fn pipes<const N: usize>(cmds: [Command<PreExpansion>; N]) -> Ast<PreExpansion> { + Ast::Pipes(Pipes { + cmds: cmds.to_vec(), + }) +} + +pub fn estr(x: &[u8]) -> ExpString { + ExpString { + parts: vec![StringPart::Boring(x.to_vec())], + } +} + +pub fn str<const N: usize>(parts: [StringPart; N]) -> ExpString { + ExpString { + parts: parts.to_vec(), + } +} + +pub fn plain(x: &[u8]) -> StringPart { + StringPart::Boring(x.to_vec()) +} + +pub fn var(x: &[u8]) -> StringPart { + StringPart::Var(VarName { name: x.to_vec() }) +} + +pub fn cmdp(x: Ast<PreExpansion>) -> StringPart { + StringPart::Cmd(x) +} + +pub fn cmd<const N: usize>(x: [ExpString; N]) -> Command<PreExpansion> { + Command { + cmd: x[0].clone(), + args: x[1..].to_vec(), + } +} + +impl CmdDisplay for Ast<PreExpansion> { + fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> { + match self { + Ast::FunDecl(fun_decl) => { + write!(w, "decl(")?; + fun_decl.name.cdisplay(w)?; + write!(w, ", ")?; + fun_decl.body.body.cdisplay(w)?; + write!(w, ")")?; + } + Ast::VarAssign(var_assign) => { + write!(w, "assign(")?; + var_assign.var.cdisplay(w)?; + write!(w, ", ")?; + var_assign.val.cdisplay(w)?; + write!(w, ")")?; + } + Ast::Pipes(pipes) => { + write!(w, "pipes([")?; + for cmd in pipes.cmds.iter() { + cmd.cdisplay(w)?; + write!(w, ",")?; + } + write!(w, "])")?; + } + } + Ok(()) + } +} + +impl CmdDisplay for ExpString { + fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> { + if self.parts.len() == 1 && self.parts[0].is_boring() { + write!( + w, + "estr({})", + self.parts[0].clone().unwrap_boring().escape_ascii() + ) + } else { + write!(w, "str([")?; + for part in self.parts.iter() { + part.cdisplay(w)?; + } + write!(w, "])") + } + } +} + +impl CmdDisplay for StringPart { + fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> { + match self { + StringPart::Boring(items) => { + write!(w, "bstr(")?; + items.as_slice().cdisplay(w)?; + write!(w, ")") + } + StringPart::Var(var_name) => { + write!(w, "var(")?; + var_name.name.as_slice().cdisplay(w)?; + write!(w, ")") + }, + StringPart::Cmd(ast) => { + write!(w, "cmdp(")?; + ast.cdisplay(w)?; + write!(w, ")") + } + } + } +} + +impl CmdDisplay for Command<PreExpansion> { + fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> { + write!(w, "cmd([")?; + self.cmd.cdisplay(w)?; + for arg in self.args.iter() { + write!(w, ", ")?; + arg.cdisplay(w)?; + } + write!(w, "])") + } +} + +impl CmdDisplay for &[u8] { + fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> { + write!(w, "b\"")?; + write!(w, "{}", self.escape_ascii())?; + write!(w, "\"") + } +} + impl Ast<PreExpansion> { pub fn expand<E: Expander>(self, e: &mut E) -> Res<Ast<PostExpansion>, E::Error> { match self { |
