aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.rs')
-rw-r--r--src/parse.rs144
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 {