1
Fork 0

syntax/attr: reduce reliance on parser

This commit is contained in:
Mazdak Farrokhzad 2019-10-09 13:19:15 +02:00
parent b7176b44a2
commit 16329402bf
6 changed files with 36 additions and 32 deletions

View file

@ -15,7 +15,7 @@ use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam};
use crate::mut_visit::visit_clobber;
use crate::source_map::{BytePos, Spanned};
use crate::parse::lexer::comments::doc_comment_style;
use crate::parse::parser::Parser;
use crate::parse;
use crate::parse::PResult;
use crate::parse::token::{self, Token};
use crate::ptr::P;
@ -280,35 +280,10 @@ impl Attribute {
self.item.meta(self.span)
}
crate fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let mut parser = Parser::new(
sess,
self.tokens.clone(),
None,
false,
false,
Some("attribute"),
);
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
}
Ok(result)
}
pub fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec<Path>> {
if self.tokens.is_empty() {
return Ok(Vec::new());
}
self.parse(sess, |p| p.parse_derive_paths())
}
pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
Ok(MetaItem {
path: self.path.clone(),
kind: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
kind: parse::parse_in_attr(sess, self, |p| p.parse_meta_item_kind())?,
span: self.span,
})
}

View file

@ -10,6 +10,7 @@ use crate::attr;
use crate::ast;
use crate::edition::Edition;
use crate::mut_visit::*;
use crate::parse;
use crate::ptr::P;
use crate::sess::ParseSess;
use crate::symbol::sym;
@ -112,7 +113,8 @@ impl<'a> StripUnconfigured<'a> {
return vec![];
}
let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |p| p.parse_cfg_attr()) {
let res = parse::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
let (cfg_predicate, expanded_attrs) = match res {
Ok(result) => result,
Err(mut e) => {
e.emit();

View file

@ -96,8 +96,7 @@ pub mod json;
pub mod ast;
pub mod attr;
pub mod source_map;
#[macro_use]
pub mod config;
#[macro_use] pub mod config;
pub mod entry;
pub mod feature_gate;
pub mod mut_visit;

View file

@ -288,6 +288,27 @@ pub fn stream_to_parser_with_base_dir<'a>(
Parser::new(sess, stream, Some(base_dir), true, false, None)
}
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
pub fn parse_in_attr<'a, T>(
sess: &'a ParseSess,
attr: &ast::Attribute,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, T> {
let mut parser = Parser::new(
sess,
attr.tokens.clone(),
None,
false,
false,
Some("attribute"),
);
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
}
Ok(result)
}
// NOTE(Centril): The following probably shouldn't be here but it acknowledges the
// fact that architecturally, we are using parsing (read on below to understand why).

View file

@ -130,7 +130,7 @@ impl<'a> Parser<'a> {
}
/// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`.
crate fn parse_derive_paths(&mut self) -> PResult<'a, Vec<Path>> {
pub fn parse_derive_paths(&mut self) -> PResult<'a, Vec<Path>> {
self.expect(&token::OpenDelim(token::Paren))?;
let mut list = Vec::new();
while !self.eat(&token::CloseDelim(token::Paren)) {

View file

@ -200,7 +200,14 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>)
return false;
}
match attr.parse_derive_paths(cx.parse_sess) {
let parse_derive_paths = |attr: &ast::Attribute| {
if attr.tokens.is_empty() {
return Ok(Vec::new());
}
parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths())
};
match parse_derive_paths(attr) {
Ok(traits) => {
result.extend(traits);
true