working if, else and while

This commit is contained in:
Daniel Bulant 2022-02-21 14:44:02 +01:00
parent 0bb157c9e7
commit b0b6eb7d48
6 changed files with 79 additions and 30 deletions

View file

@ -110,8 +110,13 @@ mod test {
}
#[test]
fn if_expr() -> Result<()> {
load_and_run("test/if.rush")
fn if_base() -> Result<()> {
load_and_run("test/base_if.rush")
}
#[test]
fn if_else() -> Result<()> {
load_and_run("test/if_else.rush")
}
#[test]

View file

@ -275,33 +275,70 @@ impl Tree {
fn parse_if(&mut self, end: usize) -> Result<IfExpression> {
self.inc();
let condition = self.get_expression(end).with_context(|| "Error getting condition for if expression")?;
dbg!(&condition);
let mut contents = Vec::new();
loop {
match self.get_next_token() {
match self.get_current_token() {
Tokens::End => break,
Tokens::Space => { self.inc(); },
Tokens::Space => {},
Tokens::Else => break,
Tokens::CommandEnd(_) => {}
_ => contents.push(self.get_expression(end).with_context(|| "Error getting contents for if expression")?)
};
self.inc();
}
loop {
match self.get_current_token() {
Tokens::CommandEnd(_) => { self.inc(); },
Tokens::Space => { self.inc(); },
_ => break
}
}
let mut else_contents = Vec::new();
if matches!(self.get_current_token(), Tokens::Else) {
self.inc();
loop {
match self.get_current_token() {
Tokens::End => break,
Tokens::Space => {},
Tokens::CommandEnd(_) => {}
Tokens::Else => break,
Tokens::If => {
else_contents.push(self.get_expression(end).with_context(|| "Error getting contents for if expression")?);
if else_contents.len() == 1 { break };
}
_ => else_contents.push(self.get_expression(end).with_context(|| "Error getting contents for if expression")?)
};
self.inc();
}
}
if self.i < self.tokens.len() {
loop {
match self.get_current_token() {
Tokens::CommandEnd(_) => { self.inc(); },
Tokens::Space => { self.inc(); },
_ => break
}
if self.i >= self.tokens.len() - 1 { break }
}
self.inc();
}
Ok(IfExpression { condition: Box::new(condition), contents, else_contents })
}
fn parse_while(&mut self, end: usize) -> Result<WhileExpression> {
self.inc();
let condition = self.get_expression(end).with_context(|| "Error getting condition for while expression")?;
dbg!(&condition);
dbg!(self.i);
let mut contents = Vec::new();
self.inc();
loop {
let token = self.get_next_token();
dbg!(token, matches!(token, Tokens::End));
let token = self.get_current_token();
match token {
Tokens::End => break,
Tokens::Else => bail!("Unexpected ELSE. Support for ELSE statements after WHILE may come later."),
Tokens::CommandEnd(_) => { self.inc(); },
Tokens::Space => { self.inc(); },
_ => contents.push(self.get_expression(end).with_context(|| "Error getting contents for while expression")?)
};
dbg!(&contents);
}
self.inc();
Ok(WhileExpression { condition: Box::new(condition), contents })
@ -404,9 +441,10 @@ impl Tree {
}
fn get_expression(&mut self, end: usize) -> Result<Expression> {
let mut token = self.get_current_token();
let mut expr: Option<Expression> = None;
let mut token = self.get_current_token();
loop {
dbg!(token);
match token {
Tokens::Space => {self.inc();},
Tokens::CommandEnd(_) => { if matches!(expr, Some(_)) { break }; self.inc();},
@ -460,14 +498,14 @@ impl Tree {
_ => expr = Some(self.parse_call(end)?)
},
Tokens::Else => bail!("Unexpected token ELSE"),
Tokens::End => bail!("Unexpected token END\nCurrent expression:{:?}", expr),
Tokens::End => { dbg!(expr); bail!("Unexpected token END"); },
Tokens::For => match expr {
Some(_) => bail!("Commands must be ended properly"),
None => expr = Some(Expression::ForExpression(self.parse_for(end)?)),
},
Tokens::If => match expr {
Some(_) => bail!("Commands must be ended properly"),
None => expr = Some(Expression::IfExpression(self.parse_if(end)?)),
None => {expr = Some(Expression::IfExpression(self.parse_if(end)?)); dbg!(&expr); },
}
Tokens::Let => return Ok(self.parse_let(end)?),
Tokens::While => return Ok(Expression::WhileExpression(self.parse_while(end)?)),
@ -501,6 +539,7 @@ impl Tree {
Tokens::JobCommandEnd => bail!("Jobs not yet implemented")
}
if self.i >= end - 1 { break }
dbg!("finished loop", &expr);
token = self.get_current_token();
}
match expr {
@ -526,6 +565,7 @@ pub fn build_tree(tokens: Vec<Tokens>) -> Result<Vec<Expression>> {
match val {
Ok(val) => expressions.push(val),
Err(error) => {
if error.to_string() == "No expression found" { break }
dbg!(tree);
return Err(error);
}

View file

@ -215,21 +215,20 @@ impl ExecExpression for IfExpression {
None => bail!("Invalid IF expression"),
Some(cmd) => cmd
};
ctx.add_scope();
let res = match condition.spawn() {
Result::Err(_) => {
Some(condition)
self.else_contents.exec(ctx)?
},
Result::Ok(mut res) => {
if !res.wait()?.success() {
Some(condition)
self.else_contents.exec(ctx)?
} else {
ctx.add_scope();
let res = self.contents.exec(ctx)?;
ctx.pop_scope();
res
self.contents.exec(ctx)?
}
}
};
ctx.pop_scope();
Ok(res)
}

View file

@ -175,11 +175,13 @@ pub fn tokenize(reader: &mut dyn std::io::BufRead) -> Result<Vec<Tokens>> {
';' | '\r' | '\n' => if !escape_active && !quote_active && !double_quote_active {
save_buf(&mut buf, &mut tokens);
tokens.push(Tokens::CommandEnd(letter.clone()));
let mut x = i;
let mut x = 0;
while x < text.len() - 1 && matches!(text.chars().nth(x).unwrap(), '\n' | '\r' | ';' | ' ') {
x += 1;
}
skipper = x - i - 1;
if x > 0 {
skipper = x - 1;
}
buf_add = false;
},
'&' => if !escape_active && !quote_active && !double_quote_active {
@ -233,6 +235,15 @@ pub fn tokenize(reader: &mut dyn std::io::BufRead) -> Result<Vec<Tokens>> {
tokens.push(Tokens::ExportSet);
buf_add = false;
},
'#' => if !escape_active && !quote_active && !double_quote_active {
save_buf(&mut buf, &mut tokens);
buf_add = false;
let mut x = 0;
while x + i + 1 < text.len() && text.chars().nth(x + i + 1).unwrap() != '\n' {
x += 1;
}
skipper = x;
}
_ => {}
}
if letter.clone() != '\\' { escape_active = false; }

3
test/base_if.rush Normal file
View file

@ -0,0 +1,3 @@
if true
echo condition true
end

View file

@ -1,12 +1,3 @@
if true
echo condition true
end
if false
echo condition false
end
if true
echo condition true
else