diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 56e8788..c7a0435 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -126,8 +126,8 @@ //! simple_pattern_match := pattern "then" simple_conditional //! else_case := "else" expr_or_block //! -//! cond_block := "{" (cond_arm comma_or_delimiter)* ("else" expr_or_block) "}" -//! cond_arm := condition guard "then" expr_or_block +//! cond_block := "{" (cond_arm comma_or_delimiter)* "}" +//! cond_arm := condition guard "then" expr_or_block | "else" expr_or_block //! condition := "is" pattern | operator precedence_expr | expression //! guard := "if" expression //! comma_or_delimiter := "," | delimiter @@ -624,6 +624,7 @@ impl Parser { let next_tok = self.token_handler.next(); let operation = match BinOp::from_sigil_token(&next_tok.kind) { Some(sigil) => sigil, + //TODO I think I can fix this unreachable None => unreachable!() }; let rhs = self.precedence_expr(new_precedence)?; @@ -860,68 +861,66 @@ impl Parser { #[recursive_descent_method] fn cond_block(&mut self) -> ParseResult { - //TODO - delimited! isn't sophisticated enough to do thisa - //let guards = delimited!(self, LCurlyBrace, guard_arm, Comma, RCurlyBrace); expect!(self, LCurlyBrace); - - let mut guards = vec![]; + let mut cond_arms = vec![]; loop { match self.token_handler.peek_kind() { RCurlyBrace | EOF => break, Semicolon | Newline => { self.token_handler.next(); continue}, _ => { - let guard_arm = self.guard_arm()?; - guards.push(guard_arm); - loop { - match self.token_handler.peek_kind() { - Semicolon | Newline => { self.token_handler.next(); continue; }, - _ => break, - } + cond_arms.push(self.cond_arm()?); + match self.token_handler.peek_kind() { + Comma | Semicolon | Newline => { self.token_handler.next(); continue; }, + _ => break, } - if let RCurlyBrace = self.token_handler.peek_kind() { - break; - } - expect!(self, Comma); } } } expect!(self, RCurlyBrace); - Ok(IfExpressionBody::GuardList(guards)) + Ok(IfExpressionBody::CondList(cond_arms)) } #[recursive_descent_method] - fn guard_arm(&mut self) -> ParseResult { - if let Keyword(Kw::Else) = self.token_handler.peek_kind() { + fn cond_arm(&mut self) -> ParseResult { + let (condition, guard) = 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 }) + (Condition:Else, None) } else { + let condition = self.condition()?; let guard = self.guard()?; expect!(self, Keyword(Kw::Then)); - let body = self.expr_or_block()?; - Ok(GuardArm { guard, body }) - } + (condition, guard) + }; + let body = self.expr_or_block()?; + Ok(ConditionArm { condition, guard, body }) } #[recursive_descent_method] - fn guard(&mut self) -> ParseResult { + fn condition(&mut self) -> ParseResult { Ok(match self.token_handler.peek_kind() { Keyword(Kw::Is) => { self.token_handler.next(); - let pat = self.pattern()?; - Guard::Pat(pat) + Condition::Pattern(self.pattern()?) }, - ref tok if BinOp::from_sigil_token(tok).is_some() => { - let op = BinOp::from_sigil_token(&self.token_handler.next().kind).unwrap(); - let precedence = op.get_precedence(); - let Expression { kind, .. } = self.precedence_expr(precedence)?; - Guard::HalfExpr(HalfExpr { op: Some(op), expr: kind }) + Operator(ref op) if !PrefixOp::is_prefix(&*op) => { + let op = self.token_handler.next(); + let expr = Box::new(self.expression()?); + Condition::TruncatedOp(op, expr) }, _ => { - //TODO - I think there's a better way to do this involving the precedence of -> - let Expression { kind, .. } = self.prefix_expr()?; - Guard::HalfExpr(HalfExpr { op: None, expr: kind }) - } + Condition::Expression(self.expression()?) + }, + }) + } + + #[recursive_descent_method] + fn guard(&mut self) -> ParseResult> { + Ok(match self.token_handler.peek_kind() { + Keyword(Kw::If) => { + self.token_handler.next(); + Some(self.expression()?) + }, + _ => None }) }