From c244dd10343ff96a73879c593bd9253c4073cb90 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Jul 2018 12:26:19 +0300 Subject: Call expr --- src/grammar.ron | 1 + src/parser/grammar/attributes.rs | 4 +- src/parser/grammar/expressions.rs | 61 ++++++++++++++++++++------- src/parser/grammar/mod.rs | 2 +- src/syntax_kinds/generated.rs | 2 + tests/data/parser/inline/0043_call_expr.rs | 4 ++ tests/data/parser/inline/0043_call_expr.txt | 65 +++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 17 deletions(-) create mode 100644 tests/data/parser/inline/0043_call_expr.rs create mode 100644 tests/data/parser/inline/0043_call_expr.txt diff --git a/src/grammar.ron b/src/grammar.ron index 3efd60ee5..5b8a9219c 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -125,6 +125,7 @@ Grammar( "TUPLE_EXPR", "PATH_EXPR", + "CALL_EXPR", "EXTERN_BLOCK", "ENUM_VARIANT", diff --git a/src/parser/grammar/attributes.rs b/src/parser/grammar/attributes.rs index 7f1c0401a..c411d4d7f 100644 --- a/src/parser/grammar/attributes.rs +++ b/src/parser/grammar/attributes.rs @@ -36,7 +36,7 @@ fn meta_item(p: &mut Parser) { match p.current() { EQ => { p.bump(); - if !expressions::literal(p) { + if expressions::literal(p).is_none() { p.error("expected literal"); } } @@ -56,7 +56,7 @@ fn meta_item_arg_list(p: &mut Parser) { match p.current() { EOF | R_PAREN => break, IDENT => meta_item(p), - c => if !expressions::literal(p) { + c => if expressions::literal(p).is_none() { let message = "expected attribute"; if items::ITEM_FIRST.contains(c) { diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs index ece698248..92aaafa3d 100644 --- a/src/parser/grammar/expressions.rs +++ b/src/parser/grammar/expressions.rs @@ -13,39 +13,72 @@ use super::*; // let _ = b"e"; // let _ = br"f"; // } -pub(super) fn literal(p: &mut Parser) -> bool { +pub(super) fn literal(p: &mut Parser) -> Option { match p.current() { TRUE_KW | FALSE_KW | INT_NUMBER | FLOAT_NUMBER | BYTE | CHAR | STRING | RAW_STRING | BYTE_STRING | RAW_BYTE_STRING => { - let lit = p.start(); + let m = p.start(); p.bump(); - lit.complete(p, LITERAL); - true + Some(m.complete(p, LITERAL)) } - _ => false, + _ => None, } } pub(super) fn expr(p: &mut Parser) { - if literal(p) { - return; + let mut lhs = atom_expr(p); + + while let Some(m) = lhs { + match p.current() { + L_PAREN => lhs = Some(call_expr(p, m)), + _ => break, + } + } +} + +fn atom_expr(p: &mut Parser) -> Option { + match literal(p) { + Some(m) => return Some(m), + None => (), } if paths::is_path_start(p) { - return path_expr(p); + return Some(path_expr(p)); } match p.current() { - L_PAREN => tuple_expr(p), - _ => p.error("expected expression"), + L_PAREN => Some(tuple_expr(p)), + _ => { + p.error("expected expression"); + None + } } } -fn tuple_expr(p: &mut Parser) { +fn tuple_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(L_PAREN)); let m = p.start(); p.expect(L_PAREN); p.expect(R_PAREN); - m.complete(p, TUPLE_EXPR); + m.complete(p, TUPLE_EXPR) +} + +// test call_expr +// fn foo() { +// let _ = f(); +// let _ = f()(1)(1, 2,); +// } +fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { + assert!(p.at(L_PAREN)); + let m = lhs.precede(p); + p.bump(); + while !p.at(R_PAREN) && !p.at(EOF) { + expr(p); + if !p.at(R_PAREN) && !p.expect(COMMA) { + break; + } + } + p.eat(R_PAREN); + m.complete(p, CALL_EXPR) } // test path_expr @@ -54,9 +87,9 @@ fn tuple_expr(p: &mut Parser) { // let _ = a::b; // let _ = ::a::; // } -fn path_expr(p: &mut Parser) { +fn path_expr(p: &mut Parser) -> CompletedMarker { assert!(paths::is_path_start(p)); let m = p.start(); paths::expr_path(p); - m.complete(p, PATH_EXPR); + m.complete(p, PATH_EXPR) } diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs index e4823eadb..63ad2782e 100644 --- a/src/parser/grammar/mod.rs +++ b/src/parser/grammar/mod.rs @@ -31,7 +31,7 @@ mod type_args; mod types; use { - parser::{parser::Parser, token_set::TokenSet}, + parser::{parser::{Parser, CompletedMarker}, token_set::TokenSet}, SyntaxKind::{self, *}, }; diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 571b64af4..1d0f1b724 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -116,6 +116,7 @@ pub enum SyntaxKind { PLACEHOLDER_PAT, TUPLE_EXPR, PATH_EXPR, + CALL_EXPR, EXTERN_BLOCK, ENUM_VARIANT, NAMED_FIELD, @@ -262,6 +263,7 @@ impl SyntaxKind { PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" }, + CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" }, EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, diff --git a/tests/data/parser/inline/0043_call_expr.rs b/tests/data/parser/inline/0043_call_expr.rs new file mode 100644 index 000000000..0c9a20718 --- /dev/null +++ b/tests/data/parser/inline/0043_call_expr.rs @@ -0,0 +1,4 @@ +fn foo() { + let _ = f(); + let _ = f()(1)(1, 2,); +} diff --git a/tests/data/parser/inline/0043_call_expr.txt b/tests/data/parser/inline/0043_call_expr.txt new file mode 100644 index 000000000..418d86270 --- /dev/null +++ b/tests/data/parser/inline/0043_call_expr.txt @@ -0,0 +1,65 @@ +FILE@[0; 57) + FN_ITEM@[0; 57) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + L_PAREN@[6; 7) + R_PAREN@[7; 8) + BLOCK@[8; 57) + WHITESPACE@[8; 9) + L_CURLY@[9; 10) + LET_STMT@[10; 32) + WHITESPACE@[10; 15) + LET_KW@[15; 18) + PLACEHOLDER_PAT@[18; 21) + WHITESPACE@[18; 19) + UNDERSCORE@[19; 20) + WHITESPACE@[20; 21) + EQ@[21; 22) + CALL_EXPR@[22; 26) + PATH_EXPR@[22; 24) + PATH@[22; 24) + PATH_SEGMENT@[22; 24) + NAME_REF@[22; 24) + WHITESPACE@[22; 23) + IDENT@[23; 24) "f" + L_PAREN@[24; 25) + R_PAREN@[25; 26) + SEMI@[26; 27) + WHITESPACE@[27; 32) + LET_STMT@[32; 55) + LET_KW@[32; 35) + PLACEHOLDER_PAT@[35; 38) + WHITESPACE@[35; 36) + UNDERSCORE@[36; 37) + WHITESPACE@[37; 38) + EQ@[38; 39) + CALL_EXPR@[39; 53) + CALL_EXPR@[39; 46) + CALL_EXPR@[39; 43) + PATH_EXPR@[39; 41) + PATH@[39; 41) + PATH_SEGMENT@[39; 41) + NAME_REF@[39; 41) + WHITESPACE@[39; 40) + IDENT@[40; 41) "f" + L_PAREN@[41; 42) + R_PAREN@[42; 43) + L_PAREN@[43; 44) + LITERAL@[44; 45) + INT_NUMBER@[44; 45) + R_PAREN@[45; 46) + L_PAREN@[46; 47) + LITERAL@[47; 48) + INT_NUMBER@[47; 48) + COMMA@[48; 49) + LITERAL@[49; 51) + WHITESPACE@[49; 50) + INT_NUMBER@[50; 51) + COMMA@[51; 52) + R_PAREN@[52; 53) + SEMI@[53; 54) + WHITESPACE@[54; 55) + R_CURLY@[55; 56) + WHITESPACE@[56; 57) -- cgit v1.2.3