diff --git a/TODO.md b/TODO.md index 8bd0d73..1c57b1b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ # TODO items ## General code cleanup +- I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule DONE -experiment with storing metadata via ItemIds on AST nodes (cf. https://rust-lang.github.io/rustc-guide/hir.html, https://github.com/rust-lang/rust/blob/master/src/librustc/hir/mod.rs ) -implement and test open/use statements -implement field access diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index 4acccc9..22b7bba 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -189,8 +189,8 @@ pub enum ExpressionKind { indexers: Vec, }, IfExpression { - discriminator: Box, - body: Box, + discriminator: Option>, + body: IfExpressionBody, }, WhileExpression { condition: Option>, @@ -218,36 +218,33 @@ pub enum InvocationArgument { Ignored } -#[derive(Debug, PartialEq, Clone)] -pub enum Discriminator { - Simple(Expression), - BinOp(Expression, BinOp) -} - #[derive(Debug, PartialEq, Clone)] pub enum IfExpressionBody { - SimpleConditional(Block, Option), - SimplePatternMatch(Pattern, Block, Option), - GuardList(Vec) + SimpleConditional { + then_case: Block, + else_case: Option + }, + SimplePatternMatch { + pattern: Pattern, + then_case: Block, + else_case: Option + }, + CondList(Vec) } #[derive(Debug, PartialEq, Clone)] -pub struct GuardArm { - pub guard: Guard, +pub struct ConditionArm { + pub condition: Condition, + pub guard: Option, pub body: Block, } #[derive(Debug, PartialEq, Clone)] -pub enum Guard { - None, - Pat(Pattern), - HalfExpr(HalfExpr) -} - -#[derive(Debug, PartialEq, Clone)] -pub struct HalfExpr { - pub op: Option, - pub expr: ExpressionKind, +pub enum Condition { + Pattern(Pattern), + TruncatedOp(BinOp, Box), + Expression(Box), + Else, } #[derive(Debug, PartialEq, Clone)] diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 869465e..56e8788 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -119,13 +119,14 @@ //! discriminator //! //! ```text -//! if_expr := "if" discriminator ("then" simple_conditional | "is" simple_pattern_match | cond_block) +//! if_expr := "if" discriminator if_expr_body +//! if_expr_body := ("then" simple_conditional | "is" simple_pattern_match | cond_block) //! discriminator := ε | expression -//! simple_conditional := expr_or_block else_clause +//! simple_conditional := expr_or_block else_case //! simple_pattern_match := pattern "then" simple_conditional -//! else_clause := "else" expr_or_block +//! else_case := "else" expr_or_block //! -//! cond_block := "{" (cond_arm comma_or_delimiter)* "}" +//! cond_block := "{" (cond_arm comma_or_delimiter)* ("else" expr_or_block) "}" //! cond_arm := condition guard "then" expr_or_block //! condition := "is" pattern | operator precedence_expr | expression //! guard := "if" expression @@ -811,54 +812,44 @@ impl Parser { #[recursive_descent_method] fn if_expr(&mut self) -> ParseResult { expect!(self, Keyword(Kw::If)); - let discriminator = Box::new({ - self.restrictions.no_struct_literal = true; - let x = self.discriminator(); - self.restrictions.no_struct_literal = false; - x? - }); - - let body = Box::new(match self.token_handler.peek_kind() { - Keyword(Kw::Then) => self.conditional()?, - Keyword(Kw::Is) => self.simple_pattern_match()? , - _ => self.guard_block()? - }); - + let discriminator = if let LCurlyBrace = self.token_handler.peek_kind() { + Some(Box::new(self.expression()?)) + } else { + None + }; + let body = if_expr_body()?; Ok(Expression::new(self.id_store.fresh(), ExpressionKind::IfExpression { discriminator, body })) } #[recursive_descent_method] - fn discriminator(&mut self) -> ParseResult { - let lhs = self.prefix_expr()?; - let ref next = self.token_handler.peek_kind(); - Ok(if let Some(op) = BinOp::from_sigil_token(next) { - self.token_handler.next(); - Discriminator::BinOp(lhs, op) - } else { - Discriminator::Simple(lhs) - }) + fn if_expr_body(&mut self) -> ParseResult { + match self.token_handler.peek_kind() { + Keyword(Kw::Then) => self.simple_conditional()?, + Keyword(Kw::Is) => self.simple_pattern_match()? , + _ => self.cond_block()? + } } #[recursive_descent_method] - fn conditional(&mut self) -> ParseResult { + fn simple_conditional(&mut self) -> ParseResult { expect!(self, Keyword(Kw::Then)); - let then_clause = self.expr_or_block()?; - let else_clause = self.else_clause()?; - Ok(IfExpressionBody::SimpleConditional(then_clause, else_clause)) + let then_case = self.expr_or_block()?; + let else_case = self.else_case()?; + Ok(IfExpressionBody::SimpleConditional {then_case, else_case }) } #[recursive_descent_method] fn simple_pattern_match(&mut self) -> ParseResult { expect!(self, Keyword(Kw::Is)); - let pat = self.pattern()?; + let pattern = self.pattern()?; expect!(self, Keyword(Kw::Then)); - let then_clause = self.expr_or_block()?; - let else_clause = self.else_clause()?; - Ok(IfExpressionBody::SimplePatternMatch(pat, then_clause, else_clause)) + let then_case = self.expr_or_block()?; + let else_case = self.else_case()?; + Ok(IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case }) } #[recursive_descent_method] - fn else_clause(&mut self) -> ParseResult> { + fn else_case(&mut self) -> ParseResult> { Ok(if let Keyword(Kw::Else) = self.token_handler.peek_kind() { self.token_handler.next(); Some(self.expr_or_block()?) @@ -868,7 +859,7 @@ impl Parser { } #[recursive_descent_method] - fn guard_block(&mut self) -> ParseResult { + 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);