2018-01-07 12:46:10 -06:00
|
|
|
use super::*;
|
|
|
|
|
2018-01-20 12:49:58 -06:00
|
|
|
#[derive(PartialEq, Eq)]
|
2018-01-11 14:01:12 -06:00
|
|
|
enum AttrKind {
|
|
|
|
Inner, Outer
|
|
|
|
}
|
|
|
|
|
2018-01-07 12:46:10 -06:00
|
|
|
pub(super) fn inner_attributes(p: &mut Parser) {
|
2018-01-15 12:44:30 -06:00
|
|
|
repeat(p, |p| attribute(p, AttrKind::Inner))
|
2018-01-07 12:46:10 -06:00
|
|
|
}
|
|
|
|
|
2018-01-11 14:01:12 -06:00
|
|
|
pub(super) fn outer_attributes(p: &mut Parser) {
|
2018-01-15 12:44:30 -06:00
|
|
|
repeat(p, |p| attribute(p, AttrKind::Outer))
|
2018-01-07 12:46:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-11 14:01:12 -06:00
|
|
|
fn attribute(p: &mut Parser, kind: AttrKind) -> bool {
|
2018-01-20 12:49:58 -06:00
|
|
|
if p.at(POUND) {
|
|
|
|
if kind == AttrKind::Inner && p.raw_lookahead(1) != EXCL {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
p.start(ATTR);
|
|
|
|
p.bump();
|
|
|
|
if kind == AttrKind::Inner {
|
|
|
|
p.bump();
|
|
|
|
}
|
|
|
|
p.expect(L_BRACK) && meta_item(p) && p.expect(R_BRACK);
|
|
|
|
p.finish();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
2018-01-08 13:40:14 -06:00
|
|
|
}
|
2018-01-07 12:46:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn meta_item(p: &mut Parser) -> bool {
|
2018-01-20 12:49:58 -06:00
|
|
|
if p.at(IDENT) {
|
|
|
|
p.start(META_ITEM);
|
|
|
|
p.bump();
|
2018-01-07 12:46:10 -06:00
|
|
|
if p.eat(EQ) {
|
|
|
|
if !expressions::literal(p) {
|
|
|
|
p.error()
|
|
|
|
.message("expected literal")
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
} else if p.eat(L_PAREN) {
|
|
|
|
comma_list(p, R_PAREN, meta_item_inner);
|
|
|
|
p.expect(R_PAREN);
|
|
|
|
}
|
2018-01-20 12:49:58 -06:00
|
|
|
p.finish();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2018-01-07 12:46:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn meta_item_inner(p: &mut Parser) -> bool {
|
|
|
|
meta_item(p) || expressions::literal(p)
|
|
|
|
}
|
|
|
|
|