From 2ed84de6418e8016a6e00f14d53396c0b15b4795 Mon Sep 17 00:00:00 2001 From: greg Date: Wed, 9 Oct 2019 01:50:32 -0700 Subject: [PATCH] Introduce bare else clause in if exprs With a non-passing test --- schala-lang/language/src/ast.rs | 1 + schala-lang/language/src/parsing.rs | 16 ++++++++++----- schala-lang/language/src/parsing/test.rs | 26 +++++++++++++++++++++++- schala-lang/language/src/reduced_ast.rs | 10 +++++++++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index 7f03fad..4acccc9 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -239,6 +239,7 @@ pub struct GuardArm { #[derive(Debug, PartialEq, Clone)] pub enum Guard { + None, Pat(Pattern), HalfExpr(HalfExpr) } diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 24de350..2d20ea5 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -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 { - 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] diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index bd0e0f5..6d4affc 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -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")], + }, + ] + )) + } + } + } +} diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 7e3b6c5..ae3b7ba 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -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);