From f4b69eb87ca61f408323ab9d24938859f7c4ceb3 Mon Sep 17 00:00:00 2001 From: Jonas Maier Date: Fri, 8 May 2026 19:00:39 +0200 Subject: while loops --- src/parse/mod.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- src/parse/test.rs | 2 +- 2 files changed, 50 insertions(+), 2 deletions(-) (limited to 'src/parse') 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 { VarAssign(VarAssign), Pipes(Pipes), If(If), + While(While), } #[allow(unused)] @@ -99,6 +100,12 @@ pub struct If { parse_progress: IfParseProgress, } +#[derive(Debug, Clone, PartialEq)] +pub struct While { + pub condition: Pipes, + pub block: Block, +} + impl If { fn expand(self, e: &mut E) -> Res, E::Error> { Ok(If { @@ -140,6 +147,13 @@ pub fn cond( }) } +pub fn whil(condition: Ast, block: Block) -> Ast { + 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 { 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 { 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 { } impl Pipes { - fn expand(self, e: &mut E) -> Res, E::Error> { + pub fn expand(self, e: &mut E) -> Res, 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 = std::result::Result; @@ -1177,6 +1201,7 @@ impl Ast { 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 { } } +impl Parse for While { + fn parse(b: &mut Cursor<'_>) -> Result { + 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 { fn parse(b: &mut Cursor<'_>) -> Result { b.spaces(); @@ -1434,6 +1474,14 @@ impl Parse for Ast { x?; } + 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 { diff --git a/src/parse/test.rs b/src/parse/test.rs index f4ac92e..768a5a2 100644 --- a/src/parse/test.rs +++ b/src/parse/test.rs @@ -259,7 +259,7 @@ fn if_else() { #[test] fn simple_while() { - parse_test!(parse(b"while cond { x }"), todo!()); + parse_test!(parse(b"while cond { x }"), whil(pipes([cmd([estr(b"cond")]),]), block([pipes([cmd([estr(b"x")]),])]))); } #[test] -- cgit v1.2.3