Introduce bare else clause in if exprs

With a non-passing test
This commit is contained in:
greg 2019-10-09 01:50:32 -07:00
parent 22efd39114
commit 2ed84de641
4 changed files with 47 additions and 6 deletions

View File

@ -239,6 +239,7 @@ pub struct GuardArm {
#[derive(Debug, PartialEq, Clone)]
pub enum Guard {
None,
Pat(Pattern),
HalfExpr(HalfExpr)
}

View File

@ -122,7 +122,7 @@
//! simple_pattern_match := pattern "then" conditional
//! else_clause := ε | "else" expr_or_block
//! guard_block := "{" (guard_arm, ",")* "}"
//! guard_arm := guard "then" expr_or_block
//! guard_arm := guard "then" expr_or_block | "else" expr_or_block
//! guard := "is" pattern | (operator)+ precedence_expr
//! ```
//!
@ -893,10 +893,16 @@ impl Parser {
#[recursive_descent_method]
fn guard_arm(&mut self) -> ParseResult<GuardArm> {
let guard = self.guard()?;
expect!(self, Keyword(Kw::Then));
let body = self.expr_or_block()?;
Ok(GuardArm { guard, body })
if let Keyword(Kw::Else) = self.token_handler.peek_kind() {
self.token_handler.next();
let body = self.expr_or_block()?;
Ok(GuardArm { guard: Guard::None, body })
} else {
let guard = self.guard()?;
expect!(self, Keyword(Kw::Then));
let body = self.expr_or_block()?;
Ok(GuardArm { guard, body })
}
}
#[recursive_descent_method]

View File

@ -4,7 +4,7 @@ use std::str::FromStr;
use super::tokenize;
use super::ParseResult;
use crate::ast::{ItemIdStore, AST, Expression, Statement, StatementKind, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName, ImportSpecifier, ImportedNames};
use crate::ast::{ItemIdStore, AST, Expression, Statement, StatementKind, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName, ImportSpecifier, ImportedNames, GuardArm, Guard};
use super::Declaration::*;
use super::Signature;
use super::TypeIdentifier::*;
@ -761,3 +761,27 @@ fn imports_4() {
}
}
#[test]
fn if_expr() {
parse_test_wrap_ast! {
"if x { 1 then 5, else 20 }",
exst! {
IfExpression {
discriminator: bx!(Discriminator::Simple(ex!(s "x"))),
body: bx!(IfExpressionBody::GuardList(
vec![
GuardArm {
guard: Guard::Pat(Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1)})),
body: vec![exst!(s "5")],
},
GuardArm {
guard: Guard::None,
body: vec![exst!(s "20")],
},
]
))
}
}
}
}

View File

@ -276,6 +276,16 @@ impl<'a> Reducer<'a> {
let mut alternatives = vec![];
for arm in guard_arms {
match arm.guard {
Guard::None => {
let item = self.block(&arm.body);
let alt = Alternative {
item, matchable: Subpattern {
tag: None, subpatterns: vec![],
bound_vars: vec![], guard: None,
}
};
alternatives.push(alt);
},
Guard::Pat(ref p) => {
let item = self.block(&arm.body);
let alt = p.to_alternative(item, symbol_table);