diff --git a/src/grammar.ron b/src/grammar.ron index d5d2e6162e..8232ba1dc3 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -120,6 +120,7 @@ Grammar( "PLACEHOLDER_PAT", "TUPLE_EXPR", + "PATH_EXPR", "EXTERN_BLOCK", "ENUM_VARIANT", @@ -133,15 +134,18 @@ Grammar( "LITERAL", "ALIAS", "VISIBILITY", - "TYPE_PARAM_LIST", "WHERE_CLAUSE", - "LIFETIME_PARAM", - "TYPE_PARAM", "ABI", "NAME", "NAME_REF", "VALUE_PARAMETER", "BLOCK", "LET_STMT", + + "TYPE_PARAM", + "LIFETIME_PARAM", + "TYPE_PARAM_LIST", + "TYPE_ARG_LIST", + ] ) diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs index 40f41535e6..ece6982483 100644 --- a/src/parser/grammar/expressions.rs +++ b/src/parser/grammar/expressions.rs @@ -2,7 +2,16 @@ use super::*; // test expr_literals // fn foo() { -// let _ = 92; +// let _ = true; +// let _ = false; +// let _ = 1; +// let _ = 2.0; +// let _ = b'a'; +// let _ = 'b'; +// let _ = "c"; +// let _ = r"d"; +// let _ = b"e"; +// let _ = br"f"; // } pub(super) fn literal(p: &mut Parser) -> bool { match p.current() { @@ -21,6 +30,9 @@ pub(super) fn expr(p: &mut Parser) { if literal(p) { return; } + if paths::is_path_start(p) { + return path_expr(p); + } match p.current() { L_PAREN => tuple_expr(p), @@ -35,3 +47,16 @@ fn tuple_expr(p: &mut Parser) { p.expect(R_PAREN); m.complete(p, TUPLE_EXPR); } + +// test path_expr +// fn foo() { +// let _ = a; +// let _ = a::b; +// let _ = ::a::; +// } +fn path_expr(p: &mut Parser) { + assert!(paths::is_path_start(p)); + let m = p.start(); + paths::expr_path(p); + m.complete(p, PATH_EXPR); +} diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs index e24f1055ef..e4823eadbf 100644 --- a/src/parser/grammar/mod.rs +++ b/src/parser/grammar/mod.rs @@ -27,6 +27,7 @@ mod items; mod paths; mod patterns; mod type_params; +mod type_args; mod types; use { diff --git a/src/parser/grammar/paths.rs b/src/parser/grammar/paths.rs index d3eb20ea14..69ed84665a 100644 --- a/src/parser/grammar/paths.rs +++ b/src/parser/grammar/paths.rs @@ -8,19 +8,26 @@ pub(super) fn is_path_start(p: &Parser) -> bool { } pub(super) fn use_path(p: &mut Parser) { - path(p) + path(p, Mode::Use) } pub(super) fn type_path(p: &mut Parser) { - path(p) + path(p, Mode::Type) } -fn path(p: &mut Parser) { +pub(super) fn expr_path(p: &mut Parser) { + path(p, Mode::Expr) +} + +#[derive(Clone, Copy, Eq, PartialEq)] +enum Mode { Use, Type, Expr } + +fn path(p: &mut Parser, mode: Mode) { if !is_path_start(p) { return; } let path = p.start(); - path_segment(p, true); + path_segment(p, mode, true); let mut qual = path.complete(p, PATH); loop { let use_tree = match p.nth(1) { @@ -30,7 +37,7 @@ fn path(p: &mut Parser) { if p.at(COLONCOLON) && !use_tree { let path = qual.precede(p); p.bump(); - path_segment(p, false); + path_segment(p, mode, false); let path = path.complete(p, PATH); qual = path; } else { @@ -39,13 +46,16 @@ fn path(p: &mut Parser) { } } -fn path_segment(p: &mut Parser, first: bool) { +fn path_segment(p: &mut Parser, mode: Mode, first: bool) { let segment = p.start(); if first { p.eat(COLONCOLON); } match p.current() { - IDENT => name_ref(p), + IDENT => { + name_ref(p); + path_generic_args(p, mode); + }, SELF_KW | SUPER_KW => p.bump(), _ => { p.error("expected identifier"); @@ -53,3 +63,11 @@ fn path_segment(p: &mut Parser, first: bool) { }; segment.complete(p, PATH_SEGMENT); } + +fn path_generic_args(p: &mut Parser, mode: Mode) { + match mode { + Mode::Use => return, + Mode::Type => type_args::list(p, false), + Mode::Expr => type_args::list(p, true), + } +} diff --git a/src/parser/grammar/type_args.rs b/src/parser/grammar/type_args.rs new file mode 100644 index 0000000000..20e75b4b0d --- /dev/null +++ b/src/parser/grammar/type_args.rs @@ -0,0 +1,26 @@ +use super::*; + +pub(super) fn list(p: &mut Parser, colon_colon_required: bool) { + let m; + match (colon_colon_required, p.nth(0), p.nth(1)) { + (_, COLONCOLON, L_ANGLE) => { + m = p.start(); + p.bump(); + p.bump(); + } + (false, L_ANGLE, _) => { + m = p.start(); + p.bump(); + } + _ => return + }; + + while !p.at(EOF) && !p.at(R_ANGLE) { + types::type_(p); + if !p.at(R_ANGLE) && !p.expect(COMMA) { + break; + } + } + p.expect(R_ANGLE); + m.complete(p, TYPE_ARG_LIST); +} diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 029972bb3a..bc2a995f6a 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -115,6 +115,7 @@ pub enum SyntaxKind { BIND_PAT, PLACEHOLDER_PAT, TUPLE_EXPR, + PATH_EXPR, EXTERN_BLOCK, ENUM_VARIANT, NAMED_FIELD, @@ -127,16 +128,17 @@ pub enum SyntaxKind { LITERAL, ALIAS, VISIBILITY, - TYPE_PARAM_LIST, WHERE_CLAUSE, - LIFETIME_PARAM, - TYPE_PARAM, ABI, NAME, NAME_REF, VALUE_PARAMETER, BLOCK, LET_STMT, + TYPE_PARAM, + LIFETIME_PARAM, + TYPE_PARAM_LIST, + TYPE_ARG_LIST, // Technical SyntaxKinds: they appear temporally during parsing, // but never end up in the final tree #[doc(hidden)] @@ -259,6 +261,7 @@ impl SyntaxKind { BIND_PAT => &SyntaxInfo { name: "BIND_PAT" }, PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, + PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" }, EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, @@ -271,16 +274,17 @@ impl SyntaxKind { LITERAL => &SyntaxInfo { name: "LITERAL" }, ALIAS => &SyntaxInfo { name: "ALIAS" }, VISIBILITY => &SyntaxInfo { name: "VISIBILITY" }, - TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" }, WHERE_CLAUSE => &SyntaxInfo { name: "WHERE_CLAUSE" }, - LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" }, - TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" }, 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" }, + TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" }, + LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" }, + TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" }, + TYPE_ARG_LIST => &SyntaxInfo { name: "TYPE_ARG_LIST" }, TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, EOF => &SyntaxInfo { name: "EOF" }, diff --git a/tests/data/parser/inline/0039_path_expr.rs b/tests/data/parser/inline/0039_path_expr.rs new file mode 100644 index 0000000000..e9855bad7c --- /dev/null +++ b/tests/data/parser/inline/0039_path_expr.rs @@ -0,0 +1,5 @@ +fn foo() { + let _ = a; + let _ = a::b; + let _ = ::a::; +} diff --git a/tests/data/parser/inline/0039_path_expr.txt b/tests/data/parser/inline/0039_path_expr.txt new file mode 100644 index 0000000000..d149fbb759 --- /dev/null +++ b/tests/data/parser/inline/0039_path_expr.txt @@ -0,0 +1,74 @@ +FILE@[0; 68) + FN_ITEM@[0; 68) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + L_PAREN@[6; 7) + R_PAREN@[7; 8) + BLOCK@[8; 68) + WHITESPACE@[8; 9) + L_CURLY@[9; 10) + LET_STMT@[10; 30) + WHITESPACE@[10; 15) + LET_KW@[15; 18) + PLACEHOLDER_PAT@[18; 21) + WHITESPACE@[18; 19) + UNDERSCORE@[19; 20) + WHITESPACE@[20; 21) + EQ@[21; 22) + PATH_EXPR@[22; 24) + PATH@[22; 24) + PATH_SEGMENT@[22; 24) + NAME_REF@[22; 24) + WHITESPACE@[22; 23) + IDENT@[23; 24) "a" + SEMI@[24; 25) + WHITESPACE@[25; 30) + LET_STMT@[30; 48) + LET_KW@[30; 33) + PLACEHOLDER_PAT@[33; 36) + WHITESPACE@[33; 34) + UNDERSCORE@[34; 35) + WHITESPACE@[35; 36) + EQ@[36; 37) + PATH_EXPR@[37; 42) + PATH@[37; 42) + PATH@[37; 39) + PATH_SEGMENT@[37; 39) + NAME_REF@[37; 39) + WHITESPACE@[37; 38) + IDENT@[38; 39) "a" + COLONCOLON@[39; 41) + PATH_SEGMENT@[41; 42) + NAME_REF@[41; 42) + IDENT@[41; 42) "b" + SEMI@[42; 43) + WHITESPACE@[43; 48) + LET_STMT@[48; 66) + LET_KW@[48; 51) + PLACEHOLDER_PAT@[51; 54) + WHITESPACE@[51; 52) + UNDERSCORE@[52; 53) + WHITESPACE@[53; 54) + EQ@[54; 55) + PATH_EXPR@[55; 64) + PATH@[55; 64) + PATH_SEGMENT@[55; 64) + WHITESPACE@[55; 56) + COLONCOLON@[56; 58) + NAME_REF@[58; 59) + IDENT@[58; 59) "a" + TYPE_ARG_LIST@[59; 64) + COLONCOLON@[59; 61) + L_ANGLE@[61; 62) + PATH_TYPE@[62; 63) + PATH@[62; 63) + PATH_SEGMENT@[62; 63) + NAME_REF@[62; 63) + IDENT@[62; 63) "b" + R_ANGLE@[63; 64) + SEMI@[64; 65) + WHITESPACE@[65; 66) + R_CURLY@[66; 67) + WHITESPACE@[67; 68) diff --git a/tests/data/parser/inline/0040_expr_literals.rs b/tests/data/parser/inline/0040_expr_literals.rs new file mode 100644 index 0000000000..2e11a5a6e6 --- /dev/null +++ b/tests/data/parser/inline/0040_expr_literals.rs @@ -0,0 +1,12 @@ +fn foo() { + let _ = true; + let _ = false; + let _ = 1; + let _ = 2.0; + let _ = b'a'; + let _ = 'b'; + let _ = "c"; + let _ = r"d"; + let _ = b"e"; + let _ = br"f"; +} diff --git a/tests/data/parser/inline/0040_expr_literals.txt b/tests/data/parser/inline/0040_expr_literals.txt new file mode 100644 index 0000000000..83d72bf950 --- /dev/null +++ b/tests/data/parser/inline/0040_expr_literals.txt @@ -0,0 +1,134 @@ +FILE@[0; 189) + FN_ITEM@[0; 189) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + L_PAREN@[6; 7) + R_PAREN@[7; 8) + BLOCK@[8; 189) + WHITESPACE@[8; 9) + L_CURLY@[9; 10) + LET_STMT@[10; 33) + WHITESPACE@[10; 15) + LET_KW@[15; 18) + PLACEHOLDER_PAT@[18; 21) + WHITESPACE@[18; 19) + UNDERSCORE@[19; 20) + WHITESPACE@[20; 21) + EQ@[21; 22) + LITERAL@[22; 27) + WHITESPACE@[22; 23) + TRUE_KW@[23; 27) + SEMI@[27; 28) + WHITESPACE@[28; 33) + LET_STMT@[33; 52) + LET_KW@[33; 36) + PLACEHOLDER_PAT@[36; 39) + WHITESPACE@[36; 37) + UNDERSCORE@[37; 38) + WHITESPACE@[38; 39) + EQ@[39; 40) + LITERAL@[40; 46) + WHITESPACE@[40; 41) + FALSE_KW@[41; 46) + SEMI@[46; 47) + WHITESPACE@[47; 52) + LET_STMT@[52; 67) + LET_KW@[52; 55) + PLACEHOLDER_PAT@[55; 58) + WHITESPACE@[55; 56) + UNDERSCORE@[56; 57) + WHITESPACE@[57; 58) + EQ@[58; 59) + LITERAL@[59; 61) + WHITESPACE@[59; 60) + INT_NUMBER@[60; 61) + SEMI@[61; 62) + WHITESPACE@[62; 67) + LET_STMT@[67; 84) + LET_KW@[67; 70) + PLACEHOLDER_PAT@[70; 73) + WHITESPACE@[70; 71) + UNDERSCORE@[71; 72) + WHITESPACE@[72; 73) + EQ@[73; 74) + LITERAL@[74; 78) + WHITESPACE@[74; 75) + FLOAT_NUMBER@[75; 78) + SEMI@[78; 79) + WHITESPACE@[79; 84) + LET_STMT@[84; 102) + LET_KW@[84; 87) + PLACEHOLDER_PAT@[87; 90) + WHITESPACE@[87; 88) + UNDERSCORE@[88; 89) + WHITESPACE@[89; 90) + EQ@[90; 91) + LITERAL@[91; 96) + WHITESPACE@[91; 92) + BYTE@[92; 96) + SEMI@[96; 97) + WHITESPACE@[97; 102) + LET_STMT@[102; 119) + LET_KW@[102; 105) + PLACEHOLDER_PAT@[105; 108) + WHITESPACE@[105; 106) + UNDERSCORE@[106; 107) + WHITESPACE@[107; 108) + EQ@[108; 109) + LITERAL@[109; 113) + WHITESPACE@[109; 110) + CHAR@[110; 113) + SEMI@[113; 114) + WHITESPACE@[114; 119) + LET_STMT@[119; 136) + LET_KW@[119; 122) + PLACEHOLDER_PAT@[122; 125) + WHITESPACE@[122; 123) + UNDERSCORE@[123; 124) + WHITESPACE@[124; 125) + EQ@[125; 126) + LITERAL@[126; 130) + WHITESPACE@[126; 127) + STRING@[127; 130) + SEMI@[130; 131) + WHITESPACE@[131; 136) + LET_STMT@[136; 154) + LET_KW@[136; 139) + PLACEHOLDER_PAT@[139; 142) + WHITESPACE@[139; 140) + UNDERSCORE@[140; 141) + WHITESPACE@[141; 142) + EQ@[142; 143) + LITERAL@[143; 148) + WHITESPACE@[143; 144) + RAW_STRING@[144; 148) + SEMI@[148; 149) + WHITESPACE@[149; 154) + LET_STMT@[154; 172) + LET_KW@[154; 157) + PLACEHOLDER_PAT@[157; 160) + WHITESPACE@[157; 158) + UNDERSCORE@[158; 159) + WHITESPACE@[159; 160) + EQ@[160; 161) + LITERAL@[161; 166) + WHITESPACE@[161; 162) + BYTE_STRING@[162; 166) + SEMI@[166; 167) + WHITESPACE@[167; 172) + LET_STMT@[172; 187) + LET_KW@[172; 175) + PLACEHOLDER_PAT@[175; 178) + WHITESPACE@[175; 176) + UNDERSCORE@[176; 177) + WHITESPACE@[177; 178) + EQ@[178; 179) + LITERAL@[179; 185) + WHITESPACE@[179; 180) + RAW_BYTE_STRING@[180; 185) + SEMI@[185; 186) + WHITESPACE@[186; 187) + R_CURLY@[187; 188) + WHITESPACE@[188; 189)