aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse/mod.rs
diff options
context:
space:
mode:
authorJonas Maier <jonas@x77.dev>2026-05-08 19:00:39 +0200
committerJonas Maier <jonas@x77.dev>2026-05-08 19:00:39 +0200
commitf4b69eb87ca61f408323ab9d24938859f7c4ceb3 (patch)
treed74bdb4869eb7ce0ee2899ec92244a484ff5b4f4 /src/parse/mod.rs
parent5697ecb492579413a7ce9589df6847a3e205c647 (diff)
downloadpish-f4b69eb87ca61f408323ab9d24938859f7c4ceb3.tar.gz
while loops
Diffstat (limited to 'src/parse/mod.rs')
-rw-r--r--src/parse/mod.rs50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 47aff20..dcb5790 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -80,6 +80,7 @@ pub enum Ast<T: Stage> {
VarAssign(VarAssign<T>),
Pipes(Pipes<T>),
If(If<T>),
+ While(While),
}
#[allow(unused)]
@@ -99,6 +100,12 @@ pub struct If<T: Stage> {
parse_progress: IfParseProgress,
}
+#[derive(Debug, Clone, PartialEq)]
+pub struct While {
+ pub condition: Pipes<PreExpansion>,
+ pub block: Block,
+}
+
impl If<PreExpansion> {
fn expand<E: Expander>(self, e: &mut E) -> Res<If<PostExpansion>, E::Error> {
Ok(If {
@@ -140,6 +147,13 @@ pub fn cond(
})
}
+pub fn whil(condition: Ast<PreExpansion>, block: Block) -> Ast<PreExpansion> {
+ let Ast::Pipes(condition) = condition else {
+ panic!()
+ };
+ Ast::While(While { condition, block })
+}
+
pub fn estr(x: &[u8]) -> ExpString {
ExpString {
parts: vec![StringPart::Boring(x.to_vec())],
@@ -243,6 +257,13 @@ impl CmdDisplay for Ast<PreExpansion> {
i.false_block.cdisplay(w)?;
write!(w, ")")?;
}
+ Ast::While(l) => {
+ write!(w, "whil(")?;
+ Ast::Pipes(l.condition.clone()).cdisplay(w)?;
+ write!(w, ", ")?;
+ l.block.cdisplay(w)?;
+ write!(w, ")")?;
+ }
}
Ok(())
}
@@ -328,6 +349,7 @@ impl Ast<PreExpansion> {
Ast::Pipes(pipes) => Ok(Ast::Pipes(pipes.expand(e)?)),
Ast::FunDecl(fd) => Ok(Ast::FunDecl(fd.expand(e)?)),
Ast::If(i) => Ok(Ast::If(i.expand(e)?)),
+ Ast::While(w) => Ok(Ast::While(w)),
}
}
}
@@ -478,7 +500,7 @@ pub struct Pipes<T: Stage> {
}
impl Pipes<PreExpansion> {
- fn expand<E: Expander>(self, e: &mut E) -> Res<Pipes<PostExpansion>, E::Error> {
+ pub fn expand<E: Expander>(self, e: &mut E) -> Res<Pipes<PostExpansion>, E::Error> {
let mut cmds = Vec::with_capacity(self.cmds.len());
for cmd in self.cmds.into_iter() {
cmds.push(cmd.expand(e)?);
@@ -1117,6 +1139,8 @@ pub enum ParseError {
NotABlock,
NotAnIf,
+
+ NotAWhile,
}
type Result<T> = std::result::Result<T, ParseError>;
@@ -1177,6 +1201,7 @@ impl Ast<PreExpansion> {
Ast::VarAssign(va) => va.val.completion(e, CompletionKind::Argument),
Ast::Pipes(p) => p.completion(e),
Ast::If(i) => i.completion(e),
+ Ast::While(_) => todo!(),
}
}
}
@@ -1422,6 +1447,21 @@ impl Parse for If<PreExpansion> {
}
}
+impl Parse for While {
+ fn parse(b: &mut Cursor<'_>) -> Result<Self> {
+ b.spaces();
+ if !b.buf.starts_with(b"while ") || b.buf.starts_with(b"while\t") {
+ return Err(ParseError::NotAWhile);
+ }
+ b.advance(6);
+ b.spaces();
+ let condition = Pipes::parse(b)?;
+ let block = Block::parse(b)?;
+
+ Ok(Self { condition, block })
+ }
+}
+
impl Parse for Ast<PreExpansion> {
fn parse(b: &mut Cursor<'_>) -> Result<Self> {
b.spaces();
@@ -1435,6 +1475,14 @@ impl Parse for Ast<PreExpansion> {
}
let orig_len = b.buf.len();
+ let x = While::parse(b);
+ if let Ok(x) = x {
+ return Ok(Self::While(x));
+ } else if b.buf.len() != orig_len {
+ x?;
+ }
+
+ let orig_len = b.buf.len();
let x = VarAssign::parse(b);
if let Ok(va) = x {
return Ok(Self::VarAssign(va));