2018-01-07 12:46:10 -06:00
|
|
|
use super::*;
|
|
|
|
|
2018-01-09 13:35:55 -06:00
|
|
|
pub(super) fn mod_contents(p: &mut Parser) {
|
|
|
|
attributes::inner_attributes(p);
|
2018-01-08 12:57:19 -06:00
|
|
|
many(p, |p| {
|
|
|
|
skip_to_first(
|
2018-01-09 13:35:55 -06:00
|
|
|
p, item_first, mod_contents_item,
|
2018-01-08 12:57:19 -06:00
|
|
|
"expected item",
|
|
|
|
)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn item_first(p: &Parser) -> bool {
|
2018-01-07 12:46:10 -06:00
|
|
|
match p.current() {
|
2018-01-12 13:05:46 -06:00
|
|
|
STRUCT_KW | FN_KW | EXTERN_KW | MOD_KW | USE_KW | POUND | PUB_KW => true,
|
2018-01-07 12:46:10 -06:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-09 13:35:55 -06:00
|
|
|
fn mod_contents_item(p: &mut Parser) {
|
2018-01-08 12:57:19 -06:00
|
|
|
if item(p) {
|
|
|
|
if p.current() == SEMI {
|
|
|
|
node(p, ERROR, |p| {
|
|
|
|
p.error()
|
|
|
|
.message("expected item, found `;`\n\
|
|
|
|
consider removing this semicolon")
|
|
|
|
.emit();
|
|
|
|
p.bump();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn item(p: &mut Parser) -> bool {
|
2018-01-12 11:32:37 -06:00
|
|
|
let attrs_start = p.mark();
|
2018-01-07 12:46:10 -06:00
|
|
|
attributes::outer_attributes(p);
|
|
|
|
visibility(p);
|
2018-01-08 13:20:58 -06:00
|
|
|
// node_if(p, USE_KW, USE_ITEM, use_item)
|
|
|
|
// || extern crate_fn
|
|
|
|
// || node_if(p, STATIC_KW, STATIC_ITEM, static_item)
|
|
|
|
// || node_if(p, CONST_KW, CONST_ITEM, const_item) or const FN!
|
|
|
|
// || unsafe trait, impl
|
|
|
|
// || node_if(p, FN_KW, FN_ITEM, fn_item)
|
|
|
|
// || node_if(p, TYPE_KW, TYPE_ITEM, type_item)
|
2018-01-12 11:32:37 -06:00
|
|
|
let item_start = p.mark();
|
|
|
|
let item_parsed = node_if(p, [EXTERN_KW, CRATE_KW], EXTERN_CRATE_ITEM, extern_crate_item)
|
2018-01-09 13:35:55 -06:00
|
|
|
|| node_if(p, MOD_KW, MOD_ITEM, mod_item)
|
2018-01-09 14:32:18 -06:00
|
|
|
|| node_if(p, USE_KW, USE_ITEM, use_item)
|
2018-01-08 15:06:42 -06:00
|
|
|
|| node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item)
|
2018-01-12 11:32:37 -06:00
|
|
|
|| node_if(p, FN_KW, FN_ITEM, fn_item);
|
|
|
|
|
|
|
|
if item_parsed && attrs_start != item_start {
|
|
|
|
p.forward_parent(attrs_start, item_start);
|
|
|
|
}
|
|
|
|
item_parsed
|
2018-01-07 12:46:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn struct_item(p: &mut Parser) {
|
|
|
|
p.expect(IDENT)
|
|
|
|
&& p.curly_block(|p| comma_list(p, EOF, struct_field));
|
|
|
|
}
|
|
|
|
|
2018-01-08 15:06:42 -06:00
|
|
|
fn extern_crate_item(p: &mut Parser) {
|
|
|
|
p.expect(IDENT) && alias(p) && p.expect(SEMI);
|
|
|
|
}
|
|
|
|
|
2018-01-09 13:35:55 -06:00
|
|
|
fn mod_item(p: &mut Parser) {
|
|
|
|
if !p.expect(IDENT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if p.eat(SEMI) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p.curly_block(mod_contents);
|
|
|
|
}
|
|
|
|
|
2018-01-13 04:42:19 -06:00
|
|
|
pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool {
|
|
|
|
kind == STAR || kind == L_CURLY
|
|
|
|
}
|
|
|
|
|
2018-01-09 14:32:18 -06:00
|
|
|
fn use_item(p: &mut Parser) {
|
2018-01-13 04:42:19 -06:00
|
|
|
use_tree(p);
|
2018-01-09 14:32:18 -06:00
|
|
|
p.expect(SEMI);
|
2018-01-13 04:42:19 -06:00
|
|
|
|
|
|
|
fn use_tree(p: &mut Parser) -> bool{
|
|
|
|
if node_if(p, STAR, USE_TREE, |_| ()) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if node_if(p, [COLONCOLON, STAR], USE_TREE, |_| ()) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if [COLONCOLON, L_CURLY].is_ahead(p) || L_CURLY.is_ahead(p) {
|
|
|
|
node(p, USE_TREE, |p| {
|
|
|
|
p.eat(COLONCOLON);
|
|
|
|
p.curly_block(|p| {
|
|
|
|
comma_list(p, EOF, use_tree);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if paths::is_path_start(p) {
|
|
|
|
node(p, USE_TREE, |p| {
|
|
|
|
paths::use_path(p);
|
|
|
|
match p.current() {
|
|
|
|
AS_KW => {
|
|
|
|
alias(p);
|
|
|
|
}
|
|
|
|
COLONCOLON => {
|
|
|
|
p.bump();
|
|
|
|
match p.current() {
|
|
|
|
STAR => {
|
|
|
|
p.bump();
|
|
|
|
}
|
|
|
|
L_CURLY => {
|
|
|
|
p.curly_block(|p| {
|
|
|
|
comma_list(p, EOF, use_tree);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// is this unreachable?
|
|
|
|
p.error()
|
|
|
|
.message("expected `{` or `*`")
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
2018-01-09 14:32:18 -06:00
|
|
|
}
|
|
|
|
|
2018-01-07 12:46:10 -06:00
|
|
|
fn struct_field(p: &mut Parser) -> bool {
|
|
|
|
node_if(p, IDENT, STRUCT_FIELD, |p| {
|
|
|
|
p.expect(COLON) && p.expect(IDENT);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_item(p: &mut Parser) {
|
|
|
|
p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN)
|
2018-01-08 13:40:14 -06:00
|
|
|
&& p.curly_block(|_| ());
|
2018-01-07 12:46:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|