diff --git a/schala-lang/src/ast.rs b/schala-lang/src/ast.rs index afbb1be..f01258f 100644 --- a/schala-lang/src/ast.rs +++ b/schala-lang/src/ast.rs @@ -93,7 +93,10 @@ pub enum ExpressionType { indexee: Box, indexers: Vec, }, - IfExpression(Box, Block, Option), + IfExpression { + discriminator: Box, + body: Box, + }, WhileExpression { condition: Option>, body: Block, @@ -108,6 +111,28 @@ pub enum ExpressionType { }, ListLiteral(Vec), } +#[derive(Debug, PartialEq, Clone)] +pub enum Discriminator { + Simple(Expression), + BinOp(Expression, BinOp) +} + +#[derive(Debug, PartialEq, Clone)] +pub enum IfExpressionBody { + SimpleConditional(Block, Option), + GuardList(Vec) +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Guard { + pat: Pattern, + body: Block, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Pattern { + +} #[derive(Debug, PartialEq, Clone)] pub struct Enumerator { diff --git a/schala-lang/src/parsing.rs b/schala-lang/src/parsing.rs index 0f9a79c..aadc90a 100644 --- a/schala-lang/src/parsing.rs +++ b/schala-lang/src/parsing.rs @@ -97,6 +97,8 @@ int_literal = ('0x' | '0b') digits float_literal := digits ('.' digits) digits := (DIGIT_GROUP underscore)+ +/* OLD OBSOLETE */ + /* Expression - If */ if_expr := 'if' expression block else_clause else_clause := ε | 'else' block @@ -107,6 +109,13 @@ match_body := '{' (match_arm)* '}' match_arm := pattern '=>' expression pattern := identifier //TODO NOT DONE +/* NEW GOOD */ + +/* Expression - If */ +if_expr := 'if' discriminator ('then' condititional | guard_block) +discriminator := modified_precedence_expression +conditional := block else_clause +else_clause := ε | 'else' block /* Expression - While */ while_expr := 'while' while_cond '{' (statement delimiter)* '}' @@ -618,15 +627,35 @@ impl Parser { parse_method!(if_expr(&mut self) -> ParseResult { expect!(self, Keyword(Kw::If)); - let condition = { + let discriminator = Box::new({ self.restrictions.no_struct_literal = true; - let x = self.expression(); + let x = self.discriminator(); self.restrictions.no_struct_literal = false; x? - }; - let then_clause = self.block()?; + }); + + let body = Box::new(if let Keyword(Kw::Then) = self.peek() { + self.conditional()? + } else { + self.guard_block()? + }); + + Ok(Expression(ExpressionType::IfExpression { discriminator, body }, None)) + }); + + parse_method!(discriminator(&mut self) -> ParseResult { + Ok(Discriminator::Simple(self.expression()?)) //TODO make proper + }); + + parse_method!(conditional(&mut self) -> ParseResult { + expect!(self, Keyword(Kw::Then)); + let then_clause = self.block()?; //TODO should be block_or_expr let else_clause = self.else_clause()?; - Ok(Expression(ExpressionType::IfExpression(bx!(condition), then_clause, else_clause), None)) + Ok(IfExpressionBody::SimpleConditional(then_clause, else_clause)) + }); + + parse_method!(guard_block(&mut self) -> ParseResult { + ParseError::new("Rest of if not done") }); parse_method!(else_clause(&mut self) -> ParseResult> { @@ -1094,13 +1123,14 @@ fn a(x) { #[test] fn parsing_block_expressions() { - parse_test!("if a() { b(); c() }", AST(vec![exprstatement!( + /* + parse_test!("if a() then { b(); c() }", AST(vec![exprstatement!( IfExpression(bx!(ex!(Call { f: bx!(ex!(val!("a"))), arguments: vec![]})), vec![exprstatement!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exprstatement!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })], None) )])); parse_test!(r#" - if true { + if true then { const a = 10 b } else { @@ -1123,6 +1153,7 @@ fn a(x) { Some(vec![exprstatement!(val!("c"))])))])); parse_error!("if A {a: 1} { b } else { c }"); + */ } #[test] fn parsing_interfaces() { diff --git a/schala-lang/src/reduced_ast.rs b/schala-lang/src/reduced_ast.rs index 118ea08..62ff25e 100644 --- a/schala-lang/src/reduced_ast.rs +++ b/schala-lang/src/reduced_ast.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use ast::{AST, Statement, Expression, Declaration}; +use ast::{AST, Statement, Expression, Declaration, Discriminator}; use symbol_table::{Symbol, SymbolSpec, SymbolTable}; use builtin::{BinOp, PrefixOp}; @@ -112,6 +112,15 @@ impl Expression { args: arguments.iter().map(|arg| arg.reduce(symbol_table)).collect(), }, TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce(symbol_table)).collect()), + IfExpression { discriminator, body } => { + let cond = Box::new(match **discriminator { + Discriminator::Simple(ref expr) => expr.reduce(symbol_table), + _ => panic!(), + }); + + Expr::Conditional { cond, then_clause: vec![], else_clause: vec![] } + }, + /* IfExpression(cond, then_clause, else_clause) => Expr::Conditional { cond: Box::new((**cond).reduce(symbol_table)), then_clause: then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(), @@ -120,6 +129,7 @@ impl Expression { Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), } }, + */ _ => Expr::UnimplementedSigilValue, } }