From d82a21ab202b2f5e8c96847802d806735ec74ad3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Jul 2018 23:13:08 +0300 Subject: lambda expressions --- src/grammar.ron | 3 +- src/parser/grammar/expressions.rs | 77 +++++++++++++++++++++++++++++++++++++++ src/parser/grammar/items/mod.rs | 63 ++------------------------------ src/parser/grammar/mod.rs | 65 +++------------------------------ src/parser/grammar/params.rs | 71 ++++++++++++++++++++++++++++++++++++ src/parser/grammar/types.rs | 2 +- src/syntax_kinds/generated.rs | 6 ++- 7 files changed, 164 insertions(+), 123 deletions(-) create mode 100644 src/parser/grammar/params.rs (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index df7b4083b..24f11f63e 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -131,6 +131,7 @@ Grammar( "FIELD_EXPR", "REF_EXPR", "DEREF_EXPR", + "LAMBDA_EXPR", "STRUCT_LIT", "STRUCT_LIT_FIELD", @@ -150,7 +151,6 @@ Grammar( "ABI", "NAME", "NAME_REF", - "VALUE_PARAMETER", "BLOCK", "LET_STMT", @@ -165,6 +165,7 @@ Grammar( "ASSOC_TYPE_ARG", "PARAM_LIST", + "VALUE_PARAMETER", "SELF_PARAM", "ARG_LIST", ] diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs index ef3a0f76c..09b351f31 100644 --- a/src/parser/grammar/expressions.rs +++ b/src/parser/grammar/expressions.rs @@ -44,6 +44,63 @@ pub(super) fn expr(p: &mut Parser) { } } +// test block +// fn a() {} +// fn b() { let _ = 1; } +// fn c() { 1; 2; } +// fn d() { 1; 2 } +pub(super) fn block(p: &mut Parser) { + if !p.at(L_CURLY) { + p.error("expected block"); + } + let m = p.start(); + p.bump(); + while !p.at(EOF) && !p.at(R_CURLY) { + match p.current() { + LET_KW => let_stmt(p), + c => { + // test block_items + // fn a() { fn b() {} } + if items::ITEM_FIRST.contains(c) { + items::item(p) + } else { + let expr_stmt = p.start(); + expressions::expr(p); + if p.eat(SEMI) { + expr_stmt.complete(p, EXPR_STMT); + } else { + expr_stmt.abandon(p); + } + } + } + } + } + p.expect(R_CURLY); + m.complete(p, BLOCK); +} + +// test let_stmt; +// fn foo() { +// let a; +// let b: i32; +// let c = 92; +// let d: i32 = 92; +// } +fn let_stmt(p: &mut Parser) { + assert!(p.at(LET_KW)); + let m = p.start(); + p.bump(); + patterns::pattern(p); + if p.at(COLON) { + types::ascription(p); + } + if p.eat(EQ) { + expressions::expr(p); + } + p.expect(SEMI); + m.complete(p, LET_STMT); +} + fn prefix_expr(p: &mut Parser) -> Option { match p.current() { AMPERSAND => Some(ref_expr(p)), @@ -89,6 +146,7 @@ fn atom_expr(p: &mut Parser) -> Option { match p.current() { L_PAREN => Some(tuple_expr(p)), + PIPE => Some(lambda_expr(p)), _ => { p.err_and_bump("expected expression"); None @@ -104,6 +162,25 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker { m.complete(p, TUPLE_EXPR) } +// test lambda_expr +// fn foo() { +// || (); +// || -> i32 { 92 }; +// |x| x; +// |x: i32,| x; +// } +fn lambda_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(PIPE)); + let m = p.start(); + params::list_opt_types(p); + if fn_ret_type(p) { + block(p); + } else { + expr(p) + } + m.complete(p, LAMBDA_EXPR) +} + // test call_expr // fn foo() { // let _ = f(); diff --git a/src/parser/grammar/items/mod.rs b/src/parser/grammar/items/mod.rs index d1da1ecb4..8c2704be5 100644 --- a/src/parser/grammar/items/mod.rs +++ b/src/parser/grammar/items/mod.rs @@ -15,7 +15,7 @@ pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { pub(super) const ITEM_FIRST: TokenSet = token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND]; -fn item(p: &mut Parser) { +pub(super) fn item(p: &mut Parser) { let item = p.start(); attributes::outer_attributes(p); visibility(p); @@ -239,7 +239,7 @@ fn fn_item(p: &mut Parser) { type_params::list(p); if p.at(L_PAREN) { - fn_value_parameters(p); + params::list(p); } else { p.error("expected function arguments"); } @@ -252,64 +252,7 @@ fn fn_item(p: &mut Parser) { // fn foo() where T: Copy {} type_params::where_clause(p); - block(p); - - // test block - // fn a() {} - // fn b() { let _ = 1; } - // fn c() { 1; 2; } - // fn d() { 1; 2 } - fn block(p: &mut Parser) { - if !p.at(L_CURLY) { - p.error("expected block"); - } - let m = p.start(); - p.bump(); - while !p.at(EOF) && !p.at(R_CURLY) { - match p.current() { - LET_KW => let_stmt(p), - c => { - // test block_items - // fn a() { fn b() {} } - if ITEM_FIRST.contains(c) { - item(p) - } else { - let expr_stmt = p.start(); - expressions::expr(p); - if p.eat(SEMI) { - expr_stmt.complete(p, EXPR_STMT); - } else { - expr_stmt.abandon(p); - } - } - } - } - } - p.expect(R_CURLY); - m.complete(p, BLOCK); - } - - // test let_stmt; - // fn foo() { - // let a; - // let b: i32; - // let c = 92; - // let d: i32 = 92; - // } - fn let_stmt(p: &mut Parser) { - assert!(p.at(LET_KW)); - let m = p.start(); - p.bump(); - patterns::pattern(p); - if p.at(COLON) { - types::ascription(p); - } - if p.eat(EQ) { - expressions::expr(p); - } - p.expect(SEMI); - m.complete(p, LET_STMT); - } + expressions::block(p); } // test type_item diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs index 69942e7f1..d4f9b80cf 100644 --- a/src/parser/grammar/mod.rs +++ b/src/parser/grammar/mod.rs @@ -26,8 +26,9 @@ mod expressions; mod items; mod paths; mod patterns; -mod type_args; +mod params; mod type_params; +mod type_args; mod types; use { @@ -95,67 +96,13 @@ fn abi(p: &mut Parser) { abi.complete(p, ABI); } -// test fn_value_parameters -// fn a() {} -// fn b(x: i32) {} -// fn c(x: i32, ) {} -// fn d(x: i32, y: ()) {} -fn fn_value_parameters(p: &mut Parser) { - assert!(p.at(L_PAREN)); - let m = p.start(); - p.bump(); - self_param(p); - while !p.at(EOF) && !p.at(R_PAREN) { - value_parameter(p); - if !p.at(R_PAREN) { - p.expect(COMMA); - } - } - p.expect(R_PAREN); - m.complete(p, PARAM_LIST); - - fn value_parameter(p: &mut Parser) { - let m = p.start(); - patterns::pattern(p); - p.expect(COLON); - types::type_(p); - m.complete(p, VALUE_PARAMETER); - } - - // test self_param - // impl S { - // fn a(self) {} - // fn b(&self,) {} - // fn c(&'a self,) {} - // fn d(&'a mut self, x: i32) {} - // } - fn self_param(p: &mut Parser) { - let la1 = p.nth(1); - let la2 = p.nth(2); - let la3 = p.nth(3); - let n_toks = match (p.current(), la1, la2, la3) { - (SELF_KW, _, _, _) => 1, - (AMPERSAND, SELF_KW, _, _) => 2, - (AMPERSAND, MUT_KW, SELF_KW, _) => 3, - (AMPERSAND, LIFETIME, SELF_KW, _) => 3, - (AMPERSAND, LIFETIME, MUT_KW, SELF_KW) => 4, - _ => return, - }; - let m = p.start(); - for _ in 0..n_toks { - p.bump(); - } - m.complete(p, SELF_PARAM); - if !p.at(R_PAREN) { - p.expect(COMMA); - } - } -} - -fn fn_ret_type(p: &mut Parser) { +fn fn_ret_type(p: &mut Parser) -> bool { if p.at(THIN_ARROW) { p.bump(); types::type_(p); + true + } else { + false } } diff --git a/src/parser/grammar/params.rs b/src/parser/grammar/params.rs new file mode 100644 index 000000000..1ef2cea88 --- /dev/null +++ b/src/parser/grammar/params.rs @@ -0,0 +1,71 @@ +use super::*; + +// test param_list +// fn a() {} +// fn b(x: i32) {} +// fn c(x: i32, ) {} +// fn d(x: i32, y: ()) {} +pub(super) fn list(p: &mut Parser) { + list_(p, true) +} + +pub(super) fn list_opt_types(p: &mut Parser) { + list_(p, false) +} + +fn list_(p: &mut Parser, require_types: bool) { + assert!(p.at(if require_types { L_PAREN } else { PIPE })); + let m = p.start(); + p.bump(); + if require_types { + self_param(p); + } + let terminator = if require_types { R_PAREN } else { PIPE }; + while !p.at(EOF) && !p.at(terminator) { + value_parameter(p, require_types); + if !p.at(terminator) { + p.expect(COMMA); + } + } + p.expect(terminator); + m.complete(p, PARAM_LIST); +} + +fn value_parameter(p: &mut Parser, require_type: bool) { + let m = p.start(); + patterns::pattern(p); + if p.at(COLON) || require_type { + types::ascription(p) + } + m.complete(p, VALUE_PARAMETER); +} + +// test self_param +// impl S { +// fn a(self) {} +// fn b(&self,) {} +// fn c(&'a self,) {} +// fn d(&'a mut self, x: i32) {} +// } +fn self_param(p: &mut Parser) { + let la1 = p.nth(1); + let la2 = p.nth(2); + let la3 = p.nth(3); + let n_toks = match (p.current(), la1, la2, la3) { + (SELF_KW, _, _, _) => 1, + (AMPERSAND, SELF_KW, _, _) => 2, + (AMPERSAND, MUT_KW, SELF_KW, _) => 3, + (AMPERSAND, LIFETIME, SELF_KW, _) => 3, + (AMPERSAND, LIFETIME, MUT_KW, SELF_KW) => 4, + _ => return, + }; + let m = p.start(); + for _ in 0..n_toks { + p.bump(); + } + m.complete(p, SELF_PARAM); + if !p.at(R_PAREN) { + p.expect(COMMA); + } +} + diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs index 31871ceec..6535f6872 100644 --- a/src/parser/grammar/types.rs +++ b/src/parser/grammar/types.rs @@ -166,7 +166,7 @@ fn fn_pointer_type(p: &mut Parser) { return; } - fn_value_parameters(p); + params::list(p); // test fn_pointer_type_with_ret // type F = fn() -> (); fn_ret_type(p); diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 156d42db4..93a3250a4 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -122,6 +122,7 @@ pub enum SyntaxKind { FIELD_EXPR, REF_EXPR, DEREF_EXPR, + LAMBDA_EXPR, STRUCT_LIT, STRUCT_LIT_FIELD, EXTERN_BLOCK, @@ -140,7 +141,6 @@ pub enum SyntaxKind { ABI, NAME, NAME_REF, - VALUE_PARAMETER, BLOCK, LET_STMT, EXPR_STMT, @@ -152,6 +152,7 @@ pub enum SyntaxKind { TYPE_ARG, ASSOC_TYPE_ARG, PARAM_LIST, + VALUE_PARAMETER, SELF_PARAM, ARG_LIST, // Technical SyntaxKinds: they appear temporally during parsing, @@ -283,6 +284,7 @@ impl SyntaxKind { FIELD_EXPR => &SyntaxInfo { name: "FIELD_EXPR" }, REF_EXPR => &SyntaxInfo { name: "REF_EXPR" }, DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" }, + LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" }, STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" }, STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" }, EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" }, @@ -301,7 +303,6 @@ impl SyntaxKind { ABI => &SyntaxInfo { name: "ABI" }, NAME => &SyntaxInfo { name: "NAME" }, NAME_REF => &SyntaxInfo { name: "NAME_REF" }, - VALUE_PARAMETER => &SyntaxInfo { name: "VALUE_PARAMETER" }, BLOCK => &SyntaxInfo { name: "BLOCK" }, LET_STMT => &SyntaxInfo { name: "LET_STMT" }, EXPR_STMT => &SyntaxInfo { name: "EXPR_STMT" }, @@ -313,6 +314,7 @@ impl SyntaxKind { TYPE_ARG => &SyntaxInfo { name: "TYPE_ARG" }, ASSOC_TYPE_ARG => &SyntaxInfo { name: "ASSOC_TYPE_ARG" }, PARAM_LIST => &SyntaxInfo { name: "PARAM_LIST" }, + VALUE_PARAMETER => &SyntaxInfo { name: "VALUE_PARAMETER" }, SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" }, ARG_LIST => &SyntaxInfo { name: "ARG_LIST" }, TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, -- cgit v1.2.3