Path expressions

This commit is contained in:
Aleksey Kladov 2018-07-30 17:02:51 +03:00
parent 69c385e810
commit d436694097
10 changed files with 320 additions and 17 deletions

View file

@ -120,6 +120,7 @@ Grammar(
"PLACEHOLDER_PAT", "PLACEHOLDER_PAT",
"TUPLE_EXPR", "TUPLE_EXPR",
"PATH_EXPR",
"EXTERN_BLOCK", "EXTERN_BLOCK",
"ENUM_VARIANT", "ENUM_VARIANT",
@ -133,15 +134,18 @@ Grammar(
"LITERAL", "LITERAL",
"ALIAS", "ALIAS",
"VISIBILITY", "VISIBILITY",
"TYPE_PARAM_LIST",
"WHERE_CLAUSE", "WHERE_CLAUSE",
"LIFETIME_PARAM",
"TYPE_PARAM",
"ABI", "ABI",
"NAME", "NAME",
"NAME_REF", "NAME_REF",
"VALUE_PARAMETER", "VALUE_PARAMETER",
"BLOCK", "BLOCK",
"LET_STMT", "LET_STMT",
"TYPE_PARAM",
"LIFETIME_PARAM",
"TYPE_PARAM_LIST",
"TYPE_ARG_LIST",
] ]
) )

View file

