diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 17145b8..7bce092 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -186,7 +186,8 @@ typed_identifier := IDENTIFIER type_anno /* Declaration - Functions */ func_declaration := func_signature func_body -func_body := ε | '{' (statement delimiter)* '}' +func_body := ε | nonempty_func_body +nonempty_func_body := '{' (statement delimiter)* '}' func_signature := 'fn' func_name formal_param_list func_body func_name := IDENTIFIER | operator formal_param_list := '(' (formal_param ',')* ')' @@ -221,13 +222,12 @@ prefix_op := '+' | '-' | '!' | '~' call_expr := index_expr ( '(' expr_list ')' )* expr_list := expression (',' expression)* | ε index_expr := primary ( '[' (expression (',' (expression)* | ε) ']' )* -primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | curly_brace_expr | list_expr +primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr /* Primary Expressions */ -curly_brace_expr := lambda_expr | anonymous_struct //TODO list_expr := '[' (expression, ',')* ']' -lambda_expr := '{' '|' (formal_param ',')* '|' (type_anno)* (statement delimiter)* '}' +lambda_expr := '\' formal_param_list nonempty_func_body paren_expr := LParen paren_inner RParen paren_inner := (expression ',')* identifier_expr := named_struct | IDENTIFIER @@ -389,7 +389,7 @@ impl Parser { fn func_declaration(&mut self) -> ParseResult { let signature = self.func_signature()?; if let LCurlyBrace = self.peek() { - let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict); + let statements = self.nonempty_func_body()?; Ok(Declaration::FuncDecl(signature, statements)) } else { Ok(Declaration::FuncSig(signature)) @@ -407,7 +407,7 @@ impl Parser { }, _ => (self.identifier()?, false) }; - let params = delimited!(self, LParen, formal_param, Comma, RParen); + let params = self.formal_param_list()?; let type_anno = match self.peek() { Colon => Some(self.type_anno()?), _ => None, @@ -415,6 +415,16 @@ impl Parser { Ok(Signature { name, operator, params, type_anno }) } + #[recursive_descent_method] + fn nonempty_func_body(&mut self) -> ParseResult> { + Ok(delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict)) + } + + #[recursive_descent_method] + fn formal_param_list(&mut self) -> ParseResult> { + Ok(delimited!(self, LParen, formal_param, Comma, RParen)) + } + #[recursive_descent_method] fn formal_param(&mut self) -> ParseResult { let name = self.identifier()?; @@ -603,6 +613,7 @@ impl Parser { fn primary(&mut self) -> ParseResult { match self.peek() { LCurlyBrace => self.curly_brace_expr(), + Backslash => self.lambda_expr(), LParen => self.paren_expr(), LSquareBracket => self.list_expr(), Keyword(Kw::If) => self.if_expr(), @@ -621,13 +632,15 @@ impl Parser { #[recursive_descent_method] fn curly_brace_expr(&mut self) -> ParseResult { - self.lambda_expr() + ParseError::new("Not implemented") } #[recursive_descent_method] fn lambda_expr(&mut self) -> ParseResult { - expect!(self, LCurlyBrace); - let params = delimited!(self, Pipe, formal_param, Comma, Pipe); + expect!(self, Backslash); + let params = self.formal_param_list()?; //TODO make this allow some more concise syntaxes + let body = self.nonempty_func_body()?; + /* let mut body = Vec::new(); loop { match self.peek() { @@ -640,6 +653,7 @@ impl Parser { } } expect!(self, RCurlyBrace); + */ Ok(Expression(ExpressionType::Lambda { params, body }, None)) //TODO need to handle types somehow } @@ -1468,18 +1482,18 @@ fn a(x) { #[test] fn parsing_lambdas() { - parse_test! { "{|x| x + 1}", single_expr!( + parse_test! { r#"\(x) { x + 1}"#, single_expr!( Lambda { params: vec![(rc!(x), None)], body: vec![exst!("+", val!("x"), NatLiteral(1))] } ) } - parse_test!("{ |x: Int, y| a;b;c;}", AST(vec![ + parse_test!(r#"\ (x: Int, y) { a;b;c;}"#, AST(vec![ exprstatement!(Lambda { params: vec![(rc!(x), Some(ty!("Int"))), (rc!(y), None)], body: vec![exst!(val!("a")), exst!(val!("b")), exst!(val!("c"))] }) ])); - parse_test!("{|x| y}(1)", AST(vec![ + parse_test!(r#"\(x){y}(1)"#, AST(vec![ exprstatement!(Call { f: bx!(ex!( Lambda { params: vec![(rc!(x), None)], body: vec![exprstatement!(val!("y"))] })), arguments: vec![ex!(NatLiteral(1))] })])); diff --git a/schala-lang/language/src/tokenizing.rs b/schala-lang/language/src/tokenizing.rs index 4f26048..bd1ca56 100644 --- a/schala-lang/language/src/tokenizing.rs +++ b/schala-lang/language/src/tokenizing.rs @@ -12,7 +12,7 @@ pub enum TokenType { LSquareBracket, RSquareBracket, LAngleBracket, RAngleBracket, LCurlyBrace, RCurlyBrace, - Pipe, + Pipe, Backslash, Comma, Period, Colon, Underscore, Slash, @@ -157,6 +157,7 @@ pub fn tokenize(input: &str) -> Vec { '{' => LCurlyBrace, '}' => RCurlyBrace, '[' => LSquareBracket, ']' => RSquareBracket, '"' => handle_quote(&mut input), + '\\' => Backslash, c if c.is_digit(10) => handle_digit(c, &mut input), c if c.is_alphabetic() || c == '_' => handle_alphabetic(c, &mut input), //TODO I'll probably have to rewrite this if I care about types being uppercase, also type parameterization c if is_operator(&c) => handle_operator(c, &mut input),