mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Remove high-order bits from attributes
This commit is contained in:
parent
0b5d39f2a2
commit
efd538d793
5 changed files with 102 additions and 44 deletions
|
@ -1,60 +1,84 @@
|
|||
use super::*;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum AttrKind {
|
||||
Inner, Outer
|
||||
}
|
||||
|
||||
pub(super) fn inner_attributes(p: &mut Parser) {
|
||||
repeat(p, |p| attribute(p, AttrKind::Inner))
|
||||
while p.at([POUND, EXCL]) {
|
||||
attribute(p, true)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn outer_attributes(p: &mut Parser) {
|
||||
repeat(p, |p| attribute(p, AttrKind::Outer))
|
||||
}
|
||||
|
||||
|
||||
fn attribute(p: &mut Parser, kind: AttrKind) -> bool {
|
||||
if p.at(POUND) {
|
||||
if kind == AttrKind::Inner && p.raw_lookahead(1) != EXCL {
|
||||
return false;
|
||||
}
|
||||
let attr = p.start();
|
||||
p.bump();
|
||||
if kind == AttrKind::Inner {
|
||||
p.bump();
|
||||
}
|
||||
p.expect(L_BRACK) && meta_item(p) && p.expect(R_BRACK);
|
||||
attr.complete(p, ATTR);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
while p.at(POUND) {
|
||||
attribute(p, false)
|
||||
}
|
||||
}
|
||||
|
||||
fn meta_item(p: &mut Parser) -> bool {
|
||||
|
||||
fn attribute(p: &mut Parser, inner: bool){
|
||||
let attr = p.start();
|
||||
assert!(p.at(POUND));
|
||||
p.bump();
|
||||
|
||||
if inner {
|
||||
assert!(p.at(EXCL));
|
||||
p.bump();
|
||||
}
|
||||
|
||||
if p.expect(L_BRACK) {
|
||||
meta_item(p);
|
||||
p.expect(R_BRACK);
|
||||
}
|
||||
attr.complete(p, ATTR);
|
||||
}
|
||||
|
||||
fn meta_item(p: &mut Parser) {
|
||||
if p.at(IDENT) {
|
||||
let meta_item = p.start();
|
||||
p.bump();
|
||||
if p.eat(EQ) {
|
||||
if !expressions::literal(p) {
|
||||
p.error()
|
||||
.message("expected literal")
|
||||
.emit();
|
||||
match p.current() {
|
||||
EQ => {
|
||||
p.bump();
|
||||
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);
|
||||
L_PAREN => meta_item_arg_list(p),
|
||||
_ => (),
|
||||
}
|
||||
meta_item.complete(p, META_ITEM);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
p.error()
|
||||
.message("expected attribute value")
|
||||
.emit()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn meta_item_inner(p: &mut Parser) -> bool {
|
||||
meta_item(p) || expressions::literal(p)
|
||||
}
|
||||
fn meta_item_arg_list(p: &mut Parser) {
|
||||
assert!(p.at(L_PAREN));
|
||||
p.bump();
|
||||
loop {
|
||||
match p.current() {
|
||||
EOF | R_PAREN => break,
|
||||
IDENT => meta_item(p),
|
||||
c => if !expressions::literal(p) {
|
||||
let message = "expected attribute";
|
||||
|
||||
if items::ITEM_FIRST.contains(c) {
|
||||
p.error().message(message).emit();
|
||||
return;
|
||||
}
|
||||
|
||||
let err = p.start();
|
||||
p.error().message(message).emit();
|
||||
p.bump();
|
||||
err.complete(p, ERROR);
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !p.at(R_PAREN) {
|
||||
p.expect(COMMA);
|
||||
}
|
||||
}
|
||||
p.expect(R_PAREN);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,16 @@ pub(super) fn mod_contents(p: &mut Parser) {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) const ITEM_FIRST: TokenSet = token_set![
|
||||
EXTERN_KW,
|
||||
MOD_KW,
|
||||
USE_KW,
|
||||
STRUCT_KW,
|
||||
FN_KW,
|
||||
PUB_KW,
|
||||
POUND,
|
||||
];
|
||||
|
||||
fn item(p: &mut Parser) {
|
||||
let item = p.start();
|
||||
attributes::outer_attributes(p);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::parser::Parser;
|
||||
use super::parser::{Parser, TokenSet};
|
||||
use {SyntaxKind};
|
||||
use tree::EOF;
|
||||
use syntax_kinds::*;
|
||||
|
@ -80,8 +80,8 @@ fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F)
|
|||
|
||||
|
||||
impl<'p> Parser<'p> {
|
||||
fn at(&self, kind: SyntaxKind) -> bool {
|
||||
self.current() == kind
|
||||
fn at<L: Lookahead>(&self, l: L) -> bool {
|
||||
l.is_ahead(self)
|
||||
}
|
||||
|
||||
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use {Token, SyntaxKind};
|
||||
|
||||
mod grammar;
|
||||
#[macro_use]
|
||||
mod parser;
|
||||
mod grammar;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Event {
|
||||
|
|
|
@ -67,6 +67,29 @@ impl CompleteMarker {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TokenSet {
|
||||
pub tokens: &'static [SyntaxKind]
|
||||
}
|
||||
|
||||
impl TokenSet {
|
||||
pub fn contains(&self, kind: SyntaxKind) -> bool {
|
||||
self.tokens.contains(&kind)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! token_set {
|
||||
($($t:ident),*) => {
|
||||
TokenSet {
|
||||
tokens: &[$($t),*],
|
||||
}
|
||||
};
|
||||
|
||||
($($t:ident),* ,) => {
|
||||
token_set!($($t),*)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
pub(crate) struct Parser<'t> {
|
||||
#[allow(unused)]
|
||||
|
|
Loading…
Reference in a new issue