@ -2,7 +2,16 @@ use super::*;
// test expr_literals // test expr_literals
// fn foo() { // 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 { pub(super) fn literal(p: &mut Parser) -> bool {
match p.current() { match p.current() {
@ -21,6 +30,9 @@ pub(super) fn expr(p: &mut Parser) {
if literal(p) { if literal(p) {
return; return;
} }
if paths::is_path_start(p) {
return path_expr(p);
}
match p.current() { match p.current() {
L_PAREN => tuple_expr(p), L_PAREN => tuple_expr(p),
@ -35,3 +47,16 @@ fn tuple_expr(p: &mut Parser) {
p.expect(R_PAREN); p.expect(R_PAREN);
m.complete(p, TUPLE_EXPR); m.complete(p, TUPLE_EXPR);
} }
// test path_expr
// fn foo() {
// let _ = a;
// let _ = a::b;
// let _ = ::a::<b>;
// }
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);
}

View file

@ -27,6 +27,7 @@ mod items;
mod paths; mod paths;
mod patterns; mod patterns;
mod type_params; mod type_params;
mod type_args;
mod types; mod types;
use { use {

View file

@ -8,19 +8,26 @@ pub(super) fn is_path_start(p: &Parser) -> bool {
} }
pub(super) fn use_path(p: &mut Parser) { pub(super) fn use_path(p: &mut Parser) {
path(p) path(p, Mode::Use)
} }
pub(super) fn type_path(p: &mut Parser) { 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) { if !is_path_start(p) {
return; return;
} }
let path = p.start(); let path = p.start();
path_segment(p, true); path_segment(p, mode, true);
let mut qual = path.complete(p, PATH); let mut qual = path.complete(p, PATH);
loop { loop {
let use_tree = match p.nth(1) { let use_tree = match p.nth(1) {
@ -30,7 +37,7 @@ fn path(p: &mut Parser) {
if p.at(COLONCOLON) && !use_tree { if p.at(COLONCOLON) && !use_tree {
let path = qual.precede(p); let path = qual.precede(p);
p.bump(); p.bump();
path_segment(p, false); path_segment(p, mode, false);
let path = path.complete(p, PATH); let path = path.complete(p, PATH);
qual = path; qual = path;
} else { } 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(); let segment = p.start();
if first { if first {
p.eat(COLONCOLON); p.eat(COLONCOLON);
} }
match p.current() { match p.current() {
IDENT => name_ref(p), IDENT => {
name_ref(p);
path_generic_args(p, mode);
},
SELF_KW | SUPER_KW => p.bump(), SELF_KW | SUPER_KW => p.bump(),
_ => { _ => {
p.error("expected identifier"); p.error("expected identifier");
@ -53,3 +63,11 @@ fn path_segment(p: &mut Parser, first: bool) {
}; };
segment.complete(p, PATH_SEGMENT); 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),
}
}

View file

@ -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);
}

View file

@ -115,6 +115,7 @@ pub enum SyntaxKind {
BIND_PAT, BIND_PAT,
PLACEHOLDER_PAT, PLACEHOLDER_PAT,
TUPLE_EXPR, TUPLE_EXPR,
PATH_EXPR,
EXTERN_BLOCK, EXTERN_BLOCK,
ENUM_VARIANT, ENUM_VARIANT,
NAMED_FIELD, NAMED_FIELD,
@ -127,16 +128,17 @@ pub enum SyntaxKind {
LITERAL, LITERAL,
ALIAS, ALIAS,
VISIBILITY, VISIBILITY,
TYPE_PARAM_LIST,
WHERE_CLAUSE, WHERE_CLAUSE,
LIFETIME_PARAM,
TYPE_PARAM,
ABI, ABI,
NAME, NAME,
NAME_REF, NAME_REF,
VALUE_PARAMETER, VALUE_PARAMETER,
BLOCK, BLOCK,
LET_STMT, LET_STMT,
TYPE_PARAM,
LIFETIME_PARAM,
TYPE_PARAM_LIST,
TYPE_ARG_LIST,
// Technical SyntaxKinds: they appear temporally during parsing, // Technical SyntaxKinds: they appear temporally during parsing,
// but never end up in the final tree // but never end up in the final tree
#[doc(hidden)] #[doc(hidden)]
@ -259,6 +261,7 @@ impl SyntaxKind {
BIND_PAT => &SyntaxInfo { name: "BIND_PAT" }, BIND_PAT => &SyntaxInfo { name: "BIND_PAT" },
PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" }, PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" },
TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" },
EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" }, EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" },
ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
@ -271,16 +274,17 @@ impl SyntaxKind {
LITERAL => &SyntaxInfo { name: "LITERAL" }, LITERAL => &SyntaxInfo { name: "LITERAL" },
ALIAS => &SyntaxInfo { name: "ALIAS" }, ALIAS => &SyntaxInfo { name: "ALIAS" },
VISIBILITY => &SyntaxInfo { name: "VISIBILITY" }, VISIBILITY => &SyntaxInfo { name: "VISIBILITY" },
TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" },
WHERE_CLAUSE => &SyntaxInfo { name: "WHERE_CLAUSE" }, WHERE_CLAUSE => &SyntaxInfo { name: "WHERE_CLAUSE" },
LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" },
TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" },
ABI => &SyntaxInfo { name: "ABI" }, ABI => &SyntaxInfo { name: "ABI" },
NAME => &SyntaxInfo { name: "NAME" }, NAME => &SyntaxInfo { name: "NAME" },
NAME_REF => &SyntaxInfo { name: "NAME_REF" }, NAME_REF => &SyntaxInfo { name: "NAME_REF" },
VALUE_PARAMETER => &SyntaxInfo { name: "VALUE_PARAMETER" }, VALUE_PARAMETER => &SyntaxInfo { name: "VALUE_PARAMETER" },
BLOCK => &SyntaxInfo { name: "BLOCK" }, BLOCK => &SyntaxInfo { name: "BLOCK" },
LET_STMT => &SyntaxInfo { name: "LET_STMT" }, 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" }, TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" },
EOF => &SyntaxInfo { name: "EOF" }, EOF => &SyntaxInfo { name: "EOF" },

View file

@ -0,0 +1,5 @@
fn foo() {
let _ = a;
let _ = a::b;
let _ = ::a::<b>;
}

View file

@ -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)

View file

@ -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";
}

View file

@ -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)