From b0291cd8c2ec1d6d164caaa743f7484416e9b3f5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 5 Aug 2018 18:07:06 +0300 Subject: Range expr --- src/grammar.ron | 1 + src/grammar/expressions/mod.rs | 37 ++++++++--- src/syntax_kinds/generated.rs | 2 + .../data/parser/inline/0082_range_binding_power.rs | 5 ++ .../parser/inline/0082_range_binding_power.txt | 72 ++++++++++++++++++++++ tests/data/parser/inline/0083_postfix_range.rs | 1 + tests/data/parser/inline/0083_postfix_range.txt | 30 +++++++++ 7 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 tests/data/parser/inline/0082_range_binding_power.rs create mode 100644 tests/data/parser/inline/0082_range_binding_power.txt create mode 100644 tests/data/parser/inline/0083_postfix_range.rs create mode 100644 tests/data/parser/inline/0083_postfix_range.txt diff --git a/src/grammar.ron b/src/grammar.ron index 1eb76abdd..9e122091b 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -163,6 +163,7 @@ Grammar( "DEREF_EXPR", "NOT_EXPR", + "RANGE_EXPR", // just weird "BIN_EXPR", diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index 7f3bc78f2..0312a757a 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs @@ -44,6 +44,13 @@ enum Op { // *x = 1 + 1; // } +// test range_binding_power +// fn foo() { +// .. 1 + 1; +// .. z = 2; +// x = false .. 1 == 1; +// } + // test compound_ops // fn foo() { // x += 1; @@ -52,10 +59,10 @@ enum Op { // } fn current_op(p: &Parser) -> (u8, Op) { if p.at_compound2(L_ANGLE, EQ) { - return (2, Op::Composite(LTEQ, 2)); + return (3, Op::Composite(LTEQ, 2)); } if p.at_compound2(R_ANGLE, EQ) { - return (2, Op::Composite(GTEQ, 2)); + return (3, Op::Composite(GTEQ, 2)); } if p.at_compound2(PLUS, EQ) { return (1, Op::Composite(PLUSEQ, 2)); @@ -66,9 +73,10 @@ fn current_op(p: &Parser) -> (u8, Op) { let bp = match p.current() { EQ => 1, - EQEQ | NEQ => 2, - MINUS | PLUS => 3, - STAR | SLASH => 4, + DOTDOT => 2, + EQEQ | NEQ => 3, + MINUS | PLUS => 4, + STAR | SLASH => 5, _ => 0, }; (bp, Op::Simple) @@ -76,7 +84,7 @@ fn current_op(p: &Parser) -> (u8, Op) { // Parses expression with binding power of at least bp. fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { - let mut lhs = match unary_expr(p, r) { + let mut lhs = match lhs(p, r) { Some(lhs) => lhs, None => return, }; @@ -102,7 +110,7 @@ const UNARY_EXPR_FIRST: TokenSet = atom::ATOM_EXPR_FIRST, ]; -fn unary_expr(p: &mut Parser, r: Restrictions) -> Option { +fn lhs(p: &mut Parser, r: Restrictions) -> Option { let m; let kind = match p.current() { // test ref_expr @@ -134,12 +142,18 @@ fn unary_expr(p: &mut Parser, r: Restrictions) -> Option { p.bump(); NOT_EXPR } + DOTDOT => { + m = p.start(); + p.bump(); + expr_bp(p, r, 2); + return Some(m.complete(p, RANGE_EXPR)); + } _ => { let lhs = atom::atom_expr(p, r)?; return Some(postfix_expr(p, lhs)); } }; - unary_expr(p, r); + expr_bp(p, r, 255); Some(m.complete(p, kind)) } @@ -154,6 +168,13 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { field_expr(p, lhs) }, DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs), + // test postfix_range + // fn foo() { let x = 1..; } + DOTDOT if !EXPR_FIRST.contains(p.nth(1)) => { + let m = lhs.precede(p); + p.bump(); + m.complete(p, RANGE_EXPR) + } QUESTION => try_expr(p, lhs), _ => break, } diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 8855e980e..8db006e54 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -148,6 +148,7 @@ pub enum SyntaxKind { REF_EXPR, DEREF_EXPR, NOT_EXPR, + RANGE_EXPR, BIN_EXPR, EXTERN_BLOCK_EXPR, ENUM_VARIANT, @@ -375,6 +376,7 @@ impl SyntaxKind { REF_EXPR => &SyntaxInfo { name: "REF_EXPR" }, DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" }, NOT_EXPR => &SyntaxInfo { name: "NOT_EXPR" }, + RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" }, BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" }, EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, diff --git a/tests/data/parser/inline/0082_range_binding_power.rs b/tests/data/parser/inline/0082_range_binding_power.rs new file mode 100644 index 000000000..259ec31e2 --- /dev/null +++ b/tests/data/parser/inline/0082_range_binding_power.rs @@ -0,0 +1,5 @@ +fn foo() { + .. 1 + 1; + .. z = 2; + x = false .. 1 == 1; +} diff --git a/tests/data/parser/inline/0082_range_binding_power.txt b/tests/data/parser/inline/0082_range_binding_power.txt new file mode 100644 index 000000000..0b7bfd56a --- /dev/null +++ b/tests/data/parser/inline/0082_range_binding_power.txt @@ -0,0 +1,72 @@ +FILE@[0; 66) + FN_ITEM@[0; 66) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 9) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 66) + L_CURLY@[9; 10) + EXPR_STMT@[10; 29) + RANGE_EXPR@[10; 23) + WHITESPACE@[10; 15) + DOTDOT@[15; 17) + BIN_EXPR@[17; 23) + LITERAL@[17; 20) + WHITESPACE@[17; 18) + INT_NUMBER@[18; 19) "1" + WHITESPACE@[19; 20) + PLUS@[20; 21) + LITERAL@[21; 23) + WHITESPACE@[21; 22) + INT_NUMBER@[22; 23) "1" + SEMI@[23; 24) + WHITESPACE@[24; 29) + EXPR_STMT@[29; 43) + BIN_EXPR@[29; 37) + RANGE_EXPR@[29; 34) + DOTDOT@[29; 31) + PATH_EXPR@[31; 34) + PATH@[31; 34) + PATH_SEGMENT@[31; 34) + NAME_REF@[31; 34) + WHITESPACE@[31; 32) + IDENT@[32; 33) "z" + WHITESPACE@[33; 34) + EQ@[34; 35) + LITERAL@[35; 37) + WHITESPACE@[35; 36) + INT_NUMBER@[36; 37) "2" + SEMI@[37; 38) + WHITESPACE@[38; 43) + EXPR_STMT@[43; 64) + BIN_EXPR@[43; 62) + PATH_EXPR@[43; 45) + PATH@[43; 45) + PATH_SEGMENT@[43; 45) + NAME_REF@[43; 45) + IDENT@[43; 44) "x" + WHITESPACE@[44; 45) + EQ@[45; 46) + BIN_EXPR@[46; 62) + LITERAL@[46; 53) + WHITESPACE@[46; 47) + FALSE_KW@[47; 52) + WHITESPACE@[52; 53) + DOTDOT@[53; 55) + BIN_EXPR@[55; 62) + LITERAL@[55; 58) + WHITESPACE@[55; 56) + INT_NUMBER@[56; 57) "1" + WHITESPACE@[57; 58) + EQEQ@[58; 60) + LITERAL@[60; 62) + WHITESPACE@[60; 61) + INT_NUMBER@[61; 62) "1" + SEMI@[62; 63) + WHITESPACE@[63; 64) + R_CURLY@[64; 65) + WHITESPACE@[65; 66) diff --git a/tests/data/parser/inline/0083_postfix_range.rs b/tests/data/parser/inline/0083_postfix_range.rs new file mode 100644 index 000000000..c39fe8e68 --- /dev/null +++ b/tests/data/parser/inline/0083_postfix_range.rs @@ -0,0 +1 @@ +fn foo() { let x = 1..; } diff --git a/tests/data/parser/inline/0083_postfix_range.txt b/tests/data/parser/inline/0083_postfix_range.txt new file mode 100644 index 000000000..6a77e3a71 --- /dev/null +++ b/tests/data/parser/inline/0083_postfix_range.txt @@ -0,0 +1,30 @@ +FILE@[0; 26) + FN_ITEM@[0; 26) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 9) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 26) + L_CURLY@[9; 10) + LET_STMT@[10; 24) + WHITESPACE@[10; 11) + LET_KW@[11; 14) + BIND_PAT@[14; 17) + NAME@[14; 17) + WHITESPACE@[14; 15) + IDENT@[15; 16) "x" + WHITESPACE@[16; 17) + EQ@[17; 18) + RANGE_EXPR@[18; 22) + LITERAL@[18; 20) + WHITESPACE@[18; 19) + INT_NUMBER@[19; 20) "1" + DOTDOT@[20; 22) + SEMI@[22; 23) + WHITESPACE@[23; 24) + R_CURLY@[24; 25) + WHITESPACE@[25; 26) -- cgit v1.2.3