From a750135a0ac5a42035a1baa808e0af8ae562cd72 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 1 Aug 2018 00:14:26 +0300 Subject: If expr --- src/grammar.ron | 2 + src/grammar/expressions.rs | 35 +++++++++-- src/syntax_kinds/generated.rs | 6 ++ tests/data/lexer/0011_keywords.rs | 2 +- tests/data/lexer/0011_keywords.txt | 2 + tests/data/parser/err/0008_item_block_recovery.txt | 2 +- tests/data/parser/inline/0065_if_expr.rs | 5 ++ tests/data/parser/inline/0065_if_expr.txt | 73 ++++++++++++++++++++++ 8 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 tests/data/parser/inline/0065_if_expr.rs create mode 100644 tests/data/parser/inline/0065_if_expr.txt diff --git a/src/grammar.ron b/src/grammar.ron index a9a3847c9..9912f9698 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -60,6 +60,7 @@ Grammar( "loop", "while", "if", + "else", "match", "const", "static", @@ -134,6 +135,7 @@ Grammar( "LAMBDA_EXPR", "STRUCT_LIT", "STRUCT_LIT_FIELD", + "IF_EXPR", "EXTERN_BLOCK", "ENUM_VARIANT", diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs index e2be13a77..ed9236b02 100644 --- a/src/grammar/expressions.rs +++ b/src/grammar/expressions.rs @@ -145,14 +145,16 @@ fn atom_expr(p: &mut Parser) -> Option { return Some(path_expr(p)); } - match p.current() { - L_PAREN => Some(tuple_expr(p)), - PIPE => Some(lambda_expr(p)), + let done = match p.current() { + L_PAREN => tuple_expr(p), + PIPE => lambda_expr(p), + IF_KW => if_expr(p), _ => { p.err_and_bump("expected expression"); - None + return None; } - } + }; + Some(done) } fn tuple_expr(p: &mut Parser) -> CompletedMarker { @@ -182,6 +184,29 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { m.complete(p, LAMBDA_EXPR) } +// test if_expr +// fn foo() { +// if true {}; +// if true {} else {}; +// if true {} else if false {} else {} +// } +fn if_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(IF_KW)); + let m = p.start(); + p.bump(); + expr(p); + block(p); + if p.at(ELSE_KW) { + p.bump(); + if p.at(IF_KW) { + if_expr(p); + } else { + block(p); + } + } + m.complete(p, IF_EXPR) +} + // test call_expr // fn foo() { // let _ = f(); diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 2f7c29008..35d9640fa 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -61,6 +61,7 @@ pub enum SyntaxKind { LOOP_KW, WHILE_KW, IF_KW, + ELSE_KW, MATCH_KW, CONST_KW, STATIC_KW, @@ -125,6 +126,7 @@ pub enum SyntaxKind { LAMBDA_EXPR, STRUCT_LIT, STRUCT_LIT_FIELD, + IF_EXPR, EXTERN_BLOCK, ENUM_VARIANT, NAMED_FIELD, @@ -223,6 +225,7 @@ impl SyntaxKind { LOOP_KW => &SyntaxInfo { name: "LOOP_KW" }, WHILE_KW => &SyntaxInfo { name: "WHILE_KW" }, IF_KW => &SyntaxInfo { name: "IF_KW" }, + ELSE_KW => &SyntaxInfo { name: "ELSE_KW" }, MATCH_KW => &SyntaxInfo { name: "MATCH_KW" }, CONST_KW => &SyntaxInfo { name: "CONST_KW" }, STATIC_KW => &SyntaxInfo { name: "STATIC_KW" }, @@ -287,6 +290,7 @@ impl SyntaxKind { LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" }, STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" }, STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" }, + IF_EXPR => &SyntaxInfo { name: "IF_EXPR" }, EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, @@ -344,6 +348,7 @@ impl SyntaxKind { "loop" => LOOP_KW, "while" => WHILE_KW, "if" => IF_KW, + "else" => ELSE_KW, "match" => MATCH_KW, "const" => CONST_KW, "static" => STATIC_KW, @@ -445,6 +450,7 @@ impl SyntaxKind { LOOP_KW => "loop", WHILE_KW => "while", IF_KW => "if", + ELSE_KW => "else", MATCH_KW => "match", CONST_KW => "const", STATIC_KW => "static", diff --git a/tests/data/lexer/0011_keywords.rs b/tests/data/lexer/0011_keywords.rs index 97ff3f954..2a78b5dd2 100644 --- a/tests/data/lexer/0011_keywords.rs +++ b/tests/data/lexer/0011_keywords.rs @@ -1,3 +1,3 @@ fn use struct trait enum impl true false as extern crate mod pub self super in where for loop while if match const -static mut type ref let +static mut type ref let else diff --git a/tests/data/lexer/0011_keywords.txt b/tests/data/lexer/0011_keywords.txt index 851a671f5..e25d7d4b4 100644 --- a/tests/data/lexer/0011_keywords.txt +++ b/tests/data/lexer/0011_keywords.txt @@ -53,4 +53,6 @@ WHITESPACE 1 " " REF_KW 3 "ref" WHITESPACE 1 " " LET_KW 3 "let" +WHITESPACE 1 " " +ELSE_KW 4 "else" WHITESPACE 1 "\n" diff --git a/tests/data/parser/err/0008_item_block_recovery.txt b/tests/data/parser/err/0008_item_block_recovery.txt index 40ce2bc1a..81a5dd4c3 100644 --- a/tests/data/parser/err/0008_item_block_recovery.txt +++ b/tests/data/parser/err/0008_item_block_recovery.txt @@ -37,7 +37,7 @@ FILE@[0; 95) WHITESPACE@[45; 50) R_CURLY@[50; 51) WHITESPACE@[51; 52) - IDENT@[52; 56) "else" + ELSE_KW@[52; 56) WHITESPACE@[56; 57) L_CURLY@[57; 58) WHITESPACE@[58; 67) diff --git a/tests/data/parser/inline/0065_if_expr.rs b/tests/data/parser/inline/0065_if_expr.rs new file mode 100644 index 000000000..f1691c159 --- /dev/null +++ b/tests/data/parser/inline/0065_if_expr.rs @@ -0,0 +1,5 @@ +fn foo() { + if true {}; + if true {} else {}; + if true {} else if false {} else {} +} diff --git a/tests/data/parser/inline/0065_if_expr.txt b/tests/data/parser/inline/0065_if_expr.txt new file mode 100644 index 000000000..5d9bdfb13 --- /dev/null +++ b/tests/data/parser/inline/0065_if_expr.txt @@ -0,0 +1,73 @@ +FILE@[0; 93) + FN_ITEM@[0; 93) + 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@[9; 93) + L_CURLY@[9; 10) + EXPR_STMT@[10; 31) + IF_EXPR@[10; 25) + WHITESPACE@[10; 15) + IF_KW@[15; 17) + LITERAL@[17; 23) + WHITESPACE@[17; 18) + TRUE_KW@[18; 22) + WHITESPACE@[22; 23) + BLOCK@[23; 25) + L_CURLY@[23; 24) + R_CURLY@[24; 25) + SEMI@[25; 26) + WHITESPACE@[26; 31) + EXPR_STMT@[31; 55) + IF_EXPR@[31; 49) + IF_KW@[31; 33) + LITERAL@[33; 39) + WHITESPACE@[33; 34) + TRUE_KW@[34; 38) + WHITESPACE@[38; 39) + BLOCK@[39; 42) + L_CURLY@[39; 40) + R_CURLY@[40; 41) + WHITESPACE@[41; 42) + ELSE_KW@[42; 46) + BLOCK@[46; 49) + WHITESPACE@[46; 47) + L_CURLY@[47; 48) + R_CURLY@[48; 49) + SEMI@[49; 50) + WHITESPACE@[50; 55) + IF_EXPR@[55; 91) + IF_KW@[55; 57) + LITERAL@[57; 63) + WHITESPACE@[57; 58) + TRUE_KW@[58; 62) + WHITESPACE@[62; 63) + BLOCK@[63; 66) + L_CURLY@[63; 64) + R_CURLY@[64; 65) + WHITESPACE@[65; 66) + ELSE_KW@[66; 70) + IF_EXPR@[70; 91) + WHITESPACE@[70; 71) + IF_KW@[71; 73) + LITERAL@[73; 80) + WHITESPACE@[73; 74) + FALSE_KW@[74; 79) + WHITESPACE@[79; 80) + BLOCK@[80; 83) + L_CURLY@[80; 81) + R_CURLY@[81; 82) + WHITESPACE@[82; 83) + ELSE_KW@[83; 87) + BLOCK@[87; 91) + WHITESPACE@[87; 88) + L_CURLY@[88; 89) + R_CURLY@[89; 90) + WHITESPACE@[90; 91) + R_CURLY@[91; 92) + WHITESPACE@[92; 93) -- cgit v1.2.3