item-macros

This commit is contained in:
Aleksey Kladov 2018-08-05 14:08:46 +03:00
parent b513e94d88
commit c871022f98
7 changed files with 151 additions and 16 deletions

View file

@ -109,6 +109,8 @@ Grammar(
"TRAIT_ITEM",
"IMPL_ITEM",
"TYPE_ITEM",
"MACRO_CALL",
"TOKEN_TREE",
"PAREN_TYPE",
"TUPLE_TYPE",

View file

@ -5,27 +5,43 @@ mod structs;
mod traits;
mod use_item;
// test mod_contents
// fn foo() {}
// macro_rules! foo {}
// foo::bar!();
// super::baz! {}
// struct S;
pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
attributes::inner_attributes(p);
while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
item(p, stop_on_r_curly)
item_or_macro(p, stop_on_r_curly)
}
}
pub(super) fn item(p: &mut Parser, stop_on_r_curly: bool) {
pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool) {
let m = p.start();
match maybe_item(p) {
MaybeItem::Item(kind) => {
m.complete(p, kind);
}
MaybeItem::None => {
m.abandon(p);
if p.at(L_CURLY) {
error_block(p, "expected an item");
} else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
p.err_and_bump("expected an item");
if paths::is_path_start(p) {
match macro_call(p) {
MacroFlavor::Curly => (),
MacroFlavor::NonCurly => {
p.expect(SEMI);
}
}
m.complete(p, MACRO_CALL);
} else {
p.error("expected an item");
m.abandon(p);
if p.at(L_CURLY) {
error_block(p, "expected an item");
} else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
p.err_and_bump("expected an item");
} else {
p.error("expected an item");
}
}
}
MaybeItem::Modifiers => {
@ -260,3 +276,49 @@ fn mod_item(p: &mut Parser) {
}
}
}
enum MacroFlavor {
Curly,
NonCurly,
}
fn macro_call(p: &mut Parser) -> MacroFlavor {
assert!(paths::is_path_start(p));
paths::use_path(p);
p.expect(EXCL);
p.eat(IDENT);
let flavor = match p.current() {
L_CURLY => {
token_tree(p);
MacroFlavor::Curly
}
L_PAREN | L_BRACK => {
token_tree(p);
MacroFlavor::NonCurly
}
_ => {
p.error("expected `{`, `[`, `(`");
MacroFlavor::NonCurly
},
};
flavor
}
fn token_tree(p: &mut Parser) {
let closing_paren_kind = match p.current() {
L_CURLY => R_CURLY,
L_PAREN => R_PAREN,
L_BRACK => R_BRACK,
_ => unreachable!(),
};
p.bump();
while !p.at(EOF) && !p.at(closing_paren_kind) {
match p.current() {
L_CURLY | L_PAREN | L_BRACK => token_tree(p),
R_CURLY | R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"),
_ => p.bump()
}
};
p.expect(closing_paren_kind);
}

View file

@ -45,7 +45,7 @@ pub(super) fn impl_item(p: &mut Parser) {
// fn bar(&self) {}
// }
while !p.at(EOF) && !p.at(R_CURLY) {
item(p, true);
item_or_macro(p, true);
}
p.expect(R_CURLY);
}

View file

@ -103,6 +103,8 @@ pub enum SyntaxKind {
TRAIT_ITEM,
IMPL_ITEM,
TYPE_ITEM,
MACRO_CALL,
TOKEN_TREE,
PAREN_TYPE,
TUPLE_TYPE,
NEVER_TYPE,
@ -322,6 +324,8 @@ impl SyntaxKind {
TRAIT_ITEM => &SyntaxInfo { name: "TRAIT_ITEM" },
IMPL_ITEM => &SyntaxInfo { name: "IMPL_ITEM" },
TYPE_ITEM => &SyntaxInfo { name: "TYPE_ITEM" },
MACRO_CALL => &SyntaxInfo { name: "MACRO_CALL" },
TOKEN_TREE => &SyntaxInfo { name: "TOKEN_TREE" },
PAREN_TYPE => &SyntaxInfo { name: "PAREN_TYPE" },
TUPLE_TYPE => &SyntaxInfo { name: "TUPLE_TYPE" },
NEVER_TYPE => &SyntaxInfo { name: "NEVER_TYPE" },

View file

@ -13,15 +13,15 @@ FILE@[0; 95)
WHITESPACE@[10; 11)
R_CURLY@[11; 12)
WHITESPACE@[12; 14)
err: `expected an item`
ERROR@[14; 17)
IDENT@[14; 17) "bar"
err: `expected an item`
ERROR@[17; 18)
MACRO_CALL@[14; 20)
PATH@[14; 17)
PATH_SEGMENT@[14; 17)
NAME_REF@[14; 17)
IDENT@[14; 17) "bar"
err: `expected EXCL`
L_PAREN@[17; 18)
err: `expected an item`
ERROR@[18; 20)
R_PAREN@[18; 19)
err: `expected SEMI`
WHITESPACE@[19; 20)
err: `expected an item`
ERROR@[20; 82)

View file

@ -0,0 +1,5 @@
fn foo() {}
macro_rules! foo {}
foo::bar!();
super::baz! {}
struct S;

View file

@ -0,0 +1,62 @@
FILE@[0; 70)
FN_ITEM@[0; 12)
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_EXPR@[9; 12)
L_CURLY@[9; 10)
R_CURLY@[10; 11)
WHITESPACE@[11; 12)
MACRO_CALL@[12; 32)
PATH@[12; 23)
PATH_SEGMENT@[12; 23)
NAME_REF@[12; 23)
IDENT@[12; 23) "macro_rules"
EXCL@[23; 24)
WHITESPACE@[24; 25)
IDENT@[25; 28) "foo"
WHITESPACE@[28; 29)
L_CURLY@[29; 30)
R_CURLY@[30; 31)
WHITESPACE@[31; 32)
MACRO_CALL@[32; 45)
PATH@[32; 40)
PATH@[32; 35)
PATH_SEGMENT@[32; 35)
NAME_REF@[32; 35)
IDENT@[32; 35) "foo"
COLONCOLON@[35; 37)
PATH_SEGMENT@[37; 40)
NAME_REF@[37; 40)
IDENT@[37; 40) "bar"
EXCL@[40; 41)
L_PAREN@[41; 42)
R_PAREN@[42; 43)
SEMI@[43; 44)
WHITESPACE@[44; 45)
MACRO_CALL@[45; 60)
PATH@[45; 55)
PATH@[45; 50)
PATH_SEGMENT@[45; 50)
SUPER_KW@[45; 50)
COLONCOLON@[50; 52)
PATH_SEGMENT@[52; 55)
NAME_REF@[52; 55)
IDENT@[52; 55) "baz"
EXCL@[55; 56)
WHITESPACE@[56; 57)
L_CURLY@[57; 58)
R_CURLY@[58; 59)
WHITESPACE@[59; 60)
STRUCT_ITEM@[60; 70)
STRUCT_KW@[60; 66)
NAME@[66; 68)
WHITESPACE@[66; 67)
IDENT@[67; 68) "S"
SEMI@[68; 69)
WHITESPACE@[69; 70)