111 lines
2.7 KiB
Rust
Raw Normal View History

//! FIXME: write short doc here
2018-01-09 23:32:18 +03:00
use super::*;
pub(super) const PATH_FIRST: TokenSet =
token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLON, L_ANGLE];
2018-01-30 22:53:19 +03:00
pub(super) fn is_path_start(p: &Parser) -> bool {
is_use_path_start(p) || p.at(T![<])
}
pub(super) fn is_use_path_start(p: &Parser) -> bool {
2018-02-11 13:13:06 +03:00
match p.current() {
IDENT | T![self] | T![super] | T![crate] => true,
T![:] if p.at(T![::]) => true,
2018-02-11 13:13:06 +03:00
_ => false,
}
2018-01-13 13:42:19 +03:00
}
2018-01-30 22:53:19 +03:00
pub(super) fn use_path(p: &mut Parser) {
2018-07-30 17:02:51 +03:00
path(p, Mode::Use)
2018-01-30 22:53:19 +03:00
}
2019-09-02 17:37:48 +03:00
pub(crate) fn type_path(p: &mut Parser) {
2018-07-30 17:02:51 +03:00
path(p, Mode::Type)
2018-01-30 22:53:19 +03:00
}
2018-07-30 17:02:51 +03:00
pub(super) fn expr_path(p: &mut Parser) {
path(p, Mode::Expr)
}
#[derive(Clone, Copy, Eq, PartialEq)]
2018-07-31 15:40:40 +03:00
enum Mode {
Use,
Type,
Expr,
}
2018-07-30 17:02:51 +03:00
fn path(p: &mut Parser, mode: Mode) {
2018-01-20 23:25:34 +03:00
let path = p.start();
2018-07-30 17:02:51 +03:00
path_segment(p, mode, true);
2018-01-20 23:25:34 +03:00
let mut qual = path.complete(p, PATH);
2018-01-20 21:49:58 +03:00
loop {
let use_tree = match p.nth(2) {
2019-05-15 15:35:47 +03:00
T![*] | T!['{'] => true,
_ => false,
};
2019-05-15 15:35:47 +03:00
if p.at(T![::]) && !use_tree {
2018-01-20 23:25:34 +03:00
let path = qual.precede(p);
p.bump(T![::]);
2018-07-30 17:02:51 +03:00
path_segment(p, mode, false);
2018-01-20 23:25:34 +03:00
let path = path.complete(p, PATH);
qual = path;
2018-01-13 13:42:19 +03:00
} else {
2018-01-20 21:49:58 +03:00
break;
2018-01-13 13:42:19 +03:00
}
2018-01-20 21:49:58 +03:00
}
2018-01-09 23:32:18 +03:00
}
2018-07-30 17:02:51 +03:00
fn path_segment(p: &mut Parser, mode: Mode, first: bool) {
2018-08-13 23:54:00 +03:00
let m = p.start();
// test qual_paths
// type X = <A as B>::Output;
// fn foo() { <usize as Default>::default(); }
2019-05-15 15:35:47 +03:00
if first && p.eat(T![<]) {
2018-08-13 23:54:00 +03:00
types::type_(p);
2019-05-15 15:35:47 +03:00
if p.eat(T![as]) {
if is_use_path_start(p) {
2018-08-13 23:54:00 +03:00
types::path_type(p);
} else {
p.error("expected a trait");
}
2018-07-31 15:40:40 +03:00
}
2019-05-15 15:35:47 +03:00
p.expect(T![>]);
2018-08-13 23:54:00 +03:00
} else {
if first {
2019-05-15 15:35:47 +03:00
p.eat(T![::]);
2018-02-09 22:55:50 +03:00
}
2018-08-13 23:54:00 +03:00
match p.current() {
IDENT => {
2019-08-09 12:16:47 +02:00
name_ref(p);
2018-08-24 02:14:10 +03:00
opt_path_type_args(p, mode);
2018-08-13 23:54:00 +03:00
}
2018-09-29 14:53:23 +03:00
// test crate_path
// use crate::foo;
2019-09-10 00:59:29 +03:00
T![self] | T![super] | T![crate] => p.bump_any(),
2018-08-13 23:54:00 +03:00
_ => {
2018-11-21 18:34:20 +03:00
p.err_recover("expected identifier", items::ITEM_RECOVERY_SET);
2018-08-13 23:54:00 +03:00
}
};
}
m.complete(p, PATH_SEGMENT);
2018-01-20 21:49:58 +03:00
}
2018-07-30 17:02:51 +03:00
2018-08-24 02:14:10 +03:00
fn opt_path_type_args(p: &mut Parser, mode: Mode) {
2018-07-30 17:02:51 +03:00
match mode {
Mode::Use => return,
2018-08-08 14:43:14 +03:00
Mode::Type => {
// test path_fn_trait_args
// type F = Box<Fn(i32) -> ()>;
2019-05-15 15:35:47 +03:00
if p.at(T!['(']) {
params::param_list_impl_fn(p);
2018-08-24 02:14:10 +03:00
opt_fn_ret_type(p);
2018-08-08 14:43:14 +03:00
} else {
2018-08-24 02:14:10 +03:00
type_args::opt_type_arg_list(p, false)
2018-08-08 14:43:14 +03:00
}
}
2018-08-24 02:14:10 +03:00
Mode::Expr => type_args::opt_type_arg_list(p, true),
2018-07-30 17:02:51 +03:00
}
}