Implement else if chaining (#910)

This commit is contained in:
Casey Rodarmor 2021-07-19 18:21:46 -07:00 committed by GitHub
parent 0fea73455b
commit c76805ab9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 40 deletions

View File

@ -414,50 +414,58 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
/// Parse an expression, e.g. `1 + 2`
fn parse_expression(&mut self) -> CompilationResult<'src, Expression<'src>> {
if self.accepted_keyword(Keyword::If)? {
let lhs = self.parse_expression()?;
let inverted = self.accepted(BangEquals)?;
if !inverted {
self.expect(EqualsEquals)?;
}
let rhs = self.parse_expression()?;
self.expect(BraceL)?;
let then = self.parse_expression()?;
self.expect(BraceR)?;
self.expect_keyword(Keyword::Else)?;
self.expect(BraceL)?;
let otherwise = self.parse_expression()?;
self.expect(BraceR)?;
return Ok(Expression::Conditional {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
then: Box::new(then),
otherwise: Box::new(otherwise),
inverted,
});
}
let value = self.parse_value()?;
if self.accepted(Plus)? {
let lhs = Box::new(value);
let rhs = Box::new(self.parse_expression()?);
Ok(Expression::Concatination { lhs, rhs })
self.parse_conditional()
} else {
Ok(value)
let value = self.parse_value()?;
if self.accepted(Plus)? {
let lhs = Box::new(value);
let rhs = Box::new(self.parse_expression()?);
Ok(Expression::Concatination { lhs, rhs })
} else {
Ok(value)
}
}
}
/// Parse a conditional, e.g. `if a == b { "foo" } else { "bar" }`
fn parse_conditional(&mut self) -> CompilationResult<'src, Expression<'src>> {
let lhs = self.parse_expression()?;
let inverted = self.accepted(BangEquals)?;
if !inverted {
self.expect(EqualsEquals)?;
}
let rhs = self.parse_expression()?;
self.expect(BraceL)?;
let then = self.parse_expression()?;
self.expect(BraceR)?;
self.expect_keyword(Keyword::Else)?;
let otherwise = if self.accepted_keyword(Keyword::If)? {
self.parse_conditional()?
} else {
self.expect(BraceL)?;
let otherwise = self.parse_expression()?;
self.expect(BraceR)?;
otherwise
};
Ok(Expression::Conditional {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
then: Box::new(then),
otherwise: Box::new(otherwise),
inverted,
})
}
/// Parse a value, e.g. `(bar)`
fn parse_value(&mut self) -> CompilationResult<'src, Expression<'src>> {
if self.next_is(StringToken) {

View File

@ -156,3 +156,15 @@ test! {
echo {{ a }}
",
}
test! {
name: if_else,
justfile: "
x := if '0' == '1' { 'a' } else if '0' == '0' { 'b' } else { 'c' }
foo:
echo {{ x }}
",
stdout: "b\n",
stderr: "echo b\n",
